From 792c182a779229412bc86b35181d20b47b133c41 Mon Sep 17 00:00:00 2001 From: Ay1man2 Date: Mon, 25 Mar 2024 12:29:12 -0700 Subject: [PATCH 01/17] Issue 1725: Classic Gateway Filter (#1742) * shifted classicGatewayFilter to new folder and file, added unit test * prettier formatting + removed console logs * typo in pysdocs * function name change --- .../pages/diagrams/ClassicGateways.js | 19 +-- client/src/lib/forms/diagrams/filters.js | 29 ++++ client/src/lib/forms/diagrams/index.js | 2 + client/src/lib/forms/index.js | 2 + client/src/lib/index.js | 2 + unit-tests/forms/diagrams/filters.test.js | 132 ++++++++++++++++++ 6 files changed, 169 insertions(+), 17 deletions(-) create mode 100644 client/src/lib/forms/diagrams/filters.js create mode 100644 unit-tests/forms/diagrams/filters.test.js diff --git a/client/src/components/pages/diagrams/ClassicGateways.js b/client/src/components/pages/diagrams/ClassicGateways.js index af8753d4..701f979a 100644 --- a/client/src/components/pages/diagrams/ClassicGateways.js +++ b/client/src/components/pages/diagrams/ClassicGateways.js @@ -3,25 +3,10 @@ import { PowerSubnetInnerBox } from "./PowerSubnetInnerBox"; import { FirewallClassic } from "@carbon/icons-react"; import { DeploymentIcon } from "./DeploymentIcon"; import HoverClassNameWrapper from "./HoverClassNameWrapper"; +import { classicGatewaysFilter } from "../../../lib"; export const ClassicGateways = (props) => { - let gateways = []; - props.craig.store.json.classic_gateways.forEach((gw, gwIndex) => { - if (gw.private_vlan === props.vlan || gw.public_vlan === props.vlan) { - let copyGw = { ...gw }; - copyGw.index = gwIndex; - if (gw.hadr) { - copyGw.name += "-1"; - } - gateways.push(copyGw); - if (gw.hadr) { - let hadrCopy = { ...gw }; - hadrCopy.name += "-2"; - hadrCopy.index = gwIndex; - gateways.push(hadrCopy); - } - } - }); + let gateways = classicGatewaysFilter(props); return gateways.length === 0 ? ( "" ) : ( diff --git a/client/src/lib/forms/diagrams/filters.js b/client/src/lib/forms/diagrams/filters.js new file mode 100644 index 00000000..bfae3fa8 --- /dev/null +++ b/client/src/lib/forms/diagrams/filters.js @@ -0,0 +1,29 @@ +/** + * filter classic gateways + * @param {*} props + * @returns {Object} list of filterd gateways + */ +function classicGatewaysFilter(props) { + let gateways = []; + props.craig.store.json.classic_gateways.forEach((gw, gwIndex) => { + if (gw.private_vlan === props.vlan || gw.public_vlan === props.vlan) { + let copyGw = { ...gw }; + copyGw.index = gwIndex; + if (gw.hadr) { + copyGw.name += "-1"; + } + gateways.push(copyGw); + if (gw.hadr) { + let hadrCopy = { ...gw }; + hadrCopy.name += "-2"; + hadrCopy.index = gwIndex; + gateways.push(hadrCopy); + } + } + }); + return gateways; +} + +module.exports = { + classicGatewaysFilter, +}; diff --git a/client/src/lib/forms/diagrams/index.js b/client/src/lib/forms/diagrams/index.js index 03bb20dd..5ec5685f 100644 --- a/client/src/lib/forms/diagrams/index.js +++ b/client/src/lib/forms/diagrams/index.js @@ -1,8 +1,10 @@ +const { classicGatewaysFilter } = require("./filters"); const { getDisplayTierSubnetList } = require("./subnet-row"); const { shouldDisplayService } = require("./subnet-service-map"); const { getDisplaySubnetTiers } = require("./subnet-tier-map"); module.exports = { + classicGatewaysFilter, getDisplayTierSubnetList, getDisplaySubnetTiers, shouldDisplayService, diff --git a/client/src/lib/forms/index.js b/client/src/lib/forms/index.js index 371e22e4..3bd2e251 100644 --- a/client/src/lib/forms/index.js +++ b/client/src/lib/forms/index.js @@ -33,6 +33,7 @@ const { leftNavItemClassName } = require("./class-names"); const { notificationText } = require("./utils"); const wizard = require("./wizard"); const { + classicGatewaysFilter, getDisplaySubnetTiers, getDisplayTierSubnetList, shouldDisplayService, @@ -105,4 +106,5 @@ module.exports = { invalidCidrBlock, invalidProjectNameText, invalidCrns, + classicGatewaysFilter, }; diff --git a/client/src/lib/index.js b/client/src/lib/index.js index a7c7be16..3d6bb596 100644 --- a/client/src/lib/index.js +++ b/client/src/lib/index.js @@ -23,6 +23,7 @@ const { invalidCrnList, invalidCrns, wizard, + classicGatewaysFilter, getDisplaySubnetTiers, getDisplayTierSubnetList, shouldDisplayService, @@ -271,4 +272,5 @@ module.exports = { invalidCrns, powerVsTf, getDisplayTierSubnetList, + classicGatewaysFilter, }; diff --git a/unit-tests/forms/diagrams/filters.test.js b/unit-tests/forms/diagrams/filters.test.js new file mode 100644 index 00000000..fb6cb745 --- /dev/null +++ b/unit-tests/forms/diagrams/filters.test.js @@ -0,0 +1,132 @@ +const { assert } = require("chai"); +const { classicGatewaysFilter, state } = require("../../../client/src/lib"); + +function newState() { + let store = new state(); + store.setUpdateCallback(() => {}); + return store; +} + +describe("filter functions", () => { + describe("classicGatewaysFilter", () => { + let craig; + beforeEach(() => { + craig = newState(); + craig.store.json.classic_vlans[0] = { + name: "classic-priv-vlan", + datacenter: "dal10", + type: "PRIVATE", + }; + craig.store.json.classic_vlans[1] = { + name: "classic-pub-vlan", + datacenter: "dal10", + type: "PUBLIC", + }; + }); + it("should return a list of filtered classic gateways for a non-HADR gateway with a private vlan only", () => { + craig.store.json.classic_gateways[0] = { + name: "test-gw", + datacenter: "dal10", + hadr: false, + private_vlan: "classic-priv-vlan", + }; + let actualData = classicGatewaysFilter({ + craig: craig, + datacenter: "dal10", + vlan: craig.store.json.classic_vlans[0].name, + }); + assert.deepEqual( + actualData, + [ + { + name: "test-gw", + datacenter: "dal10", + hadr: false, + index: 0, + private_vlan: "classic-priv-vlan", + }, + ], + "it should return list of filtered classic gateways" + ); + }); + it("should return a list of filtered classic gateways for a non-HADR gateway with a private and public vlan", () => { + craig.store.json.classic_gateways[0] = { + name: "test-gw", + datacenter: "dal10", + hadr: false, + private_vlan: "classic-priv-vlan", + public_vlan: "classic-pub-vlan", + }; + let actualData = classicGatewaysFilter({ + craig: craig, + datacenter: "dal10", + vlan: craig.store.json.classic_vlans[1].name, + }); + assert.deepEqual( + actualData, + [ + { + name: "test-gw", + datacenter: "dal10", + hadr: false, + index: 0, + private_vlan: "classic-priv-vlan", + public_vlan: "classic-pub-vlan", + }, + ], + "it should return list of filtered classic gateways" + ); + }); + it("should return a list of filtered classic gateways for a HADR gateway", () => { + craig.store.json.classic_gateways[0] = { + name: "test-gw", + datacenter: "dal10", + hadr: true, + private_vlan: "classic-priv-vlan", + }; + let actualData = classicGatewaysFilter({ + craig: craig, + datacenter: "dal10", + vlan: craig.store.json.classic_vlans[0].name, + }); + assert.deepEqual( + actualData, + [ + { + name: "test-gw-1", + datacenter: "dal10", + hadr: true, + index: 0, + private_vlan: "classic-priv-vlan", + }, + { + name: "test-gw-2", + datacenter: "dal10", + hadr: true, + index: 0, + private_vlan: "classic-priv-vlan", + }, + ], + "it should return list of filtered classic gateways" + ); + }); + it("should return an empty list if no vlans provided in props", () => { + craig.store.json.classic_gateways[0] = { + name: "test-gw", + datacenter: "dal10", + hadr: false, + private_vlan: "classic-priv-vlan", + public_vlan: "classic-pub-vlan", + }; + let actualData = classicGatewaysFilter({ + craig: craig, + datacenter: "dal10", + }); + assert.deepEqual( + actualData, + [], + "it should return list of filtered classic gateways" + ); + }); + }); +}); From b4d91a9a524ac075a96d6138992cd72ef1ee0b3c Mon Sep 17 00:00:00 2001 From: Pseusco Date: Tue, 26 Mar 2024 09:04:40 -0400 Subject: [PATCH 02/17] Issue 1696: Reset VSI Image, and Power Instance, Power Volume, and Falconstor VTL Storage Tier and Storage Pool on zone change (#1741) * append replication enabled to pool name Signed-off-by: Lucas Franke * remove log Signed-off-by: Lucas Franke * remove replication enabled tag in tf Signed-off-by: Lucas-Franke * replication tag also removed in tf for power instances Signed-off-by: Lucas-Franke * power volume and instance Signed-off-by: Lucas-Franke * pretty Signed-off-by: Lucas-Franke * vtl and don't remove storage pool and tier from different workspace Signed-off-by: Lucas-Franke * don't use deepequal in save function Signed-off-by: Lucas-Franke --------- Signed-off-by: Lucas Franke Signed-off-by: Lucas-Franke Co-authored-by: Lucas Franke --- CHANGELOG.md | 2 + client/src/lib/docs/release-notes.json | 4 +- client/src/lib/state/options.js | 8 + client/src/lib/state/power-vs/power-vs.js | 20 ++ unit-tests/state/power-vs.test.js | 234 +++++++++++++++++++++- 5 files changed, 266 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 016af664..d93c967e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ All notable changes to this project will be documented in this file. - `.env.example` has been updated to include a warning that included quotation marks in .env values will cause the application to crash - When fetching VSI Images, the Craig API has no limit on the number of images that can be retrieved. In addition, only available images are retrieved - Power VS Network interface outputs now use the Terraform field `pi_network_name` instead of the depricated field `name` +- When updating a project's region, VSI images are now reset to ensure that images are available in the selected region +- When updating a Power VS workspace availability zone, storage tiers and storage pools are now reset for Power VS Instances, Volumes, and FalconStor VTLs ### Features diff --git a/client/src/lib/docs/release-notes.json b/client/src/lib/docs/release-notes.json index 3caf6f8e..48cfff9e 100644 --- a/client/src/lib/docs/release-notes.json +++ b/client/src/lib/docs/release-notes.json @@ -16,7 +16,9 @@ "The CRAIG JSON schema is now configured dynamically using the state store on the `/docs/json` page. Additional fields will now be added automatically", "`.env.example` has been updated to include a warning that included quotation marks in .env values will cause the application to crash", "When fetching VSI Images, the Craig API has no limit on the number of images that can be retrieved. In addition, only available images are retrieved", - "Power VS Network interface outputs now use the Terraform field `pi_network_name` instead of the depricated field `name`" + "Power VS Network interface outputs now use the Terraform field `pi_network_name` instead of the depricated field `name`", + "When updating a project's region, VSI images are now reset to ensure that images are available in the selected region", + "When updating a Power VS workspace availability zone, storage tiers and storage pools are now reset for Power VS Instances, Volumes, and FalconStor VTLs" ] }, { diff --git a/client/src/lib/state/options.js b/client/src/lib/state/options.js index a6fa5caa..edec2a97 100644 --- a/client/src/lib/state/options.js +++ b/client/src/lib/state/options.js @@ -5,6 +5,7 @@ const { buildNumberDropdownList, titleCase, contains, + deepEqual, } = require("lazy-z"); const { subnetTierSave } = require("./vpc/vpc"); const { RegexButWithWords } = require("regex-but-with-words"); @@ -71,6 +72,13 @@ function optionsInit(config) { * @param {object} componentProps props from component form */ function optionsSave(config, stateData, componentProps) { + // on region change, set vsi image and image_name to null + if (componentProps.data.region !== stateData.region) { + config.store.json.vsi.forEach((deployment) => { + deployment.image = ""; + deployment.image_name = ""; + }); + } if (componentProps.data.dynamic_subnets && !stateData.dynamic_subnets) { config.store.json.vpcs.forEach((vpc) => { vpc.address_prefixes = []; diff --git a/client/src/lib/state/power-vs/power-vs.js b/client/src/lib/state/power-vs/power-vs.js index 5b27ddb3..0216b60e 100644 --- a/client/src/lib/state/power-vs/power-vs.js +++ b/client/src/lib/state/power-vs/power-vs.js @@ -10,6 +10,7 @@ const { getObjectFromArray, contains, splat, + deepEqual, } = require("lazy-z"); const { edgeRouterEnabledZones } = require("../../constants"); const { shouldDisableComponentSave, sshKeySchema } = require("../utils"); @@ -135,6 +136,25 @@ function powerVsSave(config, stateData, componentProps) { } }); }); + // if state zone and props zone are different + // go through power volumes and reset storage_pool (and tier as well) + // go through power instances and vtl and do the same thing + if (componentProps.data.zone !== stateData.zone) { + config.store.json.power_volumes.forEach((volume) => { + if (volume.workspace === componentProps.data.name) { + volume.pi_volume_pool = ""; + volume.pi_volume_type = ""; + } + }); + ["power_instances", "vtl"].forEach((field) => { + config.store.json[field].forEach((instance) => { + if (instance.workspace === componentProps.data.name) { + instance.pi_storage_pool = ""; + instance.pi_storage_type = ""; + } + }); + }); + } config.updateChild(["json", "power"], componentProps.data.name, stateData); } diff --git a/unit-tests/state/power-vs.test.js b/unit-tests/state/power-vs.test.js index 92575c3e..4daeccf7 100644 --- a/unit-tests/state/power-vs.test.js +++ b/unit-tests/state/power-vs.test.js @@ -11,7 +11,7 @@ const { function newState() { let store = new state(true); store.setUpdateCallback(() => {}); - store.store.json._options.power_vs_zones = ["us-south", "dal10"]; + store.store.json._options.power_vs_zones = ["us-south", "dal10", "dal12"]; return store; } @@ -197,6 +197,238 @@ describe("power-vs", () => { "it should return correct data" ); }); + it("should save a workspace and update instances, volumes, and vtl to remove storage pools and storage tiers", () => { + let state = new newState(); + state.power.create({ name: "toad", zone: "dal10", imageNames: [] }); + state.power_instances.create({ + name: "frog", + zone: "dal10", + workspace: "toad", + network: [], + pi_storage_pool: "General-Flash-43", + pi_storage_type: "Tier 1", + }); + state.power_volumes.create({ + name: "foo", + zone: "dal10", + workspace: "toad", + network: [], + pi_volume_pool: "General-Flash-43", + pi_volume_type: "Tier 3", + }); + state.vtl.create({ + name: "bar", + zone: "dal10", + workspace: "toad", + network: [], + pi_storage_pool: "General-Flash-43", + pi_storage_type: "Tier 3", + }); + state.power.save( + { name: "toad", zone: "dal12" }, + { data: { name: "toad", zone: "dal10" } } + ); + let expectedData = { + name: "toad", + resource_group: null, + ssh_keys: [], + network: [], + cloud_connections: [], + images: [], + imageNames: [], + attachments: [], + zone: "dal12", + }; + assert.deepEqual( + state.store.json.power[0], + expectedData, + "it should update zone in place" + ); + assert.deepEqual( + state.store.json.power_instances[0].pi_storage_pool, + "", + "it should update instance storage pool" + ); + assert.isNull( + state.store.json.power_instances[0].pi_storage_type, + "it should update instance storage type" + ); + assert.deepEqual( + state.store.json.power_volumes[0].pi_volume_pool, + "", + "it should update volume pool" + ); + assert.isNull( + state.store.json.power_volumes[0].pi_volume_type, + "it should update volume type" + ); + assert.deepEqual( + state.store.json.vtl[0].pi_storage_pool, + "", + "it should update instance storage pool" + ); + assert.isNull( + state.store.json.vtl[0].pi_storage_type, + "it should update instance storage type" + ); + }); + it("should save a workspoace and not remove storage pools and storage tiers if instances, volumes, and vtl are not in workspace", () => { + let state = new newState(); + state.power.create({ name: "toad", zone: "dal10", imageNames: [] }); + state.power.create({ name: "toad2", zone: "dal10", imageNames: [] }); + state.power_instances.create({ + name: "frog", + zone: "dal10", + workspace: "toad2", + network: [], + pi_storage_pool: "General-Flash-43", + pi_storage_type: "Tier 1", + }); + state.power_volumes.create({ + name: "foo", + zone: "dal10", + workspace: "toad2", + network: [], + pi_volume_pool: "General-Flash-43", + pi_volume_type: "Tier 3", + }); + state.vtl.create({ + name: "bar", + zone: "dal10", + workspace: "toad2", + network: [], + pi_storage_pool: "General-Flash-43", + pi_storage_type: "Tier 3", + }); + state.power.save( + { name: "toad", zone: "dal12" }, + { data: { name: "toad", zone: "dal10" } } + ); + let expectedData = { + name: "toad", + resource_group: null, + ssh_keys: [], + network: [], + cloud_connections: [], + images: [], + imageNames: [], + attachments: [], + zone: "dal12", + }; + assert.deepEqual( + state.store.json.power[0], + expectedData, + "it should update zone in place" + ); + assert.deepEqual( + state.store.json.power_instances[0].pi_storage_pool, + "General-Flash-43", + "it should update instance storage pool" + ); + assert.deepEqual( + state.store.json.power_instances[0].pi_storage_type, + "Tier 1", + "it should update instance storage type" + ); + assert.deepEqual( + state.store.json.power_volumes[0].pi_volume_pool, + "General-Flash-43", + "it should update volume pool" + ); + assert.deepEqual( + state.store.json.power_volumes[0].pi_volume_type, + "Tier 3", + "it should update volume type" + ); + assert.deepEqual( + state.store.json.vtl[0].pi_storage_pool, + "General-Flash-43", + "it should update instance storage pool" + ); + assert.deepEqual( + state.store.json.vtl[0].pi_storage_type, + "Tier 3", + "it should update instance storage type" + ); + }); + it("should save a workspace and not alter any storage pools or storage tiers if zone was not changed", () => { + let state = new newState(); + state.power.create({ name: "toad", zone: "dal10", imageNames: [] }); + state.power_instances.create({ + name: "frog", + zone: "dal10", + workspace: "toad", + network: [], + pi_storage_pool: "General-Flash-43", + pi_storage_type: "Tier 1", + }); + state.power_volumes.create({ + name: "foo", + zone: "dal10", + workspace: "toad", + network: [], + pi_volume_pool: "General-Flash-43", + pi_volume_type: "Tier 3", + }); + state.vtl.create({ + name: "bar", + zone: "dal10", + workspace: "toad", + network: [], + pi_storage_pool: "General-Flash-43", + pi_storage_type: "Tier 3", + }); + state.power.save( + { name: "cat", zone: "dal10" }, + { data: { name: "toad", zone: "dal10" } } + ); + let expectedData = { + name: "cat", + resource_group: null, + ssh_keys: [], + network: [], + cloud_connections: [], + images: [], + imageNames: [], + attachments: [], + zone: "dal10", + }; + assert.deepEqual( + state.store.json.power[0], + expectedData, + "it should update name in place" + ); + assert.deepEqual( + state.store.json.power_instances[0].pi_storage_pool, + "General-Flash-43", + "it should update instance storage pool" + ); + assert.deepEqual( + state.store.json.power_instances[0].pi_storage_type, + "Tier 1", + "it should update instance storage type" + ); + assert.deepEqual( + state.store.json.power_volumes[0].pi_volume_pool, + "General-Flash-43", + "it should update volume pool" + ); + assert.deepEqual( + state.store.json.power_volumes[0].pi_volume_type, + "Tier 3", + "it should update volume type" + ); + assert.deepEqual( + state.store.json.vtl[0].pi_storage_pool, + "General-Flash-43", + "it should update instance storage pool" + ); + assert.deepEqual( + state.store.json.vtl[0].pi_storage_type, + "Tier 3", + "it should update instance storage type" + ); + }); }); describe("power.delete", () => { it("should delete a workspace", () => { From df16b410a2b9bf250751e6782e9a289568e34f19 Mon Sep 17 00:00:00 2001 From: terechc Date: Tue, 26 Mar 2024 09:05:46 -0400 Subject: [PATCH 03/17] Issue 1739: POST template-tar route (#1743) * POST template-tar route * rm extra doc * changelog * log error * rm space in header * rm commas * commas warning --- CHANGELOG.md | 12 ++ client/src/lib/docs/api-spec.yaml | 60 ++++++++- client/src/lib/docs/release-notes.json | 8 ++ express-controllers/craig-api.js | 39 +++++- express-routes/routes.js | 1 + unit-tests/api/craig-api.test.js | 163 +++++++++++++++++++++++++ unit-tests/forms/wizard.test.js | 24 ++-- 7 files changed, 292 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d93c967e..ac52083a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,18 @@ All notable changes to this project will be documented in this file. +## 1.14.0 + +### Upgrade Notes + + +### Features + +- Users can now update existing CRAIG templates and download the updated tar file by using the endpoint POST `/api/craig/template-tar/:template` + +### Fixes + + ## 1.13.1 ### Upgrade Notes diff --git a/client/src/lib/docs/api-spec.yaml b/client/src/lib/docs/api-spec.yaml index b1bc66d0..c43baaa7 100644 --- a/client/src/lib/docs/api-spec.yaml +++ b/client/src/lib/docs/api-spec.yaml @@ -5,7 +5,9 @@ info: Cloud Resources and Infrastructure as Code Generator. In order to use the CRAIG API, you must set the environment variable `API_KEY` to your IBM Cloud API Key - version: 1.11.0 + version: 1.14.0 +servers: + - url: http://localhost:8080 externalDocs: description: To get started with CRAIG, visit here url: https://github.ibm.com/craig-automation/CRAIG/blob/main/README.md @@ -30,12 +32,66 @@ paths: required: true schema: type: string - description: Name of template to crete tar file for. Possible values `from-scratch`, `oracle-rac`, `power-vs-sap-hana`, `quick-start-power`, `mixed`, `vsi-edge`, and `vsi` + description: Name of template to crete tar file for. Possible values `from-scratch`, `oracle-rac`, `oracle-si`, `power-vs-sap-hana`, `quick-start-power`, `mixed`, `vsi-edge`, and `vsi` responses: "200": description: Successfully created tar file "404": description: Supplied template does not exist or not found + post: + tags: + - CRAIG + summary: Update a specific template and download the template tar file with the provided updates + description: | + Updates the provided template based on the fields provided in the request body, and downloads the updated template tar file to your machine. The fields provided in the request body will replace the entire contents of that field in the CRAIG json. If you wish to add a resource to a field, include the original fields as well. + + To use locally, use this command : `curl -X POST -H Content-Type:application/json -d '{field-to-update: [], field-to-update-2: []}' --url http://localhost:8080/api/craig/template-tar/ --output craig.tar` + + The below example body replaces whatever transit gateways that may or may not exist for the template with one transit gateway named `transit-gateway`. + + Note: API Call will fail if JSON is not properly formatted. Make sure that you remove all trailing commas at the end of lists and objects, otherwise you may get an `Unexpected token` error + operationId: updateTemplateTar + parameters: + - in: path + name: template + required: true + schema: + type: string + description: Name of template to crete tar file for. Possible values `from-scratch`, `oracle-rac`, `oracle-si`, `power-vs-sap-hana`, `quick-start-power`, `mixed`, `vsi-edge`, and `vsi` + requestBody: + content: + application/json: + schema: + type: object + description: JSON field(s) to update in CRAIG + example: + "transit_gateways": + [ + { + "name": "transit-gateway", + "resource_group": "service-rg", + "global": false, + "connections": + [ + { "tgw": "transit-gateway", "vpc": "transit" }, + { "tgw": "transit-gateway", "power": "dal10" } + ], + "use_data": false, + "gre_tunnels": [], + "prefix_filters": [], + "crns": null, + "classic": false + }, + ] + + responses: + "200": + description: Successfully updated and created tar file + "400": + description: The request body is incorrectly formatted in JSON or the resource(s) provided in the request do not contain all required fields + "404": + description: Supplied template does not exist or not found + /api/power/{zone}/{component}: get: tags: diff --git a/client/src/lib/docs/release-notes.json b/client/src/lib/docs/release-notes.json index 48cfff9e..7660ecf3 100644 --- a/client/src/lib/docs/release-notes.json +++ b/client/src/lib/docs/release-notes.json @@ -1,4 +1,12 @@ [ + { + "version": "1.14.0", + "features": [ + "Users can now update existing CRAIG templates and download the updated tar file by using the endpoint POST `/api/craig/template-tar/:template` " + ], + "fixes": [], + "upgrade_notes": [] + }, { "version": "1.13.1", "features": [ diff --git a/express-controllers/craig-api.js b/express-controllers/craig-api.js index f91823b1..c14e5c00 100644 --- a/express-controllers/craig-api.js +++ b/express-controllers/craig-api.js @@ -8,7 +8,7 @@ const quickStartPower = require("../client/src/lib/docs/templates/quick-start-po const slzMixed = require("../client/src/lib/docs/templates/slz-mixed.json"); const slzVsiEdge = require("../client/src/lib/docs/templates/slz-vsi-edge.json"); const slzVsi = require("../client/src/lib/docs/templates/slz-vsi.json"); - +const { transpose } = require("lazy-z"); const templateNameToJson = { "from-scratch": fromScratch, "oracle-rac": oracleRac, @@ -90,6 +90,43 @@ function craigApi(controller, tar) { res.send(err); }); }; + + this.updateTemplateTar = function (req, res) { + let fieldsToUpdate = req.body; + let template = req.params["template"]; + let pack = tar.pack(); + + return new Promise((resolve, reject) => { + if (!templateNameToJson[template]) { + let err = new Error(); + err.message = `No template found with name ${template}`; + err.status = 404; + console.error(err); + reject(err); + } + let templateJson = templateNameToJson[template]; + try { + transpose(fieldsToUpdate, templateJson); + let craigData = configToFilesJson(templateJson, false, true); + let tarFile = `${template}.tar`; + packTar(pack, tarFile.slice(0, tarFile.length - 4), craigData); + pack.finalize(); + resolve(controller.createBlob(pack)); + } catch (err) { + err.status = 400; + console.error(err); + reject(err); + } + }) + .then((data) => { + let dataFromBuffer = Buffer.from(data); + res.type("tar"); + res.send(dataFromBuffer); + }) + .catch((err) => { + res.send(err); + }); + }; } module.exports = { diff --git a/express-routes/routes.js b/express-routes/routes.js index bcb16d69..c6080d45 100644 --- a/express-routes/routes.js +++ b/express-routes/routes.js @@ -34,6 +34,7 @@ router.get("/power/:zone/:component", controller.getPowerComponent); // craig router.post("/craig/tar", craigRoutes.craigTar); router.get("/craig/template-tar/:template", craigRoutes.templateTar); +router.post("/craig/template-tar/:template", craigRoutes.updateTemplateTar); // stats router.get("/stats", controller.getStats); diff --git a/unit-tests/api/craig-api.test.js b/unit-tests/api/craig-api.test.js index 327f6536..b5542e54 100644 --- a/unit-tests/api/craig-api.test.js +++ b/unit-tests/api/craig-api.test.js @@ -326,4 +326,167 @@ describe("craig api", () => { }); }); }); + describe("updateTemplateTar", () => { + it("should respond with 404 error if no template not found", () => { + res.send = new sinon.spy(); + res.status = new sinon.spy(); + let api = new craigApi({}, new mockPackTar()); + + return api + .updateTemplateTar( + { + params: { template: "fake-template" }, + }, + res + ) + .then(() => { + assert.deepEqual(res.send.lastCall.args[0].status, 404); + }); + }).timeout(100000); + it("should respond with 400 error if body is invalid, causing tar file to not create", () => { + res.send = new sinon.spy(); + res.status = new sinon.spy(); + let api = new craigApi({}, new mockPackTar()); + + return api + .updateTemplateTar( + { + params: { + template: "quick-start-power", + body: { + ssh_keys: ["bad-data"], + }, + }, + }, + res + ) + .then(() => { + assert.deepEqual(res.send.lastCall.args[0].status, 400); + }); + }).timeout(100000); + it("it should have correct updated data in tar when finalized", () => { + let expectedFiles = [ + { name: "from-scratch", data: "" }, + { + name: "from-scratch/main.tf", + data: + "##############################################################################\n" + + "# IBM Cloud Provider\n" + + "##############################################################################\n" + + "\n" + + 'provider "ibm" {\n' + + " ibmcloud_api_key = var.ibmcloud_api_key\n" + + " region = var.region\n" + + " ibmcloud_timeout = 60\n" + + "}\n" + + "\n" + + "##############################################################################\n", + }, + { + name: "from-scratch/flow_logs.tf", + data: + "##############################################################################\n" + + "# Flow Logs Resources\n" + + "##############################################################################\n" + + "\n" + + "##############################################################################\n", + }, + { + name: "from-scratch/variables.tf", + data: '##############################################################################\n# Variables\n##############################################################################\n\nvariable "ibmcloud_api_key" {\n description = "The IBM Cloud platform API key needed to deploy IAM enabled resources."\n type = string\n sensitive = true\n}\n\nvariable "region" {\n description = "IBM Cloud Region where resources will be provisioned"\n type = string\n default = "us-south"\n}\n\nvariable "prefix" {\n description = "Name prefix that will be prepended to named resources"\n type = string\n default = "iac"\n}\n\n##############################################################################\n', + }, + { name: "from-scratch/key_management.tf", data: "\n" }, + { name: "from-scratch/object_storage.tf", data: "\n" }, + { + name: "from-scratch/resource_groups.tf", + data: + "##############################################################################\n" + + "# Resource Groups\n" + + "##############################################################################\n" + + "\n" + + 'resource "ibm_resource_group" "craig_rg" {\n' + + ' name = "${var.prefix}-craig-rg"\n' + + " tags = [\n" + + ' "hello",\n' + + ' "world"\n' + + " ]\n" + + "}\n" + + "\n" + + 'resource "ibm_resource_group" "added_rg" {\n' + + ' name = "${var.prefix}-added-rg"\n' + + " tags = [\n" + + ' "hello",\n' + + ' "world"\n' + + " ]\n" + + "}\n" + + "\n" + + "##############################################################################\n", + }, + { + name: "from-scratch/versions.tf", + data: + "##############################################################################\n" + + "# Terraform Providers\n" + + "##############################################################################\n" + + "\n" + + "terraform {\n" + + " required_providers {\n" + + " ibm = {\n" + + ' source = "IBM-Cloud/ibm"\n' + + ' version = "~>1.63.0"\n' + + " }\n" + + " }\n" + + ' required_version = ">=1.5"\n' + + "}\n" + + "\n" + + "##############################################################################\n", + }, + { + name: "from-scratch/craig.json", + data: '{\n "_options": {\n "prefix": "iac",\n "region": "us-south",\n "tags": [\n "hello",\n "world"\n ],\n "zones": 3,\n "endpoints": "private",\n "account_id": null,\n "fs_cloud": false,\n "enable_classic": false,\n "dynamic_subnets": true,\n "enable_power_vs": false,\n "craig_version": "1.12.0",\n "power_vs_zones": [],\n "power_vs_high_availability": false,\n "no_vpn_secrets_manager_auth": false,\n "power_vs_ha_zone_1": null,\n "power_vs_ha_zone_2": null\n },\n "access_groups": [],\n "appid": [],\n "atracker": {\n "enabled": false,\n "type": "cos",\n "name": "atracker",\n "target_name": "atracker-cos",\n "bucket": null,\n "add_route": true,\n "cos_key": null,\n "locations": [\n "global",\n "us-south"\n ],\n "instance": false,\n "plan": "lite",\n "resource_group": null,\n "archive": false\n },\n "cbr_rules": [],\n "cbr_zones": [],\n "classic_ssh_keys": [],\n "classic_vlans": [],\n "clusters": [],\n "dns": [],\n "event_streams": [],\n "f5_vsi": [],\n "iam_account_settings": {\n "enable": false,\n "mfa": null,\n "allowed_ip_addresses": null,\n "include_history": false,\n "if_match": null,\n "max_sessions_per_identity": null,\n "restrict_create_service_id": null,\n "restrict_create_platform_apikey": null,\n "session_expiration_in_seconds": null,\n "session_invalidation_in_seconds": null\n },\n "icd": [],\n "key_management": [],\n "load_balancers": [],\n "logdna": {\n "name": "logdna",\n "archive": false,\n "enabled": false,\n "plan": "lite",\n "endpoints": "private",\n "platform_logs": false,\n "resource_group": null,\n "cos": null,\n "bucket": null\n },\n "object_storage": [],\n "power": [],\n "power_instances": [],\n "power_volumes": [],\n "resource_groups": [\n {\n "use_prefix": true,\n "name": "craig-rg",\n "use_data": false\n },\n {\n "use_prefix": true,\n "name": "added-rg",\n "use_data": false\n }\n ],\n "routing_tables": [],\n "scc": {\n "credential_description": null,\n "id": null,\n "passphrase": null,\n "name": "",\n "location": "us",\n "collector_description": null,\n "is_public": false,\n "scope_description": null,\n "enable": false\n },\n "secrets_manager": [],\n "security_groups": [],\n "ssh_keys": [],\n "sysdig": {\n "enabled": false,\n "plan": "graduated-tier",\n "resource_group": null,\n "name": "sysdig",\n "platform_logs": false\n },\n "teleport_vsi": [],\n "transit_gateways": [],\n "virtual_private_endpoints": [],\n "vpcs": [],\n "vpn_gateways": [],\n "vpn_servers": [],\n "vsi": []\n}', + }, + { + data: ' Apache License\nVersion 2.0, January 2004\nhttp://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n\n"License" shall mean the terms and conditions for use, reproduction,\nand distribution as defined by Sections 1 through 9 of this document.\n\n"Licensor" shall mean the copyright owner or entity authorized by\nthe copyright owner that is granting the License.\n\n"Legal Entity" shall mean the union of the acting entity and all\nother entities that control, are controlled by, or are under common\ncontrol with that entity. For the purposes of this definition,\n"control" means (i) the power, direct or indirect, to cause the\ndirection or management of such entity, whether by contract or\notherwise, or (ii) ownership of fifty percent (50%) or more of the\noutstanding shares, or (iii) beneficial ownership of such entity.\n\n"You" (or "Your") shall mean an individual or Legal Entity\nexercising permissions granted by this License.\n\n"Source" form shall mean the preferred form for making modifications,\nincluding but not limited to software source code, documentation\nsource, and configuration files.\n\n"Object" form shall mean any form resulting from mechanical\ntransformation or translation of a Source form, including but\nnot limited to compiled object code, generated documentation,\nand conversions to other media types.\n\n"Work" shall mean the work of authorship, whether in Source or\nObject form, made available under the License, as indicated by a\ncopyright notice that is included in or attached to the work\n(an example is provided in the Appendix below).\n\n"Derivative Works" shall mean any work, whether in Source or Object\nform, that is based on (or derived from) the Work and for which the\neditorial revisions, annotations, elaborations, or other modifications\nrepresent, as a whole, an original work of authorship. For the purposes\nof this License, Derivative Works shall not include works that remain\nseparable from, or merely link (or bind by name) to the interfaces of,\nthe Work and Derivative Works thereof.\n\n"Contribution" shall mean any work of authorship, including\nthe original version of the Work and any modifications or additions\nto that Work or Derivative Works thereof, that is intentionally\nsubmitted to Licensor for inclusion in the Work by the copyright owner\nor by an individual or Legal Entity authorized to submit on behalf of\nthe copyright owner. For the purposes of this definition, "submitted"\nmeans any form of electronic, verbal, or written communication sent\nto the Licensor or its representatives, including but not limited to\ncommunication on electronic mailing lists, source code control systems,\nand issue tracking systems that are managed by, or on behalf of, the\nLicensor for the purpose of discussing and improving the Work, but\nexcluding communication that is conspicuously marked or otherwise\ndesignated in writing by the copyright owner as "Not a Contribution."\n\n"Contributor" shall mean Licensor and any individual or Legal Entity\non behalf of whom a Contribution has been received by Licensor and\nsubsequently incorporated within the Work.\n\n2. Grant of Copyright License. Subject to the terms and conditions of\nthis License, each Contributor hereby grants to You a perpetual,\nworldwide, non-exclusive, no-charge, royalty-free, irrevocable\ncopyright license to reproduce, prepare Derivative Works of,\npublicly display, publicly perform, sublicense, and distribute the\nWork and such Derivative Works in Source or Object form.\n\n3. Grant of Patent License. Subject to the terms and conditions of\nthis License, each Contributor hereby grants to You a perpetual,\nworldwide, non-exclusive, no-charge, royalty-free, irrevocable\n(except as stated in this section) patent license to make, have made,\nuse, offer to sell, sell, import, and otherwise transfer the Work,\nwhere such license applies only to those patent claims licensable\nby such Contributor that are necessarily infringed by their\nContribution(s) alone or by combination of their Contribution(s)\nwith the Work to which such Contribution(s) was submitted. If You\ninstitute patent litigation against any entity (including a\ncross-claim or counterclaim in a lawsuit) alleging that the Work\nor a Contribution incorporated within the Work constitutes direct\nor contributory patent infringement, then any patent licenses\ngranted to You under this License for that Work shall terminate\nas of the date such litigation is filed.\n\n4. Redistribution. You may reproduce and distribute copies of the\nWork or Derivative Works thereof in any medium, with or without\nmodifications, and in Source or Object form, provided that You\nmeet the following conditions:\n\n(a) You must give any other recipients of the Work or\nDerivative Works a copy of this License; and\n\n(b) You must cause any modified files to carry prominent notices\nstating that You changed the files; and\n\n(c) You must retain, in the Source form of any Derivative Works\nthat You distribute, all copyright, patent, trademark, and\nattribution notices from the Source form of the Work,\nexcluding those notices that do not pertain to any part of\nthe Derivative Works; and\n\n(d) If the Work includes a "NOTICE" text file as part of its\ndistribution, then any Derivative Works that You distribute must\ninclude a readable copy of the attribution notices contained\nwithin such NOTICE file, excluding those notices that do not\npertain to any part of the Derivative Works, in at least one\nof the following places: within a NOTICE text file distributed\nas part of the Derivative Works; within the Source form or\ndocumentation, if provided along with the Derivative Works; or,\nwithin a display generated by the Derivative Works, if and\nwherever such third-party notices normally appear. The contents\nof the NOTICE file are for informational purposes only and\ndo not modify the License. You may add Your own attribution\nnotices within Derivative Works that You distribute, alongside\nor as an addendum to the NOTICE text from the Work, provided\nthat such additional attribution notices cannot be construed\nas modifying the License.\n\nYou may add Your own copyright statement to Your modifications and\nmay provide additional or different license terms and conditions\nfor use, reproduction, or distribution of Your modifications, or\nfor any such Derivative Works as a whole, provided Your use,\nreproduction, and distribution of the Work otherwise complies with\nthe conditions stated in this License.\n\n5. Submission of Contributions. Unless You explicitly state otherwise,\nany Contribution intentionally submitted for inclusion in the Work\nby You to the Licensor shall be under the terms and conditions of\nthis License, without any additional terms or conditions.\nNotwithstanding the above, nothing herein shall supersede or modify\nthe terms of any separate license agreement you may have executed\nwith Licensor regarding such Contributions.\n\n6. Trademarks. This License does not grant permission to use the trade\nnames, trademarks, service marks, or product names of the Licensor,\nexcept as required for reasonable and customary use in describing the\norigin of the Work and reproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty. Unless required by applicable law or\nagreed to in writing, Licensor provides the Work (and each\nContributor provides its Contributions) on an "AS IS" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\nimplied, including, without limitation, any warranties or conditions\nof TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\nPARTICULAR PURPOSE. You are solely responsible for determining the\nappropriateness of using or redistributing the Work and assume any\nrisks associated with Your exercise of permissions under this License.\n\n8. Limitation of Liability. In no event and under no legal theory,\nwhether in tort (including negligence), contract, or otherwise,\nunless required by applicable law (such as deliberate and grossly\nnegligent acts) or agreed to in writing, shall any Contributor be\nliable to You for damages, including any direct, indirect, special,\nincidental, or consequential damages of any character arising as a\nresult of this License or out of the use or inability to use the\nWork (including but not limited to damages for loss of goodwill,\nwork stoppage, computer failure or malfunction, or any and all\nother commercial damages or losses), even if such Contributor\nhas been advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability. While redistributing\nthe Work or Derivative Works thereof, You may choose to offer,\nand charge a fee for, acceptance of support, warranty, indemnity,\nor other liability obligations and/or rights consistent with this\nLicense. However, in accepting such obligations, You may act only\non Your own behalf and on Your sole responsibility, not on behalf\nof any other Contributor, and only if You agree to indemnify,\ndefend, and hold each Contributor harmless for any liability\nincurred by, or claims asserted against, such Contributor by reason\nof your accepting any such warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n\nAPPENDIX: How to apply the Apache License to your work.\n\nTo apply the Apache License to your work, attach the following\nboilerplate notice, with the fields enclosed by brackets "[]"\nreplaced with your own identifying information. (Don\'t include\nthe brackets!) The text should be enclosed in the appropriate\ncomment syntax for the file format. We also recommend that a\nfile or class name and description of purpose be included on the\nsame "printed page" as the copyright notice for easier\nidentification within third-party archives.\n\nCopyright [yyyy] [name of copyright owner]\n\nLicensed under the Apache License, Version 2.0 (the "License");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an "AS IS" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n', + name: "from-scratch/LICENSE", + }, + ]; + + let mockController = { + createBlob: function () { + return new ArrayBuffer(5); + }, + }; + let tar = new mockPackTar(); + let api = new craigApi(mockController, tar); + + return api + .updateTemplateTar( + { + params: { template: "from-scratch" }, + body: { + resource_groups: [ + { + use_prefix: true, + name: "craig-rg", + use_data: false, + }, + { + use_prefix: true, + name: "added-rg", + use_data: false, + }, + ], + }, + }, + res + ) + .then(() => { + assert.deepEqual( + tar.files, + expectedFiles, + "it should contain added-rg in the tar file" + ); + }); + }); + }); }); diff --git a/unit-tests/forms/wizard.test.js b/unit-tests/forms/wizard.test.js index 186a08af..b555237b 100644 --- a/unit-tests/forms/wizard.test.js +++ b/unit-tests/forms/wizard.test.js @@ -57,7 +57,7 @@ describe("setup wizard", () => { enable_power_vs: false, enable_classic: false, power_vs_zones: [], - craig_version: "1.13.1", + craig_version: "1.14.0", power_vs_high_availability: false, no_vpn_secrets_manager_auth: false, }, @@ -975,7 +975,7 @@ describe("setup wizard", () => { enable_power_vs: false, enable_classic: false, power_vs_zones: [], - craig_version: "1.13.1", + craig_version: "1.14.0", power_vs_high_availability: false, no_vpn_secrets_manager_auth: false, }, @@ -1892,7 +1892,7 @@ describe("setup wizard", () => { enable_power_vs: false, enable_classic: false, power_vs_zones: [], - craig_version: "1.13.1", + craig_version: "1.14.0", power_vs_high_availability: false, no_vpn_secrets_manager_auth: false, }, @@ -2403,7 +2403,7 @@ describe("setup wizard", () => { enable_power_vs: false, enable_classic: false, power_vs_zones: [], - craig_version: "1.13.1", + craig_version: "1.14.0", power_vs_high_availability: false, no_vpn_secrets_manager_auth: false, }, @@ -2905,7 +2905,7 @@ describe("setup wizard", () => { enable_power_vs: false, enable_classic: false, power_vs_zones: [], - craig_version: "1.13.1", + craig_version: "1.14.0", power_vs_high_availability: false, no_vpn_secrets_manager_auth: false, }, @@ -3484,7 +3484,7 @@ describe("setup wizard", () => { enable_power_vs: false, enable_classic: false, power_vs_zones: [], - craig_version: "1.13.1", + craig_version: "1.14.0", no_vpn_secrets_manager_auth: false, }, resource_groups: [ @@ -3654,7 +3654,7 @@ describe("setup wizard", () => { enable_power_vs: false, enable_classic: false, power_vs_zones: [], - craig_version: "1.13.1", + craig_version: "1.14.0", power_vs_high_availability: false, no_vpn_secrets_manager_auth: false, }, @@ -4225,7 +4225,7 @@ describe("setup wizard", () => { enable_power_vs: false, enable_classic: false, power_vs_zones: [], - craig_version: "1.13.1", + craig_version: "1.14.0", power_vs_high_availability: false, no_vpn_secrets_manager_auth: false, }, @@ -4770,7 +4770,7 @@ describe("setup wizard", () => { enable_power_vs: false, enable_classic: false, power_vs_zones: [], - craig_version: "1.13.1", + craig_version: "1.14.0", power_vs_high_availability: false, no_vpn_secrets_manager_auth: false, }, @@ -5320,7 +5320,7 @@ describe("setup wizard", () => { enable_classic: false, enable_classic: false, power_vs_zones: [], - craig_version: "1.13.1", + craig_version: "1.14.0", no_vpn_secrets_manager_auth: false, }, resource_groups: [ @@ -5812,7 +5812,7 @@ describe("setup wizard", () => { enable_power_vs: true, enable_classic: false, power_vs_zones: ["dal10"], - craig_version: "1.13.1", + craig_version: "1.14.0", power_vs_high_availability: false, no_vpn_secrets_manager_auth: false, }, @@ -6314,7 +6314,7 @@ describe("setup wizard", () => { enable_power_vs: true, enable_classic: false, power_vs_zones: ["dal10"], - craig_version: "1.13.1", + craig_version: "1.14.0", power_vs_high_availability: false, no_vpn_secrets_manager_auth: false, }, From b42b01726c4611f69657b18099fcf09c2f8c7f05 Mon Sep 17 00:00:00 2001 From: jvallexm Date: Tue, 26 Mar 2024 11:27:06 -0400 Subject: [PATCH 04/17] Issue 1744 (#1747) * feat: pin policy * vsi image api updates Signed-off-by: Lucas-Franke * add timeout to random test Signed-off-by: Lucas-Franke * moving recursive mock axios into vsi-api.test Signed-off-by: Lucas-Franke * feat: express vulnerability fix * feat: manual power vs naming --------- Signed-off-by: Lucas-Franke Co-authored-by: Lucas-Franke --- CHANGELOG.md | 3 +- client/src/components/pages/Home.js | 2 + client/src/lib/docs/api-spec.yaml | 4 +- client/src/lib/docs/release-notes.json | 3 +- .../src/lib/docs/templates/from-scratch.json | 3 +- client/src/lib/docs/templates/oracle-rac.json | 3 +- client/src/lib/docs/templates/oracle-si.json | 3 +- .../docs/templates/power-poc-quick-start.json | 3 +- .../lib/docs/templates/power-sap-hana.json | 3 +- .../lib/docs/templates/quick-start-power.json | 3 +- client/src/lib/docs/templates/slz-mixed.json | 3 +- .../src/lib/docs/templates/slz-vsi-edge.json | 3 +- client/src/lib/docs/templates/slz-vsi.json | 3 +- .../lib/docs/templates/vpn-as-a-service.json | 3 +- .../src/lib/json-to-iac/power-vs-instances.js | 3 +- client/src/lib/state/options.js | 10 ++ .../power-instances-schema.js | 9 +- package-lock.json | 55 ++------- package.json | 2 +- unit-tests/api/craig-api.test.js | 6 +- .../json-to-iac/power-vs-instances.test.js | 112 ++++++++++++++++++ unit-tests/state/power-vs-instances.test.js | 41 +++++++ unit-tests/state/schema.test.js | 4 + 23 files changed, 218 insertions(+), 66 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ac52083a..b15238c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,8 @@ All notable changes to this project will be documented in this file. ### Features -- Users can now update existing CRAIG templates and download the updated tar file by using the endpoint POST `/api/craig/template-tar/:template` +- Users can now update existing CRAIG templates and download the updated tar file by using the endpoint POST `/api/craig/template-tar/:template` +- From the options page, users can now enable Manual Power VSI naming. When this is enabled, the environment prefix will not be prepended to the names of Power VS Virtual Server or FalconStor VTL instances ### Fixes diff --git a/client/src/components/pages/Home.js b/client/src/components/pages/Home.js index dc643e28..7bdb7d07 100644 --- a/client/src/components/pages/Home.js +++ b/client/src/components/pages/Home.js @@ -98,6 +98,8 @@ function Home(props) { enable_power_vs: craig.options.enable_power_vs, power_vs_high_availability: craig.options.power_vs_high_availability, + manual_power_vsi_naming: + craig.options.manual_power_vsi_naming, }, { power_vs_ha_zone_1: craig.options.power_vs_ha_zone_1, diff --git a/client/src/lib/docs/api-spec.yaml b/client/src/lib/docs/api-spec.yaml index c43baaa7..0bc938c8 100644 --- a/client/src/lib/docs/api-spec.yaml +++ b/client/src/lib/docs/api-spec.yaml @@ -74,13 +74,13 @@ paths: "connections": [ { "tgw": "transit-gateway", "vpc": "transit" }, - { "tgw": "transit-gateway", "power": "dal10" } + { "tgw": "transit-gateway", "power": "dal10" }, ], "use_data": false, "gre_tunnels": [], "prefix_filters": [], "crns": null, - "classic": false + "classic": false, }, ] diff --git a/client/src/lib/docs/release-notes.json b/client/src/lib/docs/release-notes.json index 7660ecf3..61b0f38c 100644 --- a/client/src/lib/docs/release-notes.json +++ b/client/src/lib/docs/release-notes.json @@ -2,7 +2,8 @@ { "version": "1.14.0", "features": [ - "Users can now update existing CRAIG templates and download the updated tar file by using the endpoint POST `/api/craig/template-tar/:template` " + "Users can now update existing CRAIG templates and download the updated tar file by using the endpoint POST `/api/craig/template-tar/:template`", + "From the options page, users can now enable Manual Power VSI naming. When this is enabled, the environment prefix will not be prepended to the names of Power VS Virtual Server or FalconStor VTL instances" ], "fixes": [], "upgrade_notes": [] diff --git a/client/src/lib/docs/templates/from-scratch.json b/client/src/lib/docs/templates/from-scratch.json index adc63ef2..2b66da78 100644 --- a/client/src/lib/docs/templates/from-scratch.json +++ b/client/src/lib/docs/templates/from-scratch.json @@ -15,7 +15,8 @@ "power_vs_high_availability": false, "no_vpn_secrets_manager_auth": false, "power_vs_ha_zone_1": null, - "power_vs_ha_zone_2": null + "power_vs_ha_zone_2": null, + "manual_power_vsi_naming": false }, "access_groups": [], "appid": [], diff --git a/client/src/lib/docs/templates/oracle-rac.json b/client/src/lib/docs/templates/oracle-rac.json index 6a1ec1f3..ece9b01b 100644 --- a/client/src/lib/docs/templates/oracle-rac.json +++ b/client/src/lib/docs/templates/oracle-rac.json @@ -15,7 +15,8 @@ "power_vs_high_availability": false, "no_vpn_secrets_manager_auth": false, "power_vs_ha_zone_1": null, - "power_vs_ha_zone_2": null + "power_vs_ha_zone_2": null, + "manual_power_vsi_naming": false }, "access_groups": [], "appid": [], diff --git a/client/src/lib/docs/templates/oracle-si.json b/client/src/lib/docs/templates/oracle-si.json index 07381573..35e4fa04 100644 --- a/client/src/lib/docs/templates/oracle-si.json +++ b/client/src/lib/docs/templates/oracle-si.json @@ -15,7 +15,8 @@ "no_vpn_secrets_manager_auth": false, "enable_classic": false, "power_vs_ha_zone_1": null, - "power_vs_ha_zone_2": null + "power_vs_ha_zone_2": null, + "manual_power_vsi_naming": false }, "access_groups": [], "appid": [], diff --git a/client/src/lib/docs/templates/power-poc-quick-start.json b/client/src/lib/docs/templates/power-poc-quick-start.json index 2f8a3702..0413e460 100644 --- a/client/src/lib/docs/templates/power-poc-quick-start.json +++ b/client/src/lib/docs/templates/power-poc-quick-start.json @@ -16,7 +16,8 @@ "fs_cloud": false, "power_vs_ha_zone_1": null, "power_vs_ha_zone_2": null, - "no_vpn_secrets_manager_auth": false + "no_vpn_secrets_manager_auth": false, + "manual_power_vsi_naming": false }, "access_groups": [], "appid": [], diff --git a/client/src/lib/docs/templates/power-sap-hana.json b/client/src/lib/docs/templates/power-sap-hana.json index ebd67ff7..ce81c28f 100644 --- a/client/src/lib/docs/templates/power-sap-hana.json +++ b/client/src/lib/docs/templates/power-sap-hana.json @@ -16,7 +16,8 @@ "template": "Power VS SAP Hana", "no_vpn_secrets_manager_auth": false, "power_vs_ha_zone_1": null, - "power_vs_ha_zone_2": null + "power_vs_ha_zone_2": null, + "manual_power_vsi_naming": false }, "access_groups": [], "appid": [ diff --git a/client/src/lib/docs/templates/quick-start-power.json b/client/src/lib/docs/templates/quick-start-power.json index b57ed9ef..dc7b123c 100644 --- a/client/src/lib/docs/templates/quick-start-power.json +++ b/client/src/lib/docs/templates/quick-start-power.json @@ -15,7 +15,8 @@ "fs_cloud": false, "no_vpn_secrets_manager_auth": false, "power_vs_ha_zone_1": null, - "power_vs_ha_zone_2": null + "power_vs_ha_zone_2": null, + "manual_power_vsi_naming": false }, "access_groups": [], "appid": [], diff --git a/client/src/lib/docs/templates/slz-mixed.json b/client/src/lib/docs/templates/slz-mixed.json index 4241d55b..7a87fda7 100644 --- a/client/src/lib/docs/templates/slz-mixed.json +++ b/client/src/lib/docs/templates/slz-mixed.json @@ -15,7 +15,8 @@ "power_vs_high_availability": false, "no_vpn_secrets_manager_auth": false, "power_vs_ha_zone_1": null, - "power_vs_ha_zone_2": null + "power_vs_ha_zone_2": null, + "manual_power_vsi_naming": false }, "access_groups": [], "appid": [], diff --git a/client/src/lib/docs/templates/slz-vsi-edge.json b/client/src/lib/docs/templates/slz-vsi-edge.json index cb87eae0..cc220079 100644 --- a/client/src/lib/docs/templates/slz-vsi-edge.json +++ b/client/src/lib/docs/templates/slz-vsi-edge.json @@ -15,7 +15,8 @@ "no_vpn_secrets_manager_auth": false, "enable_classic": false, "power_vs_ha_zone_1": null, - "power_vs_ha_zone_2": null + "power_vs_ha_zone_2": null, + "manual_power_vsi_naming": false }, "access_groups": [], "appid": [], diff --git a/client/src/lib/docs/templates/slz-vsi.json b/client/src/lib/docs/templates/slz-vsi.json index 68f7c126..8213fe1c 100644 --- a/client/src/lib/docs/templates/slz-vsi.json +++ b/client/src/lib/docs/templates/slz-vsi.json @@ -15,7 +15,8 @@ "no_vpn_secrets_manager_auth": false, "enable_classic": false, "power_vs_ha_zone_1": null, - "power_vs_ha_zone_2": null + "power_vs_ha_zone_2": null, + "manual_power_vsi_naming": false }, "access_groups": [], "appid": [], diff --git a/client/src/lib/docs/templates/vpn-as-a-service.json b/client/src/lib/docs/templates/vpn-as-a-service.json index f614598d..788cd3dd 100644 --- a/client/src/lib/docs/templates/vpn-as-a-service.json +++ b/client/src/lib/docs/templates/vpn-as-a-service.json @@ -16,7 +16,8 @@ "no_vpn_secrets_manager_auth": false, "enable_classic": false, "power_vs_ha_zone_1": null, - "power_vs_ha_zone_2": null + "power_vs_ha_zone_2": null, + "manual_power_vsi_naming": false }, "access_groups": [], "appid": [], diff --git a/client/src/lib/json-to-iac/power-vs-instances.js b/client/src/lib/json-to-iac/power-vs-instances.js index 06ea53f7..53719c48 100644 --- a/client/src/lib/json-to-iac/power-vs-instances.js +++ b/client/src/lib/json-to-iac/power-vs-instances.js @@ -16,6 +16,7 @@ const { * @returns {object} data object */ function powerVsInstanceData(instance, config) { + let manualVsiNaming = config?._options?.manual_power_vsi_naming; let foundWorkspace = !config?.power ? true : splatContains(config.power, "name", instance.workspace); @@ -62,7 +63,7 @@ function powerVsInstanceData(instance, config) { : false ) : "${ERROR: Unfound Ref}", - pi_instance_name: "${var.prefix}-" + instance.name, + pi_instance_name: (manualVsiNaming ? "" : "${var.prefix}-") + instance.name, }; transpose(instance, data); delete data.index; diff --git a/client/src/lib/state/options.js b/client/src/lib/state/options.js index edec2a97..2109d28b 100644 --- a/client/src/lib/state/options.js +++ b/client/src/lib/state/options.js @@ -387,6 +387,16 @@ function initOptions(store) { }[stateData.region]; }, }, + manual_power_vsi_naming: { + type: "toggle", + default: false, + labelText: "Manual Power VS Server Naming", + tooltip: { + content: + "By default CRAIG resources have the environment prefix prepended to the name of the resource. Toggle this to true to remove the prefix for Power VS Virtual Server and FalconStor VTL instances.", + }, + hideWhen: hideWhenNotPowerVs, + }, enable_classic: { type: "toggle", default: false, diff --git a/client/src/lib/state/power-vs-instances/power-instances-schema.js b/client/src/lib/state/power-vs-instances/power-instances-schema.js index a57093ee..5780ea10 100644 --- a/client/src/lib/state/power-vs-instances/power-instances-schema.js +++ b/client/src/lib/state/power-vs-instances/power-instances-schema.js @@ -164,7 +164,14 @@ function hideWhenNotIbmi(stateData) { */ function powerVsInstanceSchema(vtl) { return { - name: nameField("power_instances", { size: "small" }), + name: nameField("power_instances", { + size: "small", + helperText: function (stateData, componentProps) { + return componentProps.craig.store.json._options.manual_power_vsi_naming + ? stateData.name + : `${componentProps.craig.store.json._options.prefix}-${stateData.name}`; + }, + }), sap: { default: false, type: "toggle", diff --git a/package-lock.json b/package-lock.json index 145fb2b9..a4023754 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "blob-stream": "^0.1.3", "body-parser": "^1.20.2", "dotenv": "^16.3.1", - "express": "^4.18.1", + "express": "^4.19.2", "js-yaml": "^4.1.0", "json-to-tf": "^0.2.1", "lazy-z": "1.11.17", @@ -1227,9 +1227,9 @@ "dev": true }, "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", "engines": { "node": ">= 0.6" } @@ -1434,16 +1434,16 @@ } }, "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -1474,43 +1474,6 @@ "node": ">= 0.10.0" } }, - "node_modules/express/node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/express/node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/fast-fifo": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", diff --git a/package.json b/package.json index 4f836b03..e9d75d6b 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "blob-stream": "^0.1.3", "body-parser": "^1.20.2", "dotenv": "^16.3.1", - "express": "^4.18.1", + "express": "^4.19.2", "js-yaml": "^4.1.0", "json-to-tf": "^0.2.1", "lazy-z": "1.11.17", diff --git a/unit-tests/api/craig-api.test.js b/unit-tests/api/craig-api.test.js index b5542e54..6607dffa 100644 --- a/unit-tests/api/craig-api.test.js +++ b/unit-tests/api/craig-api.test.js @@ -95,7 +95,7 @@ describe("craig api", () => { }, { name: "craig/craig.json", - data: '{\n "_options": {\n "prefix": "iac",\n "region": "us-south",\n "tags": [\n "hello",\n "world"\n ],\n "zones": 3,\n "endpoints": "private",\n "account_id": null,\n "fs_cloud": false,\n "enable_classic": false,\n "dynamic_subnets": true,\n "enable_power_vs": false,\n "power_vs_zones": [],\n "craig_version": "1.12.0",\n "power_vs_high_availability": false,\n "no_vpn_secrets_manager_auth": false,\n "power_vs_ha_zone_1": null,\n "power_vs_ha_zone_2": null\n },\n "access_groups": [],\n "appid": [],\n "atracker": {\n "enabled": true,\n "type": "cos",\n "name": "atracker",\n "target_name": "atracker-cos",\n "bucket": "atracker-bucket",\n "add_route": true,\n "cos_key": "cos-bind-key",\n "locations": [\n "global",\n "us-south"\n ],\n "instance": false,\n "plan": "lite",\n "resource_group": null,\n "archive": false\n },\n "cbr_rules": [],\n "cbr_zones": [],\n "classic_ssh_keys": [],\n "classic_vlans": [],\n "clusters": [\n {\n "kms": "kms",\n "cos": "cos",\n "entitlement": "cloud_pak",\n "kube_type": "openshift",\n "kube_version": "4.12.26_openshift",\n "flavor": "bx2.16x64",\n "name": "workload-cluster",\n "resource_group": "workload-rg",\n "encryption_key": "roks-key",\n "subnets": [\n "vsi-zone-1",\n "vsi-zone-2",\n "vsi-zone-3"\n ],\n "update_all_workers": false,\n "vpc": "workload",\n "worker_pools": [\n {\n "entitlement": "cloud_pak",\n "cluster": "workload-cluster",\n "flavor": "bx2.16x64",\n "name": "logging-worker-pool",\n "resource_group": "workload-rg",\n "subnets": [\n "vsi-zone-1",\n "vsi-zone-2",\n "vsi-zone-3"\n ],\n "vpc": "workload",\n "workers_per_subnet": 2\n }\n ],\n "opaque_secrets": [],\n "workers_per_subnet": 2,\n "private_endpoint": true\n }\n ],\n "dns": [],\n "event_streams": [],\n "f5_vsi": [],\n "iam_account_settings": {\n "enable": false,\n "mfa": null,\n "allowed_ip_addresses": null,\n "include_history": false,\n "if_match": null,\n "max_sessions_per_identity": null,\n "restrict_create_service_id": null,\n "restrict_create_platform_apikey": null,\n "session_expiration_in_seconds": null,\n "session_invalidation_in_seconds": null\n },\n "icd": [],\n "key_management": [\n {\n "name": "kms",\n "resource_group": "service-rg",\n "use_hs_crypto": false,\n "authorize_vpc_reader_role": true,\n "use_data": false,\n "keys": [\n {\n "key_ring": "ring",\n "name": "key",\n "root_key": true,\n "force_delete": true,\n "endpoint": "public",\n "rotation": 1,\n "dual_auth_delete": false\n },\n {\n "key_ring": "ring",\n "name": "atracker-key",\n "root_key": true,\n "force_delete": true,\n "endpoint": "public",\n "rotation": 1,\n "dual_auth_delete": false\n },\n {\n "key_ring": "ring",\n "name": "vsi-volume-key",\n "root_key": true,\n "force_delete": true,\n "endpoint": "public",\n "rotation": 1,\n "dual_auth_delete": false\n },\n {\n "key_ring": "ring",\n "name": "roks-key",\n "root_key": true,\n "force_delete": null,\n "endpoint": null,\n "rotation": 1,\n "dual_auth_delete": false\n }\n ]\n }\n ],\n "load_balancers": [],\n "logdna": {\n "name": "logdna",\n "archive": false,\n "enabled": false,\n "plan": "lite",\n "endpoints": "private",\n "platform_logs": false,\n "resource_group": "service-rg",\n "cos": "atracker-cos",\n "bucket": "atracker-bucket"\n },\n "object_storage": [\n {\n "buckets": [\n {\n "endpoint": "public",\n "force_delete": true,\n "kms_key": "atracker-key",\n "name": "atracker-bucket",\n "storage_class": "standard",\n "use_random_suffix": true\n }\n ],\n "keys": [\n {\n "name": "cos-bind-key",\n "role": "Writer",\n "enable_hmac": false,\n "use_random_suffix": true\n }\n ],\n "name": "atracker-cos",\n "plan": "standard",\n "resource_group": "service-rg",\n "use_data": false,\n "use_random_suffix": true,\n "kms": "kms"\n },\n {\n "buckets": [\n {\n "endpoint": "public",\n "force_delete": true,\n "kms_key": "key",\n "name": "management-bucket",\n "storage_class": "standard",\n "use_random_suffix": true\n },\n {\n "endpoint": "public",\n "force_delete": true,\n "kms_key": "key",\n "name": "workload-bucket",\n "storage_class": "standard",\n "use_random_suffix": true\n }\n ],\n "use_random_suffix": true,\n "keys": [],\n "name": "cos",\n "plan": "standard",\n "resource_group": "service-rg",\n "use_data": false,\n "kms": "kms"\n }\n ],\n "power": [],\n "power_instances": [],\n "power_volumes": [],\n "resource_groups": [\n {\n "use_prefix": true,\n "name": "service-rg",\n "use_data": false\n },\n {\n "use_prefix": true,\n "name": "management-rg",\n "use_data": false\n },\n {\n "use_prefix": true,\n "name": "workload-rg",\n "use_data": false\n }\n ],\n "routing_tables": [],\n "scc": {\n "credential_description": null,\n "id": null,\n "passphrase": null,\n "name": "",\n "location": "us",\n "collector_description": null,\n "is_public": false,\n "scope_description": null,\n "enable": false\n },\n "secrets_manager": [],\n "security_groups": [\n {\n "vpc": "management",\n "name": "management-vpe",\n "resource_group": "management-rg",\n "rules": [\n {\n "vpc": "management",\n "sg": "management-vpe",\n "direction": "inbound",\n "name": "allow-ibm-inbound",\n "source": "161.26.0.0/16",\n "tcp": {\n "port_max": null,\n "port_min": null\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n },\n {\n "vpc": "management",\n "sg": "management-vpe",\n "direction": "inbound",\n "name": "allow-vpc-inbound",\n "source": "10.0.0.0/8",\n "tcp": {\n "port_max": null,\n "port_min": null\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n },\n {\n "vpc": "management",\n "sg": "management-vpe",\n "direction": "outbound",\n "name": "allow-vpc-outbound",\n "source": "10.0.0.0/8",\n "tcp": {\n "port_max": null,\n "port_min": null\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n },\n {\n "vpc": "management",\n "sg": "management-vpe",\n "direction": "outbound",\n "name": "allow-ibm-tcp-53-outbound",\n "source": "161.26.0.0/16",\n "tcp": {\n "port_max": 53,\n "port_min": 53\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "tcp",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n },\n {\n "vpc": "management",\n "sg": "management-vpe",\n "direction": "outbound",\n "name": "allow-ibm-tcp-80-outbound",\n "source": "161.26.0.0/16",\n "tcp": {\n "port_max": 80,\n "port_min": 80\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "tcp",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n },\n {\n "vpc": "management",\n "sg": "management-vpe",\n "direction": "outbound",\n "name": "allow-ibm-tcp-443-outbound",\n "source": "161.26.0.0/16",\n "tcp": {\n "port_max": 443,\n "port_min": 443\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "tcp",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n }\n ],\n "use_data": false\n },\n {\n "vpc": "workload",\n "name": "workload-vpe",\n "resource_group": "workload-rg",\n "rules": [\n {\n "vpc": "workload",\n "sg": "workload-vpe",\n "direction": "inbound",\n "name": "allow-ibm-inbound",\n "source": "161.26.0.0/16",\n "tcp": {\n "port_max": null,\n "port_min": null\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n },\n {\n "vpc": "workload",\n "sg": "workload-vpe",\n "direction": "inbound",\n "name": "allow-vpc-inbound",\n "source": "10.0.0.0/8",\n "tcp": {\n "port_max": null,\n "port_min": null\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n },\n {\n "vpc": "workload",\n "sg": "workload-vpe",\n "direction": "outbound",\n "name": "allow-vpc-outbound",\n "source": "10.0.0.0/8",\n "tcp": {\n "port_max": null,\n "port_min": null\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n },\n {\n "vpc": "workload",\n "sg": "workload-vpe",\n "direction": "outbound",\n "name": "allow-ibm-tcp-53-outbound",\n "source": "161.26.0.0/16",\n "tcp": {\n "port_max": 53,\n "port_min": 53\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "tcp",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n },\n {\n "vpc": "workload",\n "sg": "workload-vpe",\n "direction": "outbound",\n "name": "allow-ibm-tcp-80-outbound",\n "source": "161.26.0.0/16",\n "tcp": {\n "port_max": 80,\n "port_min": 80\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "tcp",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n },\n {\n "vpc": "workload",\n "sg": "workload-vpe",\n "direction": "outbound",\n "name": "allow-ibm-tcp-443-outbound",\n "source": "161.26.0.0/16",\n "tcp": {\n "port_max": 443,\n "port_min": 443\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "tcp",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n }\n ],\n "use_data": false\n },\n {\n "vpc": "management",\n "name": "management-vsi",\n "resource_group": "management-rg",\n "rules": [\n {\n "vpc": "management",\n "sg": "management-vsi",\n "direction": "inbound",\n "name": "allow-ibm-inbound",\n "source": "161.26.0.0/16",\n "tcp": {\n "port_max": null,\n "port_min": null\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n },\n {\n "vpc": "management",\n "sg": "management-vsi",\n "direction": "inbound",\n "name": "allow-vpc-inbound",\n "source": "10.0.0.0/8",\n "tcp": {\n "port_max": null,\n "port_min": null\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n },\n {\n "vpc": "management",\n "sg": "management-vsi",\n "direction": "outbound",\n "name": "allow-vpc-outbound",\n "source": "10.0.0.0/8",\n "tcp": {\n "port_max": null,\n "port_min": null\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n },\n {\n "vpc": "management",\n "sg": "management-vsi",\n "direction": "outbound",\n "name": "allow-ibm-tcp-53-outbound",\n "source": "161.26.0.0/16",\n "tcp": {\n "port_max": 53,\n "port_min": 53\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "tcp",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n },\n {\n "vpc": "management",\n "sg": "management-vsi",\n "direction": "outbound",\n "name": "allow-ibm-tcp-80-outbound",\n "source": "161.26.0.0/16",\n "tcp": {\n "port_max": 80,\n "port_min": 80\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "tcp",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n },\n {\n "vpc": "management",\n "sg": "management-vsi",\n "direction": "outbound",\n "name": "allow-ibm-tcp-443-outbound",\n "source": "161.26.0.0/16",\n "tcp": {\n "port_max": 443,\n "port_min": 443\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "tcp",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n }\n ],\n "use_data": false\n }\n ],\n "ssh_keys": [\n {\n "name": "ssh-key",\n "public_key": null,\n "resource_group": "management-rg",\n "use_data": false\n }\n ],\n "sysdig": {\n "enabled": false,\n "plan": "graduated-tier",\n "resource_group": "service-rg",\n "name": "sysdig",\n "platform_logs": false\n },\n "teleport_vsi": [],\n "transit_gateways": [\n {\n "name": "transit-gateway",\n "resource_group": "service-rg",\n "global": false,\n "connections": [\n {\n "tgw": "transit-gateway",\n "vpc": "management"\n },\n {\n "tgw": "transit-gateway",\n "vpc": "workload"\n }\n ],\n "use_data": false,\n "prefix_filters": [],\n "gre_tunnels": [],\n "crns": null,\n "classic": false\n }\n ],\n "virtual_private_endpoints": [\n {\n "name": "management-cos",\n "service": "cos",\n "vpc": "management",\n "resource_group": "management-rg",\n "security_groups": [\n "management-vpe"\n ],\n "subnets": [\n "vpe-zone-1",\n "vpe-zone-2",\n "vpe-zone-3"\n ],\n "instance": null\n },\n {\n "name": "workload-cos",\n "service": "cos",\n "vpc": "workload",\n "resource_group": "workload-rg",\n "security_groups": [\n "workload-vpe"\n ],\n "subnets": [\n "vpe-zone-1",\n "vpe-zone-2",\n "vpe-zone-3"\n ],\n "instance": null\n }\n ],\n "vpcs": [\n {\n "cos": "cos",\n "bucket": "management-bucket",\n "name": "management",\n "resource_group": "management-rg",\n "classic_access": false,\n "manual_address_prefix_management": true,\n "default_network_acl_name": null,\n "default_security_group_name": null,\n "default_routing_table_name": null,\n "publicGateways": [],\n "address_prefixes": [\n {\n "vpc": "management",\n "zone": 1,\n "name": "management-zone-1",\n "cidr": "10.10.0.0/22"\n },\n {\n "vpc": "management",\n "zone": 2,\n "name": "management-zone-2",\n "cidr": "10.20.0.0/22"\n },\n {\n "vpc": "management",\n "zone": 3,\n "name": "management-zone-3",\n "cidr": "10.30.0.0/22"\n }\n ],\n "subnets": [\n {\n "vpc": "management",\n "zone": 1,\n "cidr": "10.10.0.0/29",\n "name": "vsi-zone-1",\n "network_acl": "management",\n "resource_group": "management-rg",\n "public_gateway": false,\n "has_prefix": false\n },\n {\n "vpc": "management",\n "zone": 1,\n "cidr": "10.10.0.16/28",\n "name": "vpn-zone-1",\n "network_acl": "management",\n "resource_group": "management-rg",\n "public_gateway": false,\n "has_prefix": false\n },\n {\n "vpc": "management",\n "zone": 2,\n "cidr": "10.20.0.0/29",\n "name": "vsi-zone-2",\n "network_acl": "management",\n "resource_group": "management-rg",\n "public_gateway": false,\n "has_prefix": false\n },\n {\n "vpc": "management",\n "zone": 3,\n "cidr": "10.30.0.0/29",\n "name": "vsi-zone-3",\n "network_acl": "management",\n "resource_group": "management-rg",\n "public_gateway": false,\n "has_prefix": false\n },\n {\n "vpc": "management",\n "zone": 1,\n "cidr": "10.10.0.48/29",\n "name": "vpe-zone-1",\n "resource_group": "management-rg",\n "network_acl": "management",\n "public_gateway": false,\n "has_prefix": false\n },\n {\n "vpc": "management",\n "zone": 2,\n "cidr": "10.20.0.16/29",\n "name": "vpe-zone-2",\n "network_acl": "management",\n "resource_group": "management-rg",\n "public_gateway": false,\n "has_prefix": false\n },\n {\n "vpc": "management",\n "zone": 3,\n "cidr": "10.30.0.16/29",\n "name": "vpe-zone-3",\n "network_acl": "management",\n "resource_group": "management-rg",\n "public_gateway": false,\n "has_prefix": false\n }\n ],\n "public_gateways": [],\n "acls": [\n {\n "resource_group": "management-rg",\n "name": "management",\n "vpc": "management",\n "rules": [\n {\n "action": "allow",\n "destination": "10.0.0.0/8",\n "direction": "inbound",\n "name": "allow-ibm-inbound",\n "source": "161.26.0.0/16",\n "acl": "management",\n "vpc": "management",\n "icmp": {\n "type": null,\n "code": null\n },\n "tcp": {\n "port_min": null,\n "port_max": null,\n "source_port_min": null,\n "source_port_max": null\n },\n "udp": {\n "port_min": null,\n "port_max": null,\n "source_port_min": null,\n "source_port_max": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null,\n "source_port_min": null,\n "source_port_max": null\n },\n {\n "action": "allow",\n "source": "10.0.0.0/8",\n "direction": "outbound",\n "name": "allow-ibm-outbound",\n "destination": "161.26.0.0/16",\n "acl": "management",\n "vpc": "management",\n "icmp": {\n "type": null,\n "code": null\n },\n "tcp": {\n "port_min": null,\n "port_max": null,\n "source_port_min": null,\n "source_port_max": null\n },\n "udp": {\n "port_min": null,\n "port_max": null,\n "source_port_min": null,\n "source_port_max": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null,\n "source_port_min": null,\n "source_port_max": null\n },\n {\n "action": "allow",\n "destination": "10.0.0.0/8",\n "direction": "inbound",\n "name": "allow-all-network-inbound",\n "source": "10.0.0.0/8",\n "acl": "management",\n "vpc": "management",\n "icmp": {\n "type": null,\n "code": null\n },\n "tcp": {\n "port_min": null,\n "port_max": null,\n "source_port_min": null,\n "source_port_max": null\n },\n "udp": {\n "port_min": null,\n "port_max": null,\n "source_port_min": null,\n "source_port_max": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null,\n "source_port_min": null,\n "source_port_max": null\n },\n {\n "action": "allow",\n "destination": "10.0.0.0/8",\n "direction": "outbound",\n "name": "allow-all-network-outbound",\n "source": "10.0.0.0/8",\n "acl": "management",\n "vpc": "management",\n "icmp": {\n "type": null,\n "code": null\n },\n "tcp": {\n "port_min": null,\n "port_max": null,\n "source_port_min": null,\n "source_port_max": null\n },\n "udp": {\n "port_min": null,\n "port_max": null,\n "source_port_min": null,\n "source_port_max": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null,\n "source_port_min": null,\n "source_port_max": null\n }\n ],\n "use_data": false\n }\n ],\n "subnetTiers": [\n {\n "name": "vsi",\n "zones": 3\n },\n {\n "name": "vpn",\n "zones": 1\n },\n {\n "name": "vpe",\n "zones": 3\n }\n ],\n "use_data": false\n },\n {\n "cos": "cos",\n "bucket": "workload-bucket",\n "name": "workload",\n "resource_group": "workload-rg",\n "classic_access": false,\n "manual_address_prefix_management": true,\n "default_network_acl_name": null,\n "default_security_group_name": null,\n "default_routing_table_name": null,\n "publicGateways": [],\n "address_prefixes": [\n {\n "vpc": "workload",\n "zone": 1,\n "name": "workload-zone-1",\n "cidr": "10.40.0.0/22"\n },\n {\n "vpc": "workload",\n "zone": 2,\n "name": "workload-zone-2",\n "cidr": "10.50.0.0/22"\n },\n {\n "vpc": "workload",\n "zone": 3,\n "name": "workload-zone-3",\n "cidr": "10.60.0.0/22"\n }\n ],\n "subnets": [\n {\n "vpc": "workload",\n "zone": 1,\n "cidr": "10.40.0.0/28",\n "name": "vsi-zone-1",\n "network_acl": "workload",\n "resource_group": "workload-rg",\n "public_gateway": false,\n "has_prefix": false\n },\n {\n "vpc": "workload",\n "zone": 2,\n "cidr": "10.50.0.0/28",\n "name": "vsi-zone-2",\n "network_acl": "workload",\n "resource_group": "workload-rg",\n "public_gateway": false,\n "has_prefix": false\n },\n {\n "vpc": "workload",\n "zone": 3,\n "cidr": "10.60.0.0/28",\n "name": "vsi-zone-3",\n "network_acl": "workload",\n "resource_group": "workload-rg",\n "public_gateway": false,\n "has_prefix": false\n },\n {\n "vpc": "workload",\n "zone": 1,\n "cidr": "10.40.0.32/29",\n "name": "vpe-zone-1",\n "network_acl": "workload",\n "resource_group": "workload-rg",\n "public_gateway": false,\n "has_prefix": false\n },\n {\n "vpc": "workload",\n "zone": 2,\n "cidr": "10.50.0.32/29",\n "name": "vpe-zone-2",\n "network_acl": "workload",\n "resource_group": "workload-rg",\n "public_gateway": false,\n "has_prefix": false\n },\n {\n "vpc": "workload",\n "zone": 3,\n "cidr": "10.60.0.32/29",\n "name": "vpe-zone-3",\n "network_acl": "workload",\n "resource_group": "workload-rg",\n "public_gateway": false,\n "has_prefix": false\n }\n ],\n "public_gateways": [],\n "acls": [\n {\n "resource_group": "workload-rg",\n "name": "workload",\n "vpc": "workload",\n "rules": [\n {\n "action": "allow",\n "destination": "10.0.0.0/8",\n "direction": "inbound",\n "name": "allow-ibm-inbound",\n "source": "161.26.0.0/16",\n "acl": "workload",\n "vpc": "workload",\n "icmp": {\n "type": null,\n "code": null\n },\n "tcp": {\n "port_min": null,\n "port_max": null,\n "source_port_min": null,\n "source_port_max": null\n },\n "udp": {\n "port_min": null,\n "port_max": null,\n "source_port_min": null,\n "source_port_max": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null,\n "source_port_min": null,\n "source_port_max": null\n },\n {\n "action": "allow",\n "source": "10.0.0.0/8",\n "direction": "outbound",\n "name": "allow-ibm-outbound",\n "destination": "161.26.0.0/16",\n "acl": "workload",\n "vpc": "workload",\n "icmp": {\n "type": null,\n "code": null\n },\n "tcp": {\n "port_min": null,\n "port_max": null,\n "source_port_min": null,\n "source_port_max": null\n },\n "udp": {\n "port_min": null,\n "port_max": null,\n "source_port_min": null,\n "source_port_max": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null,\n "source_port_min": null,\n "source_port_max": null\n },\n {\n "action": "allow",\n "destination": "10.0.0.0/8",\n "direction": "inbound",\n "name": "allow-all-network-inbound",\n "source": "10.0.0.0/8",\n "acl": "workload",\n "vpc": "workload",\n "icmp": {\n "type": null,\n "code": null\n },\n "tcp": {\n "port_min": null,\n "port_max": null,\n "source_port_min": null,\n "source_port_max": null\n },\n "udp": {\n "port_min": null,\n "port_max": null,\n "source_port_min": null,\n "source_port_max": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null,\n "source_port_min": null,\n "source_port_max": null\n },\n {\n "action": "allow",\n "destination": "10.0.0.0/8",\n "direction": "outbound",\n "name": "allow-all-network-outbound",\n "source": "10.0.0.0/8",\n "acl": "workload",\n "vpc": "workload",\n "icmp": {\n "type": null,\n "code": null\n },\n "tcp": {\n "port_min": null,\n "port_max": null,\n "source_port_min": null,\n "source_port_max": null\n },\n "udp": {\n "port_min": null,\n "port_max": null,\n "source_port_min": null,\n "source_port_max": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null,\n "source_port_min": null,\n "source_port_max": null\n }\n ],\n "use_data": false\n }\n ],\n "subnetTiers": [\n {\n "name": "vsi",\n "zones": 3\n },\n {\n "name": "vpe",\n "zones": 3\n }\n ],\n "use_data": false\n }\n ],\n "vpn_gateways": [\n {\n "name": "management-gateway",\n "resource_group": "management-rg",\n "subnet": "vpn-zone-1",\n "vpc": "management",\n "connections": [],\n "policy_mode": false,\n "additional_prefixes": []\n }\n ],\n "vpn_servers": [],\n "vsi": [\n {\n "kms": "kms",\n "encryption_key": "vsi-volume-key",\n "image": "ibm-ubuntu-22-04-1-minimal-amd64-1",\n "profile": "cx2-4x8",\n "name": "management-server",\n "security_groups": [\n "management-vsi"\n ],\n "ssh_keys": [\n "ssh-key"\n ],\n "subnets": [\n "vsi-zone-1",\n "vsi-zone-2",\n "vsi-zone-3"\n ],\n "vpc": "management",\n "vsi_per_subnet": 2,\n "resource_group": "management-rg",\n "override_vsi_name": null,\n "user_data": null,\n "network_interfaces": [],\n "volumes": [],\n "image_name": null,\n "enable_floating_ip": false,\n "primary_interface_ip_spoofing": false\n }\n ]\n}', + data: '{\n \"_options\": {\n \"prefix\": \"iac\",\n \"region\": \"us-south\",\n \"tags\": [\n \"hello\",\n \"world\"\n ],\n \"zones\": 3,\n \"endpoints\": \"private\",\n \"account_id\": null,\n \"fs_cloud\": false,\n \"enable_classic\": false,\n \"dynamic_subnets\": true,\n \"enable_power_vs\": false,\n \"power_vs_zones\": [],\n \"craig_version\": \"1.12.0\",\n \"power_vs_high_availability\": false,\n \"no_vpn_secrets_manager_auth\": false,\n \"power_vs_ha_zone_1\": null,\n \"power_vs_ha_zone_2\": null,\n \"manual_power_vsi_naming\": false\n },\n \"access_groups\": [],\n \"appid\": [],\n \"atracker\": {\n \"enabled\": true,\n \"type\": \"cos\",\n \"name\": \"atracker\",\n \"target_name\": \"atracker-cos\",\n \"bucket\": \"atracker-bucket\",\n \"add_route\": true,\n \"cos_key\": \"cos-bind-key\",\n \"locations\": [\n \"global\",\n \"us-south\"\n ],\n \"instance\": false,\n \"plan\": \"lite\",\n \"resource_group\": null,\n \"archive\": false\n },\n \"cbr_rules\": [],\n \"cbr_zones\": [],\n \"classic_ssh_keys\": [],\n \"classic_vlans\": [],\n \"clusters\": [\n {\n \"kms\": \"kms\",\n \"cos\": \"cos\",\n \"entitlement\": \"cloud_pak\",\n \"kube_type\": \"openshift\",\n \"kube_version\": \"4.12.26_openshift\",\n \"flavor\": \"bx2.16x64\",\n \"name\": \"workload-cluster\",\n \"resource_group\": \"workload-rg\",\n \"encryption_key\": \"roks-key\",\n \"subnets\": [\n \"vsi-zone-1\",\n \"vsi-zone-2\",\n \"vsi-zone-3\"\n ],\n \"update_all_workers\": false,\n \"vpc\": \"workload\",\n \"worker_pools\": [\n {\n \"entitlement\": \"cloud_pak\",\n \"cluster\": \"workload-cluster\",\n \"flavor\": \"bx2.16x64\",\n \"name\": \"logging-worker-pool\",\n \"resource_group\": \"workload-rg\",\n \"subnets\": [\n \"vsi-zone-1\",\n \"vsi-zone-2\",\n \"vsi-zone-3\"\n ],\n \"vpc\": \"workload\",\n \"workers_per_subnet\": 2\n }\n ],\n \"opaque_secrets\": [],\n \"workers_per_subnet\": 2,\n \"private_endpoint\": true\n }\n ],\n \"dns\": [],\n \"event_streams\": [],\n \"f5_vsi\": [],\n \"iam_account_settings\": {\n \"enable\": false,\n \"mfa\": null,\n \"allowed_ip_addresses\": null,\n \"include_history\": false,\n \"if_match\": null,\n \"max_sessions_per_identity\": null,\n \"restrict_create_service_id\": null,\n \"restrict_create_platform_apikey\": null,\n \"session_expiration_in_seconds\": null,\n \"session_invalidation_in_seconds\": null\n },\n \"icd\": [],\n \"key_management\": [\n {\n \"name\": \"kms\",\n \"resource_group\": \"service-rg\",\n \"use_hs_crypto\": false,\n \"authorize_vpc_reader_role\": true,\n \"use_data\": false,\n \"keys\": [\n {\n \"key_ring\": \"ring\",\n \"name\": \"key\",\n \"root_key\": true,\n \"force_delete\": true,\n \"endpoint\": \"public\",\n \"rotation\": 1,\n \"dual_auth_delete\": false\n },\n {\n \"key_ring\": \"ring\",\n \"name\": \"atracker-key\",\n \"root_key\": true,\n \"force_delete\": true,\n \"endpoint\": \"public\",\n \"rotation\": 1,\n \"dual_auth_delete\": false\n },\n {\n \"key_ring\": \"ring\",\n \"name\": \"vsi-volume-key\",\n \"root_key\": true,\n \"force_delete\": true,\n \"endpoint\": \"public\",\n \"rotation\": 1,\n \"dual_auth_delete\": false\n },\n {\n \"key_ring\": \"ring\",\n \"name\": \"roks-key\",\n \"root_key\": true,\n \"force_delete\": null,\n \"endpoint\": null,\n \"rotation\": 1,\n \"dual_auth_delete\": false\n }\n ]\n }\n ],\n \"load_balancers\": [],\n \"logdna\": {\n \"name\": \"logdna\",\n \"archive\": false,\n \"enabled\": false,\n \"plan\": \"lite\",\n \"endpoints\": \"private\",\n \"platform_logs\": false,\n \"resource_group\": \"service-rg\",\n \"cos\": \"atracker-cos\",\n \"bucket\": \"atracker-bucket\"\n },\n \"object_storage\": [\n {\n \"buckets\": [\n {\n \"endpoint\": \"public\",\n \"force_delete\": true,\n \"kms_key\": \"atracker-key\",\n \"name\": \"atracker-bucket\",\n \"storage_class\": \"standard\",\n \"use_random_suffix\": true\n }\n ],\n \"keys\": [\n {\n \"name\": \"cos-bind-key\",\n \"role\": \"Writer\",\n \"enable_hmac\": false,\n \"use_random_suffix\": true\n }\n ],\n \"name\": \"atracker-cos\",\n \"plan\": \"standard\",\n \"resource_group\": \"service-rg\",\n \"use_data\": false,\n \"use_random_suffix\": true,\n \"kms\": \"kms\"\n },\n {\n \"buckets\": [\n {\n \"endpoint\": \"public\",\n \"force_delete\": true,\n \"kms_key\": \"key\",\n \"name\": \"management-bucket\",\n \"storage_class\": \"standard\",\n \"use_random_suffix\": true\n },\n {\n \"endpoint\": \"public\",\n \"force_delete\": true,\n \"kms_key\": \"key\",\n \"name\": \"workload-bucket\",\n \"storage_class\": \"standard\",\n \"use_random_suffix\": true\n }\n ],\n \"use_random_suffix\": true,\n \"keys\": [],\n \"name\": \"cos\",\n \"plan\": \"standard\",\n \"resource_group\": \"service-rg\",\n \"use_data\": false,\n \"kms\": \"kms\"\n }\n ],\n \"power\": [],\n \"power_instances\": [],\n \"power_volumes\": [],\n \"resource_groups\": [\n {\n \"use_prefix\": true,\n \"name\": \"service-rg\",\n \"use_data\": false\n },\n {\n \"use_prefix\": true,\n \"name\": \"management-rg\",\n \"use_data\": false\n },\n {\n \"use_prefix\": true,\n \"name\": \"workload-rg\",\n \"use_data\": false\n }\n ],\n \"routing_tables\": [],\n \"scc\": {\n \"credential_description\": null,\n \"id\": null,\n \"passphrase\": null,\n \"name\": \"\",\n \"location\": \"us\",\n \"collector_description\": null,\n \"is_public\": false,\n \"scope_description\": null,\n \"enable\": false\n },\n \"secrets_manager\": [],\n \"security_groups\": [\n {\n \"vpc\": \"management\",\n \"name\": \"management-vpe\",\n \"resource_group\": \"management-rg\",\n \"rules\": [\n {\n \"vpc\": \"management\",\n \"sg\": \"management-vpe\",\n \"direction\": \"inbound\",\n \"name\": \"allow-ibm-inbound\",\n \"source\": \"161.26.0.0/16\",\n \"tcp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n },\n {\n \"vpc\": \"management\",\n \"sg\": \"management-vpe\",\n \"direction\": \"inbound\",\n \"name\": \"allow-vpc-inbound\",\n \"source\": \"10.0.0.0/8\",\n \"tcp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n },\n {\n \"vpc\": \"management\",\n \"sg\": \"management-vpe\",\n \"direction\": \"outbound\",\n \"name\": \"allow-vpc-outbound\",\n \"source\": \"10.0.0.0/8\",\n \"tcp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n },\n {\n \"vpc\": \"management\",\n \"sg\": \"management-vpe\",\n \"direction\": \"outbound\",\n \"name\": \"allow-ibm-tcp-53-outbound\",\n \"source\": \"161.26.0.0/16\",\n \"tcp\": {\n \"port_max\": 53,\n \"port_min\": 53\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"tcp\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n },\n {\n \"vpc\": \"management\",\n \"sg\": \"management-vpe\",\n \"direction\": \"outbound\",\n \"name\": \"allow-ibm-tcp-80-outbound\",\n \"source\": \"161.26.0.0/16\",\n \"tcp\": {\n \"port_max\": 80,\n \"port_min\": 80\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"tcp\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n },\n {\n \"vpc\": \"management\",\n \"sg\": \"management-vpe\",\n \"direction\": \"outbound\",\n \"name\": \"allow-ibm-tcp-443-outbound\",\n \"source\": \"161.26.0.0/16\",\n \"tcp\": {\n \"port_max\": 443,\n \"port_min\": 443\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"tcp\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n }\n ],\n \"use_data\": false\n },\n {\n \"vpc\": \"workload\",\n \"name\": \"workload-vpe\",\n \"resource_group\": \"workload-rg\",\n \"rules\": [\n {\n \"vpc\": \"workload\",\n \"sg\": \"workload-vpe\",\n \"direction\": \"inbound\",\n \"name\": \"allow-ibm-inbound\",\n \"source\": \"161.26.0.0/16\",\n \"tcp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n },\n {\n \"vpc\": \"workload\",\n \"sg\": \"workload-vpe\",\n \"direction\": \"inbound\",\n \"name\": \"allow-vpc-inbound\",\n \"source\": \"10.0.0.0/8\",\n \"tcp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n },\n {\n \"vpc\": \"workload\",\n \"sg\": \"workload-vpe\",\n \"direction\": \"outbound\",\n \"name\": \"allow-vpc-outbound\",\n \"source\": \"10.0.0.0/8\",\n \"tcp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n },\n {\n \"vpc\": \"workload\",\n \"sg\": \"workload-vpe\",\n \"direction\": \"outbound\",\n \"name\": \"allow-ibm-tcp-53-outbound\",\n \"source\": \"161.26.0.0/16\",\n \"tcp\": {\n \"port_max\": 53,\n \"port_min\": 53\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"tcp\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n },\n {\n \"vpc\": \"workload\",\n \"sg\": \"workload-vpe\",\n \"direction\": \"outbound\",\n \"name\": \"allow-ibm-tcp-80-outbound\",\n \"source\": \"161.26.0.0/16\",\n \"tcp\": {\n \"port_max\": 80,\n \"port_min\": 80\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"tcp\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n },\n {\n \"vpc\": \"workload\",\n \"sg\": \"workload-vpe\",\n \"direction\": \"outbound\",\n \"name\": \"allow-ibm-tcp-443-outbound\",\n \"source\": \"161.26.0.0/16\",\n \"tcp\": {\n \"port_max\": 443,\n \"port_min\": 443\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"tcp\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n }\n ],\n \"use_data\": false\n },\n {\n \"vpc\": \"management\",\n \"name\": \"management-vsi\",\n \"resource_group\": \"management-rg\",\n \"rules\": [\n {\n \"vpc\": \"management\",\n \"sg\": \"management-vsi\",\n \"direction\": \"inbound\",\n \"name\": \"allow-ibm-inbound\",\n \"source\": \"161.26.0.0/16\",\n \"tcp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n },\n {\n \"vpc\": \"management\",\n \"sg\": \"management-vsi\",\n \"direction\": \"inbound\",\n \"name\": \"allow-vpc-inbound\",\n \"source\": \"10.0.0.0/8\",\n \"tcp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n },\n {\n \"vpc\": \"management\",\n \"sg\": \"management-vsi\",\n \"direction\": \"outbound\",\n \"name\": \"allow-vpc-outbound\",\n \"source\": \"10.0.0.0/8\",\n \"tcp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n },\n {\n \"vpc\": \"management\",\n \"sg\": \"management-vsi\",\n \"direction\": \"outbound\",\n \"name\": \"allow-ibm-tcp-53-outbound\",\n \"source\": \"161.26.0.0/16\",\n \"tcp\": {\n \"port_max\": 53,\n \"port_min\": 53\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"tcp\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n },\n {\n \"vpc\": \"management\",\n \"sg\": \"management-vsi\",\n \"direction\": \"outbound\",\n \"name\": \"allow-ibm-tcp-80-outbound\",\n \"source\": \"161.26.0.0/16\",\n \"tcp\": {\n \"port_max\": 80,\n \"port_min\": 80\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"tcp\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n },\n {\n \"vpc\": \"management\",\n \"sg\": \"management-vsi\",\n \"direction\": \"outbound\",\n \"name\": \"allow-ibm-tcp-443-outbound\",\n \"source\": \"161.26.0.0/16\",\n \"tcp\": {\n \"port_max\": 443,\n \"port_min\": 443\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"tcp\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n }\n ],\n \"use_data\": false\n }\n ],\n \"ssh_keys\": [\n {\n \"name\": \"ssh-key\",\n \"public_key\": null,\n \"resource_group\": \"management-rg\",\n \"use_data\": false\n }\n ],\n \"sysdig\": {\n \"enabled\": false,\n \"plan\": \"graduated-tier\",\n \"resource_group\": \"service-rg\",\n \"name\": \"sysdig\",\n \"platform_logs\": false\n },\n \"teleport_vsi\": [],\n \"transit_gateways\": [\n {\n \"name\": \"transit-gateway\",\n \"resource_group\": \"service-rg\",\n \"global\": false,\n \"connections\": [\n {\n \"tgw\": \"transit-gateway\",\n \"vpc\": \"management\"\n },\n {\n \"tgw\": \"transit-gateway\",\n \"vpc\": \"workload\"\n }\n ],\n \"use_data\": false,\n \"prefix_filters\": [],\n \"gre_tunnels\": [],\n \"crns\": null,\n \"classic\": false\n }\n ],\n \"virtual_private_endpoints\": [\n {\n \"name\": \"management-cos\",\n \"service\": \"cos\",\n \"vpc\": \"management\",\n \"resource_group\": \"management-rg\",\n \"security_groups\": [\n \"management-vpe\"\n ],\n \"subnets\": [\n \"vpe-zone-1\",\n \"vpe-zone-2\",\n \"vpe-zone-3\"\n ],\n \"instance\": null\n },\n {\n \"name\": \"workload-cos\",\n \"service\": \"cos\",\n \"vpc\": \"workload\",\n \"resource_group\": \"workload-rg\",\n \"security_groups\": [\n \"workload-vpe\"\n ],\n \"subnets\": [\n \"vpe-zone-1\",\n \"vpe-zone-2\",\n \"vpe-zone-3\"\n ],\n \"instance\": null\n }\n ],\n \"vpcs\": [\n {\n \"cos\": \"cos\",\n \"bucket\": \"management-bucket\",\n \"name\": \"management\",\n \"resource_group\": \"management-rg\",\n \"classic_access\": false,\n \"manual_address_prefix_management\": true,\n \"default_network_acl_name\": null,\n \"default_security_group_name\": null,\n \"default_routing_table_name\": null,\n \"publicGateways\": [],\n \"address_prefixes\": [\n {\n \"vpc\": \"management\",\n \"zone\": 1,\n \"name\": \"management-zone-1\",\n \"cidr\": \"10.10.0.0/22\"\n },\n {\n \"vpc\": \"management\",\n \"zone\": 2,\n \"name\": \"management-zone-2\",\n \"cidr\": \"10.20.0.0/22\"\n },\n {\n \"vpc\": \"management\",\n \"zone\": 3,\n \"name\": \"management-zone-3\",\n \"cidr\": \"10.30.0.0/22\"\n }\n ],\n \"subnets\": [\n {\n \"vpc\": \"management\",\n \"zone\": 1,\n \"cidr\": \"10.10.0.0/29\",\n \"name\": \"vsi-zone-1\",\n \"network_acl\": \"management\",\n \"resource_group\": \"management-rg\",\n \"public_gateway\": false,\n \"has_prefix\": false\n },\n {\n \"vpc\": \"management\",\n \"zone\": 1,\n \"cidr\": \"10.10.0.16/28\",\n \"name\": \"vpn-zone-1\",\n \"network_acl\": \"management\",\n \"resource_group\": \"management-rg\",\n \"public_gateway\": false,\n \"has_prefix\": false\n },\n {\n \"vpc\": \"management\",\n \"zone\": 2,\n \"cidr\": \"10.20.0.0/29\",\n \"name\": \"vsi-zone-2\",\n \"network_acl\": \"management\",\n \"resource_group\": \"management-rg\",\n \"public_gateway\": false,\n \"has_prefix\": false\n },\n {\n \"vpc\": \"management\",\n \"zone\": 3,\n \"cidr\": \"10.30.0.0/29\",\n \"name\": \"vsi-zone-3\",\n \"network_acl\": \"management\",\n \"resource_group\": \"management-rg\",\n \"public_gateway\": false,\n \"has_prefix\": false\n },\n {\n \"vpc\": \"management\",\n \"zone\": 1,\n \"cidr\": \"10.10.0.48/29\",\n \"name\": \"vpe-zone-1\",\n \"resource_group\": \"management-rg\",\n \"network_acl\": \"management\",\n \"public_gateway\": false,\n \"has_prefix\": false\n },\n {\n \"vpc\": \"management\",\n \"zone\": 2,\n \"cidr\": \"10.20.0.16/29\",\n \"name\": \"vpe-zone-2\",\n \"network_acl\": \"management\",\n \"resource_group\": \"management-rg\",\n \"public_gateway\": false,\n \"has_prefix\": false\n },\n {\n \"vpc\": \"management\",\n \"zone\": 3,\n \"cidr\": \"10.30.0.16/29\",\n \"name\": \"vpe-zone-3\",\n \"network_acl\": \"management\",\n \"resource_group\": \"management-rg\",\n \"public_gateway\": false,\n \"has_prefix\": false\n }\n ],\n \"public_gateways\": [],\n \"acls\": [\n {\n \"resource_group\": \"management-rg\",\n \"name\": \"management\",\n \"vpc\": \"management\",\n \"rules\": [\n {\n \"action\": \"allow\",\n \"destination\": \"10.0.0.0/8\",\n \"direction\": \"inbound\",\n \"name\": \"allow-ibm-inbound\",\n \"source\": \"161.26.0.0/16\",\n \"acl\": \"management\",\n \"vpc\": \"management\",\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"tcp\": {\n \"port_min\": null,\n \"port_max\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n \"udp\": {\n \"port_min\": null,\n \"port_max\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n {\n \"action\": \"allow\",\n \"source\": \"10.0.0.0/8\",\n \"direction\": \"outbound\",\n \"name\": \"allow-ibm-outbound\",\n \"destination\": \"161.26.0.0/16\",\n \"acl\": \"management\",\n \"vpc\": \"management\",\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"tcp\": {\n \"port_min\": null,\n \"port_max\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n \"udp\": {\n \"port_min\": null,\n \"port_max\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n {\n \"action\": \"allow\",\n \"destination\": \"10.0.0.0/8\",\n \"direction\": \"inbound\",\n \"name\": \"allow-all-network-inbound\",\n \"source\": \"10.0.0.0/8\",\n \"acl\": \"management\",\n \"vpc\": \"management\",\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"tcp\": {\n \"port_min\": null,\n \"port_max\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n \"udp\": {\n \"port_min\": null,\n \"port_max\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n {\n \"action\": \"allow\",\n \"destination\": \"10.0.0.0/8\",\n \"direction\": \"outbound\",\n \"name\": \"allow-all-network-outbound\",\n \"source\": \"10.0.0.0/8\",\n \"acl\": \"management\",\n \"vpc\": \"management\",\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"tcp\": {\n \"port_min\": null,\n \"port_max\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n \"udp\": {\n \"port_min\": null,\n \"port_max\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n }\n ],\n \"use_data\": false\n }\n ],\n \"subnetTiers\": [\n {\n \"name\": \"vsi\",\n \"zones\": 3\n },\n {\n \"name\": \"vpn\",\n \"zones\": 1\n },\n {\n \"name\": \"vpe\",\n \"zones\": 3\n }\n ],\n \"use_data\": false\n },\n {\n \"cos\": \"cos\",\n \"bucket\": \"workload-bucket\",\n \"name\": \"workload\",\n \"resource_group\": \"workload-rg\",\n \"classic_access\": false,\n \"manual_address_prefix_management\": true,\n \"default_network_acl_name\": null,\n \"default_security_group_name\": null,\n \"default_routing_table_name\": null,\n \"publicGateways\": [],\n \"address_prefixes\": [\n {\n \"vpc\": \"workload\",\n \"zone\": 1,\n \"name\": \"workload-zone-1\",\n \"cidr\": \"10.40.0.0/22\"\n },\n {\n \"vpc\": \"workload\",\n \"zone\": 2,\n \"name\": \"workload-zone-2\",\n \"cidr\": \"10.50.0.0/22\"\n },\n {\n \"vpc\": \"workload\",\n \"zone\": 3,\n \"name\": \"workload-zone-3\",\n \"cidr\": \"10.60.0.0/22\"\n }\n ],\n \"subnets\": [\n {\n \"vpc\": \"workload\",\n \"zone\": 1,\n \"cidr\": \"10.40.0.0/28\",\n \"name\": \"vsi-zone-1\",\n \"network_acl\": \"workload\",\n \"resource_group\": \"workload-rg\",\n \"public_gateway\": false,\n \"has_prefix\": false\n },\n {\n \"vpc\": \"workload\",\n \"zone\": 2,\n \"cidr\": \"10.50.0.0/28\",\n \"name\": \"vsi-zone-2\",\n \"network_acl\": \"workload\",\n \"resource_group\": \"workload-rg\",\n \"public_gateway\": false,\n \"has_prefix\": false\n },\n {\n \"vpc\": \"workload\",\n \"zone\": 3,\n \"cidr\": \"10.60.0.0/28\",\n \"name\": \"vsi-zone-3\",\n \"network_acl\": \"workload\",\n \"resource_group\": \"workload-rg\",\n \"public_gateway\": false,\n \"has_prefix\": false\n },\n {\n \"vpc\": \"workload\",\n \"zone\": 1,\n \"cidr\": \"10.40.0.32/29\",\n \"name\": \"vpe-zone-1\",\n \"network_acl\": \"workload\",\n \"resource_group\": \"workload-rg\",\n \"public_gateway\": false,\n \"has_prefix\": false\n },\n {\n \"vpc\": \"workload\",\n \"zone\": 2,\n \"cidr\": \"10.50.0.32/29\",\n \"name\": \"vpe-zone-2\",\n \"network_acl\": \"workload\",\n \"resource_group\": \"workload-rg\",\n \"public_gateway\": false,\n \"has_prefix\": false\n },\n {\n \"vpc\": \"workload\",\n \"zone\": 3,\n \"cidr\": \"10.60.0.32/29\",\n \"name\": \"vpe-zone-3\",\n \"network_acl\": \"workload\",\n \"resource_group\": \"workload-rg\",\n \"public_gateway\": false,\n \"has_prefix\": false\n }\n ],\n \"public_gateways\": [],\n \"acls\": [\n {\n \"resource_group\": \"workload-rg\",\n \"name\": \"workload\",\n \"vpc\": \"workload\",\n \"rules\": [\n {\n \"action\": \"allow\",\n \"destination\": \"10.0.0.0/8\",\n \"direction\": \"inbound\",\n \"name\": \"allow-ibm-inbound\",\n \"source\": \"161.26.0.0/16\",\n \"acl\": \"workload\",\n \"vpc\": \"workload\",\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"tcp\": {\n \"port_min\": null,\n \"port_max\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n \"udp\": {\n \"port_min\": null,\n \"port_max\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n {\n \"action\": \"allow\",\n \"source\": \"10.0.0.0/8\",\n \"direction\": \"outbound\",\n \"name\": \"allow-ibm-outbound\",\n \"destination\": \"161.26.0.0/16\",\n \"acl\": \"workload\",\n \"vpc\": \"workload\",\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"tcp\": {\n \"port_min\": null,\n \"port_max\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n \"udp\": {\n \"port_min\": null,\n \"port_max\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n {\n \"action\": \"allow\",\n \"destination\": \"10.0.0.0/8\",\n \"direction\": \"inbound\",\n \"name\": \"allow-all-network-inbound\",\n \"source\": \"10.0.0.0/8\",\n \"acl\": \"workload\",\n \"vpc\": \"workload\",\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"tcp\": {\n \"port_min\": null,\n \"port_max\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n \"udp\": {\n \"port_min\": null,\n \"port_max\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n {\n \"action\": \"allow\",\n \"destination\": \"10.0.0.0/8\",\n \"direction\": \"outbound\",\n \"name\": \"allow-all-network-outbound\",\n \"source\": \"10.0.0.0/8\",\n \"acl\": \"workload\",\n \"vpc\": \"workload\",\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"tcp\": {\n \"port_min\": null,\n \"port_max\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n \"udp\": {\n \"port_min\": null,\n \"port_max\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n }\n ],\n \"use_data\": false\n }\n ],\n \"subnetTiers\": [\n {\n \"name\": \"vsi\",\n \"zones\": 3\n },\n {\n \"name\": \"vpe\",\n \"zones\": 3\n }\n ],\n \"use_data\": false\n }\n ],\n \"vpn_gateways\": [\n {\n \"name\": \"management-gateway\",\n \"resource_group\": \"management-rg\",\n \"subnet\": \"vpn-zone-1\",\n \"vpc\": \"management\",\n \"connections\": [],\n \"policy_mode\": false,\n \"additional_prefixes\": []\n }\n ],\n \"vpn_servers\": [],\n \"vsi\": [\n {\n \"kms\": \"kms\",\n \"encryption_key\": \"vsi-volume-key\",\n \"image\": \"ibm-ubuntu-22-04-1-minimal-amd64-1\",\n \"profile\": \"cx2-4x8\",\n \"name\": \"management-server\",\n \"security_groups\": [\n \"management-vsi\"\n ],\n \"ssh_keys\": [\n \"ssh-key\"\n ],\n \"subnets\": [\n \"vsi-zone-1\",\n \"vsi-zone-2\",\n \"vsi-zone-3\"\n ],\n \"vpc\": \"management\",\n \"vsi_per_subnet\": 2,\n \"resource_group\": \"management-rg\",\n \"override_vsi_name\": null,\n \"user_data\": null,\n \"network_interfaces\": [],\n \"volumes\": [],\n \"image_name\": null,\n \"enable_floating_ip\": false,\n \"primary_interface_ip_spoofing\": false\n }\n ]\n}' }, { data: ' Apache License\nVersion 2.0, January 2004\nhttp://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n\n"License" shall mean the terms and conditions for use, reproduction,\nand distribution as defined by Sections 1 through 9 of this document.\n\n"Licensor" shall mean the copyright owner or entity authorized by\nthe copyright owner that is granting the License.\n\n"Legal Entity" shall mean the union of the acting entity and all\nother entities that control, are controlled by, or are under common\ncontrol with that entity. For the purposes of this definition,\n"control" means (i) the power, direct or indirect, to cause the\ndirection or management of such entity, whether by contract or\notherwise, or (ii) ownership of fifty percent (50%) or more of the\noutstanding shares, or (iii) beneficial ownership of such entity.\n\n"You" (or "Your") shall mean an individual or Legal Entity\nexercising permissions granted by this License.\n\n"Source" form shall mean the preferred form for making modifications,\nincluding but not limited to software source code, documentation\nsource, and configuration files.\n\n"Object" form shall mean any form resulting from mechanical\ntransformation or translation of a Source form, including but\nnot limited to compiled object code, generated documentation,\nand conversions to other media types.\n\n"Work" shall mean the work of authorship, whether in Source or\nObject form, made available under the License, as indicated by a\ncopyright notice that is included in or attached to the work\n(an example is provided in the Appendix below).\n\n"Derivative Works" shall mean any work, whether in Source or Object\nform, that is based on (or derived from) the Work and for which the\neditorial revisions, annotations, elaborations, or other modifications\nrepresent, as a whole, an original work of authorship. For the purposes\nof this License, Derivative Works shall not include works that remain\nseparable from, or merely link (or bind by name) to the interfaces of,\nthe Work and Derivative Works thereof.\n\n"Contribution" shall mean any work of authorship, including\nthe original version of the Work and any modifications or additions\nto that Work or Derivative Works thereof, that is intentionally\nsubmitted to Licensor for inclusion in the Work by the copyright owner\nor by an individual or Legal Entity authorized to submit on behalf of\nthe copyright owner. For the purposes of this definition, "submitted"\nmeans any form of electronic, verbal, or written communication sent\nto the Licensor or its representatives, including but not limited to\ncommunication on electronic mailing lists, source code control systems,\nand issue tracking systems that are managed by, or on behalf of, the\nLicensor for the purpose of discussing and improving the Work, but\nexcluding communication that is conspicuously marked or otherwise\ndesignated in writing by the copyright owner as "Not a Contribution."\n\n"Contributor" shall mean Licensor and any individual or Legal Entity\non behalf of whom a Contribution has been received by Licensor and\nsubsequently incorporated within the Work.\n\n2. Grant of Copyright License. Subject to the terms and conditions of\nthis License, each Contributor hereby grants to You a perpetual,\nworldwide, non-exclusive, no-charge, royalty-free, irrevocable\ncopyright license to reproduce, prepare Derivative Works of,\npublicly display, publicly perform, sublicense, and distribute the\nWork and such Derivative Works in Source or Object form.\n\n3. Grant of Patent License. Subject to the terms and conditions of\nthis License, each Contributor hereby grants to You a perpetual,\nworldwide, non-exclusive, no-charge, royalty-free, irrevocable\n(except as stated in this section) patent license to make, have made,\nuse, offer to sell, sell, import, and otherwise transfer the Work,\nwhere such license applies only to those patent claims licensable\nby such Contributor that are necessarily infringed by their\nContribution(s) alone or by combination of their Contribution(s)\nwith the Work to which such Contribution(s) was submitted. If You\ninstitute patent litigation against any entity (including a\ncross-claim or counterclaim in a lawsuit) alleging that the Work\nor a Contribution incorporated within the Work constitutes direct\nor contributory patent infringement, then any patent licenses\ngranted to You under this License for that Work shall terminate\nas of the date such litigation is filed.\n\n4. Redistribution. You may reproduce and distribute copies of the\nWork or Derivative Works thereof in any medium, with or without\nmodifications, and in Source or Object form, provided that You\nmeet the following conditions:\n\n(a) You must give any other recipients of the Work or\nDerivative Works a copy of this License; and\n\n(b) You must cause any modified files to carry prominent notices\nstating that You changed the files; and\n\n(c) You must retain, in the Source form of any Derivative Works\nthat You distribute, all copyright, patent, trademark, and\nattribution notices from the Source form of the Work,\nexcluding those notices that do not pertain to any part of\nthe Derivative Works; and\n\n(d) If the Work includes a "NOTICE" text file as part of its\ndistribution, then any Derivative Works that You distribute must\ninclude a readable copy of the attribution notices contained\nwithin such NOTICE file, excluding those notices that do not\npertain to any part of the Derivative Works, in at least one\nof the following places: within a NOTICE text file distributed\nas part of the Derivative Works; within the Source form or\ndocumentation, if provided along with the Derivative Works; or,\nwithin a display generated by the Derivative Works, if and\nwherever such third-party notices normally appear. The contents\nof the NOTICE file are for informational purposes only and\ndo not modify the License. You may add Your own attribution\nnotices within Derivative Works that You distribute, alongside\nor as an addendum to the NOTICE text from the Work, provided\nthat such additional attribution notices cannot be construed\nas modifying the License.\n\nYou may add Your own copyright statement to Your modifications and\nmay provide additional or different license terms and conditions\nfor use, reproduction, or distribution of Your modifications, or\nfor any such Derivative Works as a whole, provided Your use,\nreproduction, and distribution of the Work otherwise complies with\nthe conditions stated in this License.\n\n5. Submission of Contributions. Unless You explicitly state otherwise,\nany Contribution intentionally submitted for inclusion in the Work\nby You to the Licensor shall be under the terms and conditions of\nthis License, without any additional terms or conditions.\nNotwithstanding the above, nothing herein shall supersede or modify\nthe terms of any separate license agreement you may have executed\nwith Licensor regarding such Contributions.\n\n6. Trademarks. This License does not grant permission to use the trade\nnames, trademarks, service marks, or product names of the Licensor,\nexcept as required for reasonable and customary use in describing the\norigin of the Work and reproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty. Unless required by applicable law or\nagreed to in writing, Licensor provides the Work (and each\nContributor provides its Contributions) on an "AS IS" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\nimplied, including, without limitation, any warranties or conditions\nof TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\nPARTICULAR PURPOSE. You are solely responsible for determining the\nappropriateness of using or redistributing the Work and assume any\nrisks associated with Your exercise of permissions under this License.\n\n8. Limitation of Liability. In no event and under no legal theory,\nwhether in tort (including negligence), contract, or otherwise,\nunless required by applicable law (such as deliberate and grossly\nnegligent acts) or agreed to in writing, shall any Contributor be\nliable to You for damages, including any direct, indirect, special,\nincidental, or consequential damages of any character arising as a\nresult of this License or out of the use or inability to use the\nWork (including but not limited to damages for loss of goodwill,\nwork stoppage, computer failure or malfunction, or any and all\nother commercial damages or losses), even if such Contributor\nhas been advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability. While redistributing\nthe Work or Derivative Works thereof, You may choose to offer,\nand charge a fee for, acceptance of support, warranty, indemnity,\nor other liability obligations and/or rights consistent with this\nLicense. However, in accepting such obligations, You may act only\non Your own behalf and on Your sole responsibility, not on behalf\nof any other Contributor, and only if You agree to indemnify,\ndefend, and hold each Contributor harmless for any liability\nincurred by, or claims asserted against, such Contributor by reason\nof your accepting any such warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n\nAPPENDIX: How to apply the Apache License to your work.\n\nTo apply the Apache License to your work, attach the following\nboilerplate notice, with the fields enclosed by brackets "[]"\nreplaced with your own identifying information. (Don\'t include\nthe brackets!) The text should be enclosed in the appropriate\ncomment syntax for the file format. We also recommend that a\nfile or class name and description of purpose be included on the\nsame "printed page" as the copyright notice for easier\nidentification within third-party archives.\n\nCopyright [yyyy] [name of copyright owner]\n\nLicensed under the Apache License, Version 2.0 (the "License");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an "AS IS" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n', @@ -276,7 +276,7 @@ describe("craig api", () => { }, { name: "from-scratch/craig.json", - data: '{\n "_options": {\n "prefix": "iac",\n "region": "us-south",\n "tags": [\n "hello",\n "world"\n ],\n "zones": 3,\n "endpoints": "private",\n "account_id": null,\n "fs_cloud": false,\n "enable_classic": false,\n "dynamic_subnets": true,\n "enable_power_vs": false,\n "craig_version": "1.12.0",\n "power_vs_zones": [],\n "power_vs_high_availability": false,\n "no_vpn_secrets_manager_auth": false,\n "power_vs_ha_zone_1": null,\n "power_vs_ha_zone_2": null\n },\n "access_groups": [],\n "appid": [],\n "atracker": {\n "enabled": false,\n "type": "cos",\n "name": "atracker",\n "target_name": "atracker-cos",\n "bucket": null,\n "add_route": true,\n "cos_key": null,\n "locations": [\n "global",\n "us-south"\n ],\n "instance": false,\n "plan": "lite",\n "resource_group": null,\n "archive": false\n },\n "cbr_rules": [],\n "cbr_zones": [],\n "classic_ssh_keys": [],\n "classic_vlans": [],\n "clusters": [],\n "dns": [],\n "event_streams": [],\n "f5_vsi": [],\n "iam_account_settings": {\n "enable": false,\n "mfa": null,\n "allowed_ip_addresses": null,\n "include_history": false,\n "if_match": null,\n "max_sessions_per_identity": null,\n "restrict_create_service_id": null,\n "restrict_create_platform_apikey": null,\n "session_expiration_in_seconds": null,\n "session_invalidation_in_seconds": null\n },\n "icd": [],\n "key_management": [],\n "load_balancers": [],\n "logdna": {\n "name": "logdna",\n "archive": false,\n "enabled": false,\n "plan": "lite",\n "endpoints": "private",\n "platform_logs": false,\n "resource_group": null,\n "cos": null,\n "bucket": null\n },\n "object_storage": [],\n "power": [],\n "power_instances": [],\n "power_volumes": [],\n "resource_groups": [\n {\n "use_prefix": true,\n "name": "craig-rg",\n "use_data": false\n }\n ],\n "routing_tables": [],\n "scc": {\n "credential_description": null,\n "id": null,\n "passphrase": null,\n "name": "",\n "location": "us",\n "collector_description": null,\n "is_public": false,\n "scope_description": null,\n "enable": false\n },\n "secrets_manager": [],\n "security_groups": [],\n "ssh_keys": [],\n "sysdig": {\n "enabled": false,\n "plan": "graduated-tier",\n "resource_group": null,\n "name": "sysdig",\n "platform_logs": false\n },\n "teleport_vsi": [],\n "transit_gateways": [],\n "virtual_private_endpoints": [],\n "vpcs": [],\n "vpn_gateways": [],\n "vpn_servers": [],\n "vsi": []\n}', + data: '{\n \"_options\": {\n \"prefix\": \"iac\",\n \"region\": \"us-south\",\n \"tags\": [\n \"hello\",\n \"world\"\n ],\n \"zones\": 3,\n \"endpoints\": \"private\",\n \"account_id\": null,\n \"fs_cloud\": false,\n \"enable_classic\": false,\n \"dynamic_subnets\": true,\n \"enable_power_vs\": false,\n \"craig_version\": \"1.12.0\",\n \"power_vs_zones\": [],\n \"power_vs_high_availability\": false,\n \"no_vpn_secrets_manager_auth\": false,\n \"power_vs_ha_zone_1\": null,\n \"power_vs_ha_zone_2\": null,\n \"manual_power_vsi_naming\": false\n },\n \"access_groups\": [],\n \"appid\": [],\n \"atracker\": {\n \"enabled\": false,\n \"type\": \"cos\",\n \"name\": \"atracker\",\n \"target_name\": \"atracker-cos\",\n \"bucket\": null,\n \"add_route\": true,\n \"cos_key\": null,\n \"locations\": [\n \"global\",\n \"us-south\"\n ],\n \"instance\": false,\n \"plan\": \"lite\",\n \"resource_group\": null,\n \"archive\": false\n },\n \"cbr_rules\": [],\n \"cbr_zones\": [],\n \"classic_ssh_keys\": [],\n \"classic_vlans\": [],\n \"clusters\": [],\n \"dns\": [],\n \"event_streams\": [],\n \"f5_vsi\": [],\n \"iam_account_settings\": {\n \"enable\": false,\n \"mfa\": null,\n \"allowed_ip_addresses\": null,\n \"include_history\": false,\n \"if_match\": null,\n \"max_sessions_per_identity\": null,\n \"restrict_create_service_id\": null,\n \"restrict_create_platform_apikey\": null,\n \"session_expiration_in_seconds\": null,\n \"session_invalidation_in_seconds\": null\n },\n \"icd\": [],\n \"key_management\": [],\n \"load_balancers\": [],\n \"logdna\": {\n \"name\": \"logdna\",\n \"archive\": false,\n \"enabled\": false,\n \"plan\": \"lite\",\n \"endpoints\": \"private\",\n \"platform_logs\": false,\n \"resource_group\": null,\n \"cos\": null,\n \"bucket\": null\n },\n \"object_storage\": [],\n \"power\": [],\n \"power_instances\": [],\n \"power_volumes\": [],\n \"resource_groups\": [\n {\n \"use_prefix\": true,\n \"name\": \"craig-rg\",\n \"use_data\": false\n }\n ],\n \"routing_tables\": [],\n \"scc\": {\n \"credential_description\": null,\n \"id\": null,\n \"passphrase\": null,\n \"name\": \"\",\n \"location\": \"us\",\n \"collector_description\": null,\n \"is_public\": false,\n \"scope_description\": null,\n \"enable\": false\n },\n \"secrets_manager\": [],\n \"security_groups\": [],\n \"ssh_keys\": [],\n \"sysdig\": {\n \"enabled\": false,\n \"plan\": \"graduated-tier\",\n \"resource_group\": null,\n \"name\": \"sysdig\",\n \"platform_logs\": false\n },\n \"teleport_vsi\": [],\n \"transit_gateways\": [],\n \"virtual_private_endpoints\": [],\n \"vpcs\": [],\n \"vpn_gateways\": [],\n \"vpn_servers\": [],\n \"vsi\": []\n}' }, { data: ' Apache License\nVersion 2.0, January 2004\nhttp://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n\n"License" shall mean the terms and conditions for use, reproduction,\nand distribution as defined by Sections 1 through 9 of this document.\n\n"Licensor" shall mean the copyright owner or entity authorized by\nthe copyright owner that is granting the License.\n\n"Legal Entity" shall mean the union of the acting entity and all\nother entities that control, are controlled by, or are under common\ncontrol with that entity. For the purposes of this definition,\n"control" means (i) the power, direct or indirect, to cause the\ndirection or management of such entity, whether by contract or\notherwise, or (ii) ownership of fifty percent (50%) or more of the\noutstanding shares, or (iii) beneficial ownership of such entity.\n\n"You" (or "Your") shall mean an individual or Legal Entity\nexercising permissions granted by this License.\n\n"Source" form shall mean the preferred form for making modifications,\nincluding but not limited to software source code, documentation\nsource, and configuration files.\n\n"Object" form shall mean any form resulting from mechanical\ntransformation or translation of a Source form, including but\nnot limited to compiled object code, generated documentation,\nand conversions to other media types.\n\n"Work" shall mean the work of authorship, whether in Source or\nObject form, made available under the License, as indicated by a\ncopyright notice that is included in or attached to the work\n(an example is provided in the Appendix below).\n\n"Derivative Works" shall mean any work, whether in Source or Object\nform, that is based on (or derived from) the Work and for which the\neditorial revisions, annotations, elaborations, or other modifications\nrepresent, as a whole, an original work of authorship. For the purposes\nof this License, Derivative Works shall not include works that remain\nseparable from, or merely link (or bind by name) to the interfaces of,\nthe Work and Derivative Works thereof.\n\n"Contribution" shall mean any work of authorship, including\nthe original version of the Work and any modifications or additions\nto that Work or Derivative Works thereof, that is intentionally\nsubmitted to Licensor for inclusion in the Work by the copyright owner\nor by an individual or Legal Entity authorized to submit on behalf of\nthe copyright owner. For the purposes of this definition, "submitted"\nmeans any form of electronic, verbal, or written communication sent\nto the Licensor or its representatives, including but not limited to\ncommunication on electronic mailing lists, source code control systems,\nand issue tracking systems that are managed by, or on behalf of, the\nLicensor for the purpose of discussing and improving the Work, but\nexcluding communication that is conspicuously marked or otherwise\ndesignated in writing by the copyright owner as "Not a Contribution."\n\n"Contributor" shall mean Licensor and any individual or Legal Entity\non behalf of whom a Contribution has been received by Licensor and\nsubsequently incorporated within the Work.\n\n2. Grant of Copyright License. Subject to the terms and conditions of\nthis License, each Contributor hereby grants to You a perpetual,\nworldwide, non-exclusive, no-charge, royalty-free, irrevocable\ncopyright license to reproduce, prepare Derivative Works of,\npublicly display, publicly perform, sublicense, and distribute the\nWork and such Derivative Works in Source or Object form.\n\n3. Grant of Patent License. Subject to the terms and conditions of\nthis License, each Contributor hereby grants to You a perpetual,\nworldwide, non-exclusive, no-charge, royalty-free, irrevocable\n(except as stated in this section) patent license to make, have made,\nuse, offer to sell, sell, import, and otherwise transfer the Work,\nwhere such license applies only to those patent claims licensable\nby such Contributor that are necessarily infringed by their\nContribution(s) alone or by combination of their Contribution(s)\nwith the Work to which such Contribution(s) was submitted. If You\ninstitute patent litigation against any entity (including a\ncross-claim or counterclaim in a lawsuit) alleging that the Work\nor a Contribution incorporated within the Work constitutes direct\nor contributory patent infringement, then any patent licenses\ngranted to You under this License for that Work shall terminate\nas of the date such litigation is filed.\n\n4. Redistribution. You may reproduce and distribute copies of the\nWork or Derivative Works thereof in any medium, with or without\nmodifications, and in Source or Object form, provided that You\nmeet the following conditions:\n\n(a) You must give any other recipients of the Work or\nDerivative Works a copy of this License; and\n\n(b) You must cause any modified files to carry prominent notices\nstating that You changed the files; and\n\n(c) You must retain, in the Source form of any Derivative Works\nthat You distribute, all copyright, patent, trademark, and\nattribution notices from the Source form of the Work,\nexcluding those notices that do not pertain to any part of\nthe Derivative Works; and\n\n(d) If the Work includes a "NOTICE" text file as part of its\ndistribution, then any Derivative Works that You distribute must\ninclude a readable copy of the attribution notices contained\nwithin such NOTICE file, excluding those notices that do not\npertain to any part of the Derivative Works, in at least one\nof the following places: within a NOTICE text file distributed\nas part of the Derivative Works; within the Source form or\ndocumentation, if provided along with the Derivative Works; or,\nwithin a display generated by the Derivative Works, if and\nwherever such third-party notices normally appear. The contents\nof the NOTICE file are for informational purposes only and\ndo not modify the License. You may add Your own attribution\nnotices within Derivative Works that You distribute, alongside\nor as an addendum to the NOTICE text from the Work, provided\nthat such additional attribution notices cannot be construed\nas modifying the License.\n\nYou may add Your own copyright statement to Your modifications and\nmay provide additional or different license terms and conditions\nfor use, reproduction, or distribution of Your modifications, or\nfor any such Derivative Works as a whole, provided Your use,\nreproduction, and distribution of the Work otherwise complies with\nthe conditions stated in this License.\n\n5. Submission of Contributions. Unless You explicitly state otherwise,\nany Contribution intentionally submitted for inclusion in the Work\nby You to the Licensor shall be under the terms and conditions of\nthis License, without any additional terms or conditions.\nNotwithstanding the above, nothing herein shall supersede or modify\nthe terms of any separate license agreement you may have executed\nwith Licensor regarding such Contributions.\n\n6. Trademarks. This License does not grant permission to use the trade\nnames, trademarks, service marks, or product names of the Licensor,\nexcept as required for reasonable and customary use in describing the\norigin of the Work and reproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty. Unless required by applicable law or\nagreed to in writing, Licensor provides the Work (and each\nContributor provides its Contributions) on an "AS IS" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\nimplied, including, without limitation, any warranties or conditions\nof TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\nPARTICULAR PURPOSE. You are solely responsible for determining the\nappropriateness of using or redistributing the Work and assume any\nrisks associated with Your exercise of permissions under this License.\n\n8. Limitation of Liability. In no event and under no legal theory,\nwhether in tort (including negligence), contract, or otherwise,\nunless required by applicable law (such as deliberate and grossly\nnegligent acts) or agreed to in writing, shall any Contributor be\nliable to You for damages, including any direct, indirect, special,\nincidental, or consequential damages of any character arising as a\nresult of this License or out of the use or inability to use the\nWork (including but not limited to damages for loss of goodwill,\nwork stoppage, computer failure or malfunction, or any and all\nother commercial damages or losses), even if such Contributor\nhas been advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability. While redistributing\nthe Work or Derivative Works thereof, You may choose to offer,\nand charge a fee for, acceptance of support, warranty, indemnity,\nor other liability obligations and/or rights consistent with this\nLicense. However, in accepting such obligations, You may act only\non Your own behalf and on Your sole responsibility, not on behalf\nof any other Contributor, and only if You agree to indemnify,\ndefend, and hold each Contributor harmless for any liability\nincurred by, or claims asserted against, such Contributor by reason\nof your accepting any such warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n\nAPPENDIX: How to apply the Apache License to your work.\n\nTo apply the Apache License to your work, attach the following\nboilerplate notice, with the fields enclosed by brackets "[]"\nreplaced with your own identifying information. (Don\'t include\nthe brackets!) The text should be enclosed in the appropriate\ncomment syntax for the file format. We also recommend that a\nfile or class name and description of purpose be included on the\nsame "printed page" as the copyright notice for easier\nidentification within third-party archives.\n\nCopyright [yyyy] [name of copyright owner]\n\nLicensed under the Apache License, Version 2.0 (the "License");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an "AS IS" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n', @@ -443,7 +443,7 @@ describe("craig api", () => { }, { name: "from-scratch/craig.json", - data: '{\n "_options": {\n "prefix": "iac",\n "region": "us-south",\n "tags": [\n "hello",\n "world"\n ],\n "zones": 3,\n "endpoints": "private",\n "account_id": null,\n "fs_cloud": false,\n "enable_classic": false,\n "dynamic_subnets": true,\n "enable_power_vs": false,\n "craig_version": "1.12.0",\n "power_vs_zones": [],\n "power_vs_high_availability": false,\n "no_vpn_secrets_manager_auth": false,\n "power_vs_ha_zone_1": null,\n "power_vs_ha_zone_2": null\n },\n "access_groups": [],\n "appid": [],\n "atracker": {\n "enabled": false,\n "type": "cos",\n "name": "atracker",\n "target_name": "atracker-cos",\n "bucket": null,\n "add_route": true,\n "cos_key": null,\n "locations": [\n "global",\n "us-south"\n ],\n "instance": false,\n "plan": "lite",\n "resource_group": null,\n "archive": false\n },\n "cbr_rules": [],\n "cbr_zones": [],\n "classic_ssh_keys": [],\n "classic_vlans": [],\n "clusters": [],\n "dns": [],\n "event_streams": [],\n "f5_vsi": [],\n "iam_account_settings": {\n "enable": false,\n "mfa": null,\n "allowed_ip_addresses": null,\n "include_history": false,\n "if_match": null,\n "max_sessions_per_identity": null,\n "restrict_create_service_id": null,\n "restrict_create_platform_apikey": null,\n "session_expiration_in_seconds": null,\n "session_invalidation_in_seconds": null\n },\n "icd": [],\n "key_management": [],\n "load_balancers": [],\n "logdna": {\n "name": "logdna",\n "archive": false,\n "enabled": false,\n "plan": "lite",\n "endpoints": "private",\n "platform_logs": false,\n "resource_group": null,\n "cos": null,\n "bucket": null\n },\n "object_storage": [],\n "power": [],\n "power_instances": [],\n "power_volumes": [],\n "resource_groups": [\n {\n "use_prefix": true,\n "name": "craig-rg",\n "use_data": false\n },\n {\n "use_prefix": true,\n "name": "added-rg",\n "use_data": false\n }\n ],\n "routing_tables": [],\n "scc": {\n "credential_description": null,\n "id": null,\n "passphrase": null,\n "name": "",\n "location": "us",\n "collector_description": null,\n "is_public": false,\n "scope_description": null,\n "enable": false\n },\n "secrets_manager": [],\n "security_groups": [],\n "ssh_keys": [],\n "sysdig": {\n "enabled": false,\n "plan": "graduated-tier",\n "resource_group": null,\n "name": "sysdig",\n "platform_logs": false\n },\n "teleport_vsi": [],\n "transit_gateways": [],\n "virtual_private_endpoints": [],\n "vpcs": [],\n "vpn_gateways": [],\n "vpn_servers": [],\n "vsi": []\n}', + data: '{\n \"_options\": {\n \"prefix\": \"iac\",\n \"region\": \"us-south\",\n \"tags\": [\n \"hello\",\n \"world\"\n ],\n \"zones\": 3,\n \"endpoints\": \"private\",\n \"account_id\": null,\n \"fs_cloud\": false,\n \"enable_classic\": false,\n \"dynamic_subnets\": true,\n \"enable_power_vs\": false,\n \"craig_version\": \"1.12.0\",\n \"power_vs_zones\": [],\n \"power_vs_high_availability\": false,\n \"no_vpn_secrets_manager_auth\": false,\n \"power_vs_ha_zone_1\": null,\n \"power_vs_ha_zone_2\": null,\n \"manual_power_vsi_naming\": false\n },\n \"access_groups\": [],\n \"appid\": [],\n \"atracker\": {\n \"enabled\": false,\n \"type\": \"cos\",\n \"name\": \"atracker\",\n \"target_name\": \"atracker-cos\",\n \"bucket\": null,\n \"add_route\": true,\n \"cos_key\": null,\n \"locations\": [\n \"global\",\n \"us-south\"\n ],\n \"instance\": false,\n \"plan\": \"lite\",\n \"resource_group\": null,\n \"archive\": false\n },\n \"cbr_rules\": [],\n \"cbr_zones\": [],\n \"classic_ssh_keys\": [],\n \"classic_vlans\": [],\n \"clusters\": [],\n \"dns\": [],\n \"event_streams\": [],\n \"f5_vsi\": [],\n \"iam_account_settings\": {\n \"enable\": false,\n \"mfa\": null,\n \"allowed_ip_addresses\": null,\n \"include_history\": false,\n \"if_match\": null,\n \"max_sessions_per_identity\": null,\n \"restrict_create_service_id\": null,\n \"restrict_create_platform_apikey\": null,\n \"session_expiration_in_seconds\": null,\n \"session_invalidation_in_seconds\": null\n },\n \"icd\": [],\n \"key_management\": [],\n \"load_balancers\": [],\n \"logdna\": {\n \"name\": \"logdna\",\n \"archive\": false,\n \"enabled\": false,\n \"plan\": \"lite\",\n \"endpoints\": \"private\",\n \"platform_logs\": false,\n \"resource_group\": null,\n \"cos\": null,\n \"bucket\": null\n },\n \"object_storage\": [],\n \"power\": [],\n \"power_instances\": [],\n \"power_volumes\": [],\n \"resource_groups\": [\n {\n \"use_prefix\": true,\n \"name\": \"craig-rg\",\n \"use_data\": false\n },\n {\n \"use_prefix\": true,\n \"name\": \"added-rg\",\n \"use_data\": false\n }\n ],\n \"routing_tables\": [],\n \"scc\": {\n \"credential_description\": null,\n \"id\": null,\n \"passphrase\": null,\n \"name\": \"\",\n \"location\": \"us\",\n \"collector_description\": null,\n \"is_public\": false,\n \"scope_description\": null,\n \"enable\": false\n },\n \"secrets_manager\": [],\n \"security_groups\": [],\n \"ssh_keys\": [],\n \"sysdig\": {\n \"enabled\": false,\n \"plan\": \"graduated-tier\",\n \"resource_group\": null,\n \"name\": \"sysdig\",\n \"platform_logs\": false\n },\n \"teleport_vsi\": [],\n \"transit_gateways\": [],\n \"virtual_private_endpoints\": [],\n \"vpcs\": [],\n \"vpn_gateways\": [],\n \"vpn_servers\": [],\n \"vsi\": []\n}' }, { data: ' Apache License\nVersion 2.0, January 2004\nhttp://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n\n"License" shall mean the terms and conditions for use, reproduction,\nand distribution as defined by Sections 1 through 9 of this document.\n\n"Licensor" shall mean the copyright owner or entity authorized by\nthe copyright owner that is granting the License.\n\n"Legal Entity" shall mean the union of the acting entity and all\nother entities that control, are controlled by, or are under common\ncontrol with that entity. For the purposes of this definition,\n"control" means (i) the power, direct or indirect, to cause the\ndirection or management of such entity, whether by contract or\notherwise, or (ii) ownership of fifty percent (50%) or more of the\noutstanding shares, or (iii) beneficial ownership of such entity.\n\n"You" (or "Your") shall mean an individual or Legal Entity\nexercising permissions granted by this License.\n\n"Source" form shall mean the preferred form for making modifications,\nincluding but not limited to software source code, documentation\nsource, and configuration files.\n\n"Object" form shall mean any form resulting from mechanical\ntransformation or translation of a Source form, including but\nnot limited to compiled object code, generated documentation,\nand conversions to other media types.\n\n"Work" shall mean the work of authorship, whether in Source or\nObject form, made available under the License, as indicated by a\ncopyright notice that is included in or attached to the work\n(an example is provided in the Appendix below).\n\n"Derivative Works" shall mean any work, whether in Source or Object\nform, that is based on (or derived from) the Work and for which the\neditorial revisions, annotations, elaborations, or other modifications\nrepresent, as a whole, an original work of authorship. For the purposes\nof this License, Derivative Works shall not include works that remain\nseparable from, or merely link (or bind by name) to the interfaces of,\nthe Work and Derivative Works thereof.\n\n"Contribution" shall mean any work of authorship, including\nthe original version of the Work and any modifications or additions\nto that Work or Derivative Works thereof, that is intentionally\nsubmitted to Licensor for inclusion in the Work by the copyright owner\nor by an individual or Legal Entity authorized to submit on behalf of\nthe copyright owner. For the purposes of this definition, "submitted"\nmeans any form of electronic, verbal, or written communication sent\nto the Licensor or its representatives, including but not limited to\ncommunication on electronic mailing lists, source code control systems,\nand issue tracking systems that are managed by, or on behalf of, the\nLicensor for the purpose of discussing and improving the Work, but\nexcluding communication that is conspicuously marked or otherwise\ndesignated in writing by the copyright owner as "Not a Contribution."\n\n"Contributor" shall mean Licensor and any individual or Legal Entity\non behalf of whom a Contribution has been received by Licensor and\nsubsequently incorporated within the Work.\n\n2. Grant of Copyright License. Subject to the terms and conditions of\nthis License, each Contributor hereby grants to You a perpetual,\nworldwide, non-exclusive, no-charge, royalty-free, irrevocable\ncopyright license to reproduce, prepare Derivative Works of,\npublicly display, publicly perform, sublicense, and distribute the\nWork and such Derivative Works in Source or Object form.\n\n3. Grant of Patent License. Subject to the terms and conditions of\nthis License, each Contributor hereby grants to You a perpetual,\nworldwide, non-exclusive, no-charge, royalty-free, irrevocable\n(except as stated in this section) patent license to make, have made,\nuse, offer to sell, sell, import, and otherwise transfer the Work,\nwhere such license applies only to those patent claims licensable\nby such Contributor that are necessarily infringed by their\nContribution(s) alone or by combination of their Contribution(s)\nwith the Work to which such Contribution(s) was submitted. If You\ninstitute patent litigation against any entity (including a\ncross-claim or counterclaim in a lawsuit) alleging that the Work\nor a Contribution incorporated within the Work constitutes direct\nor contributory patent infringement, then any patent licenses\ngranted to You under this License for that Work shall terminate\nas of the date such litigation is filed.\n\n4. Redistribution. You may reproduce and distribute copies of the\nWork or Derivative Works thereof in any medium, with or without\nmodifications, and in Source or Object form, provided that You\nmeet the following conditions:\n\n(a) You must give any other recipients of the Work or\nDerivative Works a copy of this License; and\n\n(b) You must cause any modified files to carry prominent notices\nstating that You changed the files; and\n\n(c) You must retain, in the Source form of any Derivative Works\nthat You distribute, all copyright, patent, trademark, and\nattribution notices from the Source form of the Work,\nexcluding those notices that do not pertain to any part of\nthe Derivative Works; and\n\n(d) If the Work includes a "NOTICE" text file as part of its\ndistribution, then any Derivative Works that You distribute must\ninclude a readable copy of the attribution notices contained\nwithin such NOTICE file, excluding those notices that do not\npertain to any part of the Derivative Works, in at least one\nof the following places: within a NOTICE text file distributed\nas part of the Derivative Works; within the Source form or\ndocumentation, if provided along with the Derivative Works; or,\nwithin a display generated by the Derivative Works, if and\nwherever such third-party notices normally appear. The contents\nof the NOTICE file are for informational purposes only and\ndo not modify the License. You may add Your own attribution\nnotices within Derivative Works that You distribute, alongside\nor as an addendum to the NOTICE text from the Work, provided\nthat such additional attribution notices cannot be construed\nas modifying the License.\n\nYou may add Your own copyright statement to Your modifications and\nmay provide additional or different license terms and conditions\nfor use, reproduction, or distribution of Your modifications, or\nfor any such Derivative Works as a whole, provided Your use,\nreproduction, and distribution of the Work otherwise complies with\nthe conditions stated in this License.\n\n5. Submission of Contributions. Unless You explicitly state otherwise,\nany Contribution intentionally submitted for inclusion in the Work\nby You to the Licensor shall be under the terms and conditions of\nthis License, without any additional terms or conditions.\nNotwithstanding the above, nothing herein shall supersede or modify\nthe terms of any separate license agreement you may have executed\nwith Licensor regarding such Contributions.\n\n6. Trademarks. This License does not grant permission to use the trade\nnames, trademarks, service marks, or product names of the Licensor,\nexcept as required for reasonable and customary use in describing the\norigin of the Work and reproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty. Unless required by applicable law or\nagreed to in writing, Licensor provides the Work (and each\nContributor provides its Contributions) on an "AS IS" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\nimplied, including, without limitation, any warranties or conditions\nof TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\nPARTICULAR PURPOSE. You are solely responsible for determining the\nappropriateness of using or redistributing the Work and assume any\nrisks associated with Your exercise of permissions under this License.\n\n8. Limitation of Liability. In no event and under no legal theory,\nwhether in tort (including negligence), contract, or otherwise,\nunless required by applicable law (such as deliberate and grossly\nnegligent acts) or agreed to in writing, shall any Contributor be\nliable to You for damages, including any direct, indirect, special,\nincidental, or consequential damages of any character arising as a\nresult of this License or out of the use or inability to use the\nWork (including but not limited to damages for loss of goodwill,\nwork stoppage, computer failure or malfunction, or any and all\nother commercial damages or losses), even if such Contributor\nhas been advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability. While redistributing\nthe Work or Derivative Works thereof, You may choose to offer,\nand charge a fee for, acceptance of support, warranty, indemnity,\nor other liability obligations and/or rights consistent with this\nLicense. However, in accepting such obligations, You may act only\non Your own behalf and on Your sole responsibility, not on behalf\nof any other Contributor, and only if You agree to indemnify,\ndefend, and hold each Contributor harmless for any liability\nincurred by, or claims asserted against, such Contributor by reason\nof your accepting any such warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n\nAPPENDIX: How to apply the Apache License to your work.\n\nTo apply the Apache License to your work, attach the following\nboilerplate notice, with the fields enclosed by brackets "[]"\nreplaced with your own identifying information. (Don\'t include\nthe brackets!) The text should be enclosed in the appropriate\ncomment syntax for the file format. We also recommend that a\nfile or class name and description of purpose be included on the\nsame "printed page" as the copyright notice for easier\nidentification within third-party archives.\n\nCopyright [yyyy] [name of copyright owner]\n\nLicensed under the Apache License, Version 2.0 (the "License");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an "AS IS" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n', diff --git a/unit-tests/json-to-iac/power-vs-instances.test.js b/unit-tests/json-to-iac/power-vs-instances.test.js index 762534ab..7924ba24 100644 --- a/unit-tests/json-to-iac/power-vs-instances.test.js +++ b/unit-tests/json-to-iac/power-vs-instances.test.js @@ -1516,6 +1516,118 @@ resource "ibm_pi_instance" "example_falconstor_vtl_test" { } } +############################################################################## +`; + + assert.deepEqual( + actualData, + expectedData, + "it should return correct instance data" + ); + }); + it("should return power file with vtl and manual naming", () => { + let actualData = powerInstanceTf({ + _options: { + manual_power_vsi_naming: true, + }, + power_instances: [ + { + zone: "dal12", + workspace: "example", + name: "test", + image: "SLES15-SP3-SAP", + ssh_key: "keyname", + network: [ + { + name: "dev-nw", + }, + ], + primary_subnet: "dev-nw", + pi_memory: "4", + pi_processors: "2", + pi_proc_type: "shared", + pi_sys_type: "s922", + pi_pin_policy: "none", + pi_health_status: "WARNING", + pi_storage_type: "tier1", + }, + ], + vtl: [ + { + zone: "dal12", + workspace: "example", + name: "test2", + ssh_key: "keyname", + network: [ + { + name: "dev-nw", + }, + ], + image: "VTL-FalconStor-10_03-001", + pi_memory: "4", + pi_processors: "2", + pi_proc_type: "shared", + pi_sys_type: "s922", + pi_pin_policy: "none", + pi_health_status: "WARNING", + pi_storage_type: "tier1", + pi_license_repository_capacity: 1, + }, + ], + }); + let expectedData = `############################################################################## +# Test Power Instance +############################################################################## + +resource "ibm_pi_instance" "example_workspace_instance_test" { + provider = ibm.power_vs_dal12 + pi_image_id = ibm_pi_image.power_image_example_sles15_sp3_sap.image_id + pi_key_pair_name = ibm_pi_key.power_vs_ssh_key_keyname.pi_key_name + pi_cloud_instance_id = ibm_resource_instance.power_vs_workspace_example.guid + pi_instance_name = "test" + pi_memory = "4" + pi_processors = "2" + pi_proc_type = "shared" + pi_sys_type = "s922" + pi_pin_policy = "none" + pi_health_status = "WARNING" + pi_storage_type = "tier1" + pi_network { + network_id = ibm_pi_network.power_network_example_dev_nw.network_id + } + timeouts { + create = "3h" + } +} + +############################################################################## + +############################################################################## +# Test 2 FalconStor VTL +############################################################################## + +resource "ibm_pi_instance" "example_falconstor_vtl_test2" { + provider = ibm.power_vs_dal12 + pi_image_id = ibm_pi_image.power_image_example_vtl_falconstor_10_03_001.image_id + pi_key_pair_name = ibm_pi_key.power_vs_ssh_key_keyname.pi_key_name + pi_cloud_instance_id = ibm_resource_instance.power_vs_workspace_example.guid + pi_instance_name = "test2" + pi_memory = "4" + pi_processors = "2" + pi_proc_type = "shared" + pi_sys_type = "s922" + pi_pin_policy = "none" + pi_health_status = "WARNING" + pi_storage_type = "tier1" + pi_license_repository_capacity = 1 + pi_network { + network_id = ibm_pi_network.power_network_example_dev_nw.network_id + } + timeouts { + create = "3h" + } +} + ############################################################################## `; diff --git a/unit-tests/state/power-vs-instances.test.js b/unit-tests/state/power-vs-instances.test.js index 86e0350d..9c75231d 100644 --- a/unit-tests/state/power-vs-instances.test.js +++ b/unit-tests/state/power-vs-instances.test.js @@ -2561,6 +2561,47 @@ describe("power_instances", () => { ); }); }); + describe("power_instance.name.helperText", () => { + it("should return correct helper text", () => { + assert.deepEqual( + craig.power_instances.name.helperText( + { name: "frog" }, + { + craig: { + store: { + json: { + _options: { + prefix: "hi", + }, + }, + }, + }, + } + ), + "hi-frog", + "it should return correct helper text" + ); + assert.deepEqual( + craig.power_instances.name.helperText( + { name: "frog" }, + { + craig: { + store: { + json: { + _options: { + prefix: "hi", + manual_power_vsi_naming: true, + }, + }, + }, + }, + } + ), + "frog", + "it should return correct helper text" + ); + }); + }); describe("power_instance.network.onStateChange", () => { it("should return new networks and update primary subnet with first network name value", () => { let craig = state(); diff --git a/unit-tests/state/schema.test.js b/unit-tests/state/schema.test.js index 647741c6..85730388 100644 --- a/unit-tests/state/schema.test.js +++ b/unit-tests/state/schema.test.js @@ -254,6 +254,10 @@ describe("automate schema generation", () => { power_vs_zones: { type: "Array", default: [] }, enable_classic: { type: "boolean", default: false }, tags: { type: "Array", default: ["hello", "world"] }, + manual_power_vsi_naming: { + default: false, + type: "boolean", + }, no_vpn_secrets_manager_auth: { type: "boolean", default: false }, }, }, From 7e0bccbd8c9b59197f6fe66ebe015f7b0b95ebef Mon Sep 17 00:00:00 2001 From: jvallexm Date: Tue, 26 Mar 2024 15:55:02 -0400 Subject: [PATCH 05/17] feat: snapshots api (#1756) * feat: snapshots api * rm slz gui reference * feat: json to iac for snapshots --- client/src/lib/docs/api-spec.yaml | 28 +++++ client/src/lib/json-to-iac/vsi.js | 40 ++++++- express-controllers/vsi-api.js | 33 +++++ express-routes/routes.js | 1 + server.js | 1 - unit-tests/api/craig-api.test.js | 6 +- unit-tests/api/vsi-api.test.js | 31 +++++ unit-tests/json-to-iac/vsi.test.js | 185 +++++++++++++++++++++++++++++ 8 files changed, 315 insertions(+), 10 deletions(-) diff --git a/client/src/lib/docs/api-spec.yaml b/client/src/lib/docs/api-spec.yaml index 0bc938c8..694f9e31 100644 --- a/client/src/lib/docs/api-spec.yaml +++ b/client/src/lib/docs/api-spec.yaml @@ -276,6 +276,34 @@ paths: type: string "401": description: Unauthorized + /api/vsi/{region}/snapshots: + get: + tags: + - VSI + summary: Returns a list of VSI snapshots in a region for the cloud account linked to the API key + description: Get a list of VSI snapshots in a region for the cloud account linked to the API key + operationId: getImages + parameters: + - in: path + name: region + required: true + schema: + type: string + description: Region to get images from + responses: + "200": + description: successful operation + content: + application/json: + schema: + type: array + example: + - my-restore-volume + - another-restore-volume + items: + type: string + "401": + description: Unauthorized /api/cluster/versions: get: tags: diff --git a/client/src/lib/json-to-iac/vsi.js b/client/src/lib/json-to-iac/vsi.js index acd07c6c..b5a9a6c3 100644 --- a/client/src/lib/json-to-iac/vsi.js +++ b/client/src/lib/json-to-iac/vsi.js @@ -62,7 +62,9 @@ function ibmIsInstance(vsi, config) { }; let vsiData = { name: vsiName, - image: !vsi.image + image: vsi.snapshot + ? undefined + : !vsi.image ? "ERROR: Unfound Ref" : contains(vsi.image, "local") ? vsi.image @@ -80,9 +82,18 @@ function ibmIsInstance(vsi, config) { }, ], boot_volume: [ - { - encryption: encryptionKeyRef(vsi.kms, vsi.encryption_key, "crn"), - }, + vsi.snapshot + ? { + snapshot: tfRef( + "ibm_is_snapshot", + "snapshot " + vsi.snapshot, + "id", + true + ), + } + : { + encryption: encryptionKeyRef(vsi.kms, vsi.encryption_key, "crn"), + }, ], }; if (vsi.primary_interface_ip_spoofing) { @@ -445,12 +456,29 @@ function formatLoadBalancer(deployment, config) { function vsiTf(config) { let tf = "", imageTf = "", + snapshotTf = "", fipTf = ""; - let allImagesNames = distinct(splat(config.vsi, "image")); + + let allSnapshotNames = distinct(splat(config.vsi, "snapshot")).filter( + (name) => { + if (name) return name; + } + ); + let allImagesNames = distinct(splat(config.vsi, "image")).filter((name) => { + if (name) return name; + }); + allSnapshotNames.forEach((name) => { + snapshotTf += jsonToTfPrint("data", "ibm_is_snapshot", "snapshot " + name, { + name: name, + }); + }); allImagesNames.forEach((name) => { imageTf += formatVsiImage(name); }); - tf += tfBlock("image data sources", imageTf) + "\n"; + if (allImagesNames.length > 0) + tf += tfBlock("image data sources", imageTf) + "\n"; + if (allSnapshotNames.length > 0) + tf += tfBlock("snapshot sources", snapshotTf) + "\n"; config.vsi.forEach((deployment) => { let blockData = ""; deployment.subnets.sort(azsort).forEach((subnet) => { diff --git a/express-controllers/vsi-api.js b/express-controllers/vsi-api.js index 731ce788..f30c5514 100644 --- a/express-controllers/vsi-api.js +++ b/express-controllers/vsi-api.js @@ -96,6 +96,39 @@ function vsiRoutes(axios, controller) { return controller.imageGet(req, res); }); }; + + /** + * route for getting vsi snapshots + * @param {*} req + * @param {*} res + * @returns {Promise} get promise + */ + controller.vsiSnapShots = (req, res) => { + return controller + .getBearerToken() + .then(() => { + let region = req.params["region"]; + let requestConfig = { + method: "get", + url: `https://${region}.iaas.cloud.ibm.com/v1/snapshots?version=2024-03-19&generation=2`, + headers: { + "Accept-Encoding": "application/json", + Authorization: `Bearer ${controller.token}`, + }, + }; + return axios(requestConfig); + }) + .then((response) => { + let snapshots = []; + response.data.snapshots.forEach((item) => { + snapshots.push(item.name); + }); + res.send(snapshots); + }) + .catch((err) => { + res.send(err.data); + }); + }; } module.exports = { diff --git a/express-routes/routes.js b/express-routes/routes.js index c6080d45..54b295a0 100644 --- a/express-routes/routes.js +++ b/express-routes/routes.js @@ -16,6 +16,7 @@ const apiSpec = yaml.load( // vsi router.get("/vsi/:region/instanceProfiles", controller.vsiInstanceProfiles); router.get("/vsi/:region/images", controller.vsiImages); +router.get("/vsi/:region/snapshots", controller.vsiSnapShots); // cluster router.get("/cluster/:region/flavors", controller.clusterFlavors); diff --git a/server.js b/server.js index 9ef40b3a..b82f811a 100644 --- a/server.js +++ b/server.js @@ -1,4 +1,3 @@ -//simple backend express server which hosts production build version of slzgui, to test locally go to http://localhost:3000 require("dotenv").config(); // import env const express = require("express"); const path = require("path"); diff --git a/unit-tests/api/craig-api.test.js b/unit-tests/api/craig-api.test.js index 6607dffa..3cc98699 100644 --- a/unit-tests/api/craig-api.test.js +++ b/unit-tests/api/craig-api.test.js @@ -95,7 +95,7 @@ describe("craig api", () => { }, { name: "craig/craig.json", - data: '{\n \"_options\": {\n \"prefix\": \"iac\",\n \"region\": \"us-south\",\n \"tags\": [\n \"hello\",\n \"world\"\n ],\n \"zones\": 3,\n \"endpoints\": \"private\",\n \"account_id\": null,\n \"fs_cloud\": false,\n \"enable_classic\": false,\n \"dynamic_subnets\": true,\n \"enable_power_vs\": false,\n \"power_vs_zones\": [],\n \"craig_version\": \"1.12.0\",\n \"power_vs_high_availability\": false,\n \"no_vpn_secrets_manager_auth\": false,\n \"power_vs_ha_zone_1\": null,\n \"power_vs_ha_zone_2\": null,\n \"manual_power_vsi_naming\": false\n },\n \"access_groups\": [],\n \"appid\": [],\n \"atracker\": {\n \"enabled\": true,\n \"type\": \"cos\",\n \"name\": \"atracker\",\n \"target_name\": \"atracker-cos\",\n \"bucket\": \"atracker-bucket\",\n \"add_route\": true,\n \"cos_key\": \"cos-bind-key\",\n \"locations\": [\n \"global\",\n \"us-south\"\n ],\n \"instance\": false,\n \"plan\": \"lite\",\n \"resource_group\": null,\n \"archive\": false\n },\n \"cbr_rules\": [],\n \"cbr_zones\": [],\n \"classic_ssh_keys\": [],\n \"classic_vlans\": [],\n \"clusters\": [\n {\n \"kms\": \"kms\",\n \"cos\": \"cos\",\n \"entitlement\": \"cloud_pak\",\n \"kube_type\": \"openshift\",\n \"kube_version\": \"4.12.26_openshift\",\n \"flavor\": \"bx2.16x64\",\n \"name\": \"workload-cluster\",\n \"resource_group\": \"workload-rg\",\n \"encryption_key\": \"roks-key\",\n \"subnets\": [\n \"vsi-zone-1\",\n \"vsi-zone-2\",\n \"vsi-zone-3\"\n ],\n \"update_all_workers\": false,\n \"vpc\": \"workload\",\n \"worker_pools\": [\n {\n \"entitlement\": \"cloud_pak\",\n \"cluster\": \"workload-cluster\",\n \"flavor\": \"bx2.16x64\",\n \"name\": \"logging-worker-pool\",\n \"resource_group\": \"workload-rg\",\n \"subnets\": [\n \"vsi-zone-1\",\n \"vsi-zone-2\",\n \"vsi-zone-3\"\n ],\n \"vpc\": \"workload\",\n \"workers_per_subnet\": 2\n }\n ],\n \"opaque_secrets\": [],\n \"workers_per_subnet\": 2,\n \"private_endpoint\": true\n }\n ],\n \"dns\": [],\n \"event_streams\": [],\n \"f5_vsi\": [],\n \"iam_account_settings\": {\n \"enable\": false,\n \"mfa\": null,\n \"allowed_ip_addresses\": null,\n \"include_history\": false,\n \"if_match\": null,\n \"max_sessions_per_identity\": null,\n \"restrict_create_service_id\": null,\n \"restrict_create_platform_apikey\": null,\n \"session_expiration_in_seconds\": null,\n \"session_invalidation_in_seconds\": null\n },\n \"icd\": [],\n \"key_management\": [\n {\n \"name\": \"kms\",\n \"resource_group\": \"service-rg\",\n \"use_hs_crypto\": false,\n \"authorize_vpc_reader_role\": true,\n \"use_data\": false,\n \"keys\": [\n {\n \"key_ring\": \"ring\",\n \"name\": \"key\",\n \"root_key\": true,\n \"force_delete\": true,\n \"endpoint\": \"public\",\n \"rotation\": 1,\n \"dual_auth_delete\": false\n },\n {\n \"key_ring\": \"ring\",\n \"name\": \"atracker-key\",\n \"root_key\": true,\n \"force_delete\": true,\n \"endpoint\": \"public\",\n \"rotation\": 1,\n \"dual_auth_delete\": false\n },\n {\n \"key_ring\": \"ring\",\n \"name\": \"vsi-volume-key\",\n \"root_key\": true,\n \"force_delete\": true,\n \"endpoint\": \"public\",\n \"rotation\": 1,\n \"dual_auth_delete\": false\n },\n {\n \"key_ring\": \"ring\",\n \"name\": \"roks-key\",\n \"root_key\": true,\n \"force_delete\": null,\n \"endpoint\": null,\n \"rotation\": 1,\n \"dual_auth_delete\": false\n }\n ]\n }\n ],\n \"load_balancers\": [],\n \"logdna\": {\n \"name\": \"logdna\",\n \"archive\": false,\n \"enabled\": false,\n \"plan\": \"lite\",\n \"endpoints\": \"private\",\n \"platform_logs\": false,\n \"resource_group\": \"service-rg\",\n \"cos\": \"atracker-cos\",\n \"bucket\": \"atracker-bucket\"\n },\n \"object_storage\": [\n {\n \"buckets\": [\n {\n \"endpoint\": \"public\",\n \"force_delete\": true,\n \"kms_key\": \"atracker-key\",\n \"name\": \"atracker-bucket\",\n \"storage_class\": \"standard\",\n \"use_random_suffix\": true\n }\n ],\n \"keys\": [\n {\n \"name\": \"cos-bind-key\",\n \"role\": \"Writer\",\n \"enable_hmac\": false,\n \"use_random_suffix\": true\n }\n ],\n \"name\": \"atracker-cos\",\n \"plan\": \"standard\",\n \"resource_group\": \"service-rg\",\n \"use_data\": false,\n \"use_random_suffix\": true,\n \"kms\": \"kms\"\n },\n {\n \"buckets\": [\n {\n \"endpoint\": \"public\",\n \"force_delete\": true,\n \"kms_key\": \"key\",\n \"name\": \"management-bucket\",\n \"storage_class\": \"standard\",\n \"use_random_suffix\": true\n },\n {\n \"endpoint\": \"public\",\n \"force_delete\": true,\n \"kms_key\": \"key\",\n \"name\": \"workload-bucket\",\n \"storage_class\": \"standard\",\n \"use_random_suffix\": true\n }\n ],\n \"use_random_suffix\": true,\n \"keys\": [],\n \"name\": \"cos\",\n \"plan\": \"standard\",\n \"resource_group\": \"service-rg\",\n \"use_data\": false,\n \"kms\": \"kms\"\n }\n ],\n \"power\": [],\n \"power_instances\": [],\n \"power_volumes\": [],\n \"resource_groups\": [\n {\n \"use_prefix\": true,\n \"name\": \"service-rg\",\n \"use_data\": false\n },\n {\n \"use_prefix\": true,\n \"name\": \"management-rg\",\n \"use_data\": false\n },\n {\n \"use_prefix\": true,\n \"name\": \"workload-rg\",\n \"use_data\": false\n }\n ],\n \"routing_tables\": [],\n \"scc\": {\n \"credential_description\": null,\n \"id\": null,\n \"passphrase\": null,\n \"name\": \"\",\n \"location\": \"us\",\n \"collector_description\": null,\n \"is_public\": false,\n \"scope_description\": null,\n \"enable\": false\n },\n \"secrets_manager\": [],\n \"security_groups\": [\n {\n \"vpc\": \"management\",\n \"name\": \"management-vpe\",\n \"resource_group\": \"management-rg\",\n \"rules\": [\n {\n \"vpc\": \"management\",\n \"sg\": \"management-vpe\",\n \"direction\": \"inbound\",\n \"name\": \"allow-ibm-inbound\",\n \"source\": \"161.26.0.0/16\",\n \"tcp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n },\n {\n \"vpc\": \"management\",\n \"sg\": \"management-vpe\",\n \"direction\": \"inbound\",\n \"name\": \"allow-vpc-inbound\",\n \"source\": \"10.0.0.0/8\",\n \"tcp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n },\n {\n \"vpc\": \"management\",\n \"sg\": \"management-vpe\",\n \"direction\": \"outbound\",\n \"name\": \"allow-vpc-outbound\",\n \"source\": \"10.0.0.0/8\",\n \"tcp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n },\n {\n \"vpc\": \"management\",\n \"sg\": \"management-vpe\",\n \"direction\": \"outbound\",\n \"name\": \"allow-ibm-tcp-53-outbound\",\n \"source\": \"161.26.0.0/16\",\n \"tcp\": {\n \"port_max\": 53,\n \"port_min\": 53\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"tcp\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n },\n {\n \"vpc\": \"management\",\n \"sg\": \"management-vpe\",\n \"direction\": \"outbound\",\n \"name\": \"allow-ibm-tcp-80-outbound\",\n \"source\": \"161.26.0.0/16\",\n \"tcp\": {\n \"port_max\": 80,\n \"port_min\": 80\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"tcp\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n },\n {\n \"vpc\": \"management\",\n \"sg\": \"management-vpe\",\n \"direction\": \"outbound\",\n \"name\": \"allow-ibm-tcp-443-outbound\",\n \"source\": \"161.26.0.0/16\",\n \"tcp\": {\n \"port_max\": 443,\n \"port_min\": 443\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"tcp\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n }\n ],\n \"use_data\": false\n },\n {\n \"vpc\": \"workload\",\n \"name\": \"workload-vpe\",\n \"resource_group\": \"workload-rg\",\n \"rules\": [\n {\n \"vpc\": \"workload\",\n \"sg\": \"workload-vpe\",\n \"direction\": \"inbound\",\n \"name\": \"allow-ibm-inbound\",\n \"source\": \"161.26.0.0/16\",\n \"tcp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n },\n {\n \"vpc\": \"workload\",\n \"sg\": \"workload-vpe\",\n \"direction\": \"inbound\",\n \"name\": \"allow-vpc-inbound\",\n \"source\": \"10.0.0.0/8\",\n \"tcp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n },\n {\n \"vpc\": \"workload\",\n \"sg\": \"workload-vpe\",\n \"direction\": \"outbound\",\n \"name\": \"allow-vpc-outbound\",\n \"source\": \"10.0.0.0/8\",\n \"tcp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n },\n {\n \"vpc\": \"workload\",\n \"sg\": \"workload-vpe\",\n \"direction\": \"outbound\",\n \"name\": \"allow-ibm-tcp-53-outbound\",\n \"source\": \"161.26.0.0/16\",\n \"tcp\": {\n \"port_max\": 53,\n \"port_min\": 53\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"tcp\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n },\n {\n \"vpc\": \"workload\",\n \"sg\": \"workload-vpe\",\n \"direction\": \"outbound\",\n \"name\": \"allow-ibm-tcp-80-outbound\",\n \"source\": \"161.26.0.0/16\",\n \"tcp\": {\n \"port_max\": 80,\n \"port_min\": 80\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"tcp\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n },\n {\n \"vpc\": \"workload\",\n \"sg\": \"workload-vpe\",\n \"direction\": \"outbound\",\n \"name\": \"allow-ibm-tcp-443-outbound\",\n \"source\": \"161.26.0.0/16\",\n \"tcp\": {\n \"port_max\": 443,\n \"port_min\": 443\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"tcp\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n }\n ],\n \"use_data\": false\n },\n {\n \"vpc\": \"management\",\n \"name\": \"management-vsi\",\n \"resource_group\": \"management-rg\",\n \"rules\": [\n {\n \"vpc\": \"management\",\n \"sg\": \"management-vsi\",\n \"direction\": \"inbound\",\n \"name\": \"allow-ibm-inbound\",\n \"source\": \"161.26.0.0/16\",\n \"tcp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n },\n {\n \"vpc\": \"management\",\n \"sg\": \"management-vsi\",\n \"direction\": \"inbound\",\n \"name\": \"allow-vpc-inbound\",\n \"source\": \"10.0.0.0/8\",\n \"tcp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n },\n {\n \"vpc\": \"management\",\n \"sg\": \"management-vsi\",\n \"direction\": \"outbound\",\n \"name\": \"allow-vpc-outbound\",\n \"source\": \"10.0.0.0/8\",\n \"tcp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n },\n {\n \"vpc\": \"management\",\n \"sg\": \"management-vsi\",\n \"direction\": \"outbound\",\n \"name\": \"allow-ibm-tcp-53-outbound\",\n \"source\": \"161.26.0.0/16\",\n \"tcp\": {\n \"port_max\": 53,\n \"port_min\": 53\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"tcp\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n },\n {\n \"vpc\": \"management\",\n \"sg\": \"management-vsi\",\n \"direction\": \"outbound\",\n \"name\": \"allow-ibm-tcp-80-outbound\",\n \"source\": \"161.26.0.0/16\",\n \"tcp\": {\n \"port_max\": 80,\n \"port_min\": 80\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"tcp\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n },\n {\n \"vpc\": \"management\",\n \"sg\": \"management-vsi\",\n \"direction\": \"outbound\",\n \"name\": \"allow-ibm-tcp-443-outbound\",\n \"source\": \"161.26.0.0/16\",\n \"tcp\": {\n \"port_max\": 443,\n \"port_min\": 443\n },\n \"udp\": {\n \"port_max\": null,\n \"port_min\": null\n },\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"ruleProtocol\": \"tcp\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null\n }\n ],\n \"use_data\": false\n }\n ],\n \"ssh_keys\": [\n {\n \"name\": \"ssh-key\",\n \"public_key\": null,\n \"resource_group\": \"management-rg\",\n \"use_data\": false\n }\n ],\n \"sysdig\": {\n \"enabled\": false,\n \"plan\": \"graduated-tier\",\n \"resource_group\": \"service-rg\",\n \"name\": \"sysdig\",\n \"platform_logs\": false\n },\n \"teleport_vsi\": [],\n \"transit_gateways\": [\n {\n \"name\": \"transit-gateway\",\n \"resource_group\": \"service-rg\",\n \"global\": false,\n \"connections\": [\n {\n \"tgw\": \"transit-gateway\",\n \"vpc\": \"management\"\n },\n {\n \"tgw\": \"transit-gateway\",\n \"vpc\": \"workload\"\n }\n ],\n \"use_data\": false,\n \"prefix_filters\": [],\n \"gre_tunnels\": [],\n \"crns\": null,\n \"classic\": false\n }\n ],\n \"virtual_private_endpoints\": [\n {\n \"name\": \"management-cos\",\n \"service\": \"cos\",\n \"vpc\": \"management\",\n \"resource_group\": \"management-rg\",\n \"security_groups\": [\n \"management-vpe\"\n ],\n \"subnets\": [\n \"vpe-zone-1\",\n \"vpe-zone-2\",\n \"vpe-zone-3\"\n ],\n \"instance\": null\n },\n {\n \"name\": \"workload-cos\",\n \"service\": \"cos\",\n \"vpc\": \"workload\",\n \"resource_group\": \"workload-rg\",\n \"security_groups\": [\n \"workload-vpe\"\n ],\n \"subnets\": [\n \"vpe-zone-1\",\n \"vpe-zone-2\",\n \"vpe-zone-3\"\n ],\n \"instance\": null\n }\n ],\n \"vpcs\": [\n {\n \"cos\": \"cos\",\n \"bucket\": \"management-bucket\",\n \"name\": \"management\",\n \"resource_group\": \"management-rg\",\n \"classic_access\": false,\n \"manual_address_prefix_management\": true,\n \"default_network_acl_name\": null,\n \"default_security_group_name\": null,\n \"default_routing_table_name\": null,\n \"publicGateways\": [],\n \"address_prefixes\": [\n {\n \"vpc\": \"management\",\n \"zone\": 1,\n \"name\": \"management-zone-1\",\n \"cidr\": \"10.10.0.0/22\"\n },\n {\n \"vpc\": \"management\",\n \"zone\": 2,\n \"name\": \"management-zone-2\",\n \"cidr\": \"10.20.0.0/22\"\n },\n {\n \"vpc\": \"management\",\n \"zone\": 3,\n \"name\": \"management-zone-3\",\n \"cidr\": \"10.30.0.0/22\"\n }\n ],\n \"subnets\": [\n {\n \"vpc\": \"management\",\n \"zone\": 1,\n \"cidr\": \"10.10.0.0/29\",\n \"name\": \"vsi-zone-1\",\n \"network_acl\": \"management\",\n \"resource_group\": \"management-rg\",\n \"public_gateway\": false,\n \"has_prefix\": false\n },\n {\n \"vpc\": \"management\",\n \"zone\": 1,\n \"cidr\": \"10.10.0.16/28\",\n \"name\": \"vpn-zone-1\",\n \"network_acl\": \"management\",\n \"resource_group\": \"management-rg\",\n \"public_gateway\": false,\n \"has_prefix\": false\n },\n {\n \"vpc\": \"management\",\n \"zone\": 2,\n \"cidr\": \"10.20.0.0/29\",\n \"name\": \"vsi-zone-2\",\n \"network_acl\": \"management\",\n \"resource_group\": \"management-rg\",\n \"public_gateway\": false,\n \"has_prefix\": false\n },\n {\n \"vpc\": \"management\",\n \"zone\": 3,\n \"cidr\": \"10.30.0.0/29\",\n \"name\": \"vsi-zone-3\",\n \"network_acl\": \"management\",\n \"resource_group\": \"management-rg\",\n \"public_gateway\": false,\n \"has_prefix\": false\n },\n {\n \"vpc\": \"management\",\n \"zone\": 1,\n \"cidr\": \"10.10.0.48/29\",\n \"name\": \"vpe-zone-1\",\n \"resource_group\": \"management-rg\",\n \"network_acl\": \"management\",\n \"public_gateway\": false,\n \"has_prefix\": false\n },\n {\n \"vpc\": \"management\",\n \"zone\": 2,\n \"cidr\": \"10.20.0.16/29\",\n \"name\": \"vpe-zone-2\",\n \"network_acl\": \"management\",\n \"resource_group\": \"management-rg\",\n \"public_gateway\": false,\n \"has_prefix\": false\n },\n {\n \"vpc\": \"management\",\n \"zone\": 3,\n \"cidr\": \"10.30.0.16/29\",\n \"name\": \"vpe-zone-3\",\n \"network_acl\": \"management\",\n \"resource_group\": \"management-rg\",\n \"public_gateway\": false,\n \"has_prefix\": false\n }\n ],\n \"public_gateways\": [],\n \"acls\": [\n {\n \"resource_group\": \"management-rg\",\n \"name\": \"management\",\n \"vpc\": \"management\",\n \"rules\": [\n {\n \"action\": \"allow\",\n \"destination\": \"10.0.0.0/8\",\n \"direction\": \"inbound\",\n \"name\": \"allow-ibm-inbound\",\n \"source\": \"161.26.0.0/16\",\n \"acl\": \"management\",\n \"vpc\": \"management\",\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"tcp\": {\n \"port_min\": null,\n \"port_max\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n \"udp\": {\n \"port_min\": null,\n \"port_max\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n {\n \"action\": \"allow\",\n \"source\": \"10.0.0.0/8\",\n \"direction\": \"outbound\",\n \"name\": \"allow-ibm-outbound\",\n \"destination\": \"161.26.0.0/16\",\n \"acl\": \"management\",\n \"vpc\": \"management\",\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"tcp\": {\n \"port_min\": null,\n \"port_max\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n \"udp\": {\n \"port_min\": null,\n \"port_max\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n {\n \"action\": \"allow\",\n \"destination\": \"10.0.0.0/8\",\n \"direction\": \"inbound\",\n \"name\": \"allow-all-network-inbound\",\n \"source\": \"10.0.0.0/8\",\n \"acl\": \"management\",\n \"vpc\": \"management\",\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"tcp\": {\n \"port_min\": null,\n \"port_max\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n \"udp\": {\n \"port_min\": null,\n \"port_max\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n {\n \"action\": \"allow\",\n \"destination\": \"10.0.0.0/8\",\n \"direction\": \"outbound\",\n \"name\": \"allow-all-network-outbound\",\n \"source\": \"10.0.0.0/8\",\n \"acl\": \"management\",\n \"vpc\": \"management\",\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"tcp\": {\n \"port_min\": null,\n \"port_max\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n \"udp\": {\n \"port_min\": null,\n \"port_max\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n }\n ],\n \"use_data\": false\n }\n ],\n \"subnetTiers\": [\n {\n \"name\": \"vsi\",\n \"zones\": 3\n },\n {\n \"name\": \"vpn\",\n \"zones\": 1\n },\n {\n \"name\": \"vpe\",\n \"zones\": 3\n }\n ],\n \"use_data\": false\n },\n {\n \"cos\": \"cos\",\n \"bucket\": \"workload-bucket\",\n \"name\": \"workload\",\n \"resource_group\": \"workload-rg\",\n \"classic_access\": false,\n \"manual_address_prefix_management\": true,\n \"default_network_acl_name\": null,\n \"default_security_group_name\": null,\n \"default_routing_table_name\": null,\n \"publicGateways\": [],\n \"address_prefixes\": [\n {\n \"vpc\": \"workload\",\n \"zone\": 1,\n \"name\": \"workload-zone-1\",\n \"cidr\": \"10.40.0.0/22\"\n },\n {\n \"vpc\": \"workload\",\n \"zone\": 2,\n \"name\": \"workload-zone-2\",\n \"cidr\": \"10.50.0.0/22\"\n },\n {\n \"vpc\": \"workload\",\n \"zone\": 3,\n \"name\": \"workload-zone-3\",\n \"cidr\": \"10.60.0.0/22\"\n }\n ],\n \"subnets\": [\n {\n \"vpc\": \"workload\",\n \"zone\": 1,\n \"cidr\": \"10.40.0.0/28\",\n \"name\": \"vsi-zone-1\",\n \"network_acl\": \"workload\",\n \"resource_group\": \"workload-rg\",\n \"public_gateway\": false,\n \"has_prefix\": false\n },\n {\n \"vpc\": \"workload\",\n \"zone\": 2,\n \"cidr\": \"10.50.0.0/28\",\n \"name\": \"vsi-zone-2\",\n \"network_acl\": \"workload\",\n \"resource_group\": \"workload-rg\",\n \"public_gateway\": false,\n \"has_prefix\": false\n },\n {\n \"vpc\": \"workload\",\n \"zone\": 3,\n \"cidr\": \"10.60.0.0/28\",\n \"name\": \"vsi-zone-3\",\n \"network_acl\": \"workload\",\n \"resource_group\": \"workload-rg\",\n \"public_gateway\": false,\n \"has_prefix\": false\n },\n {\n \"vpc\": \"workload\",\n \"zone\": 1,\n \"cidr\": \"10.40.0.32/29\",\n \"name\": \"vpe-zone-1\",\n \"network_acl\": \"workload\",\n \"resource_group\": \"workload-rg\",\n \"public_gateway\": false,\n \"has_prefix\": false\n },\n {\n \"vpc\": \"workload\",\n \"zone\": 2,\n \"cidr\": \"10.50.0.32/29\",\n \"name\": \"vpe-zone-2\",\n \"network_acl\": \"workload\",\n \"resource_group\": \"workload-rg\",\n \"public_gateway\": false,\n \"has_prefix\": false\n },\n {\n \"vpc\": \"workload\",\n \"zone\": 3,\n \"cidr\": \"10.60.0.32/29\",\n \"name\": \"vpe-zone-3\",\n \"network_acl\": \"workload\",\n \"resource_group\": \"workload-rg\",\n \"public_gateway\": false,\n \"has_prefix\": false\n }\n ],\n \"public_gateways\": [],\n \"acls\": [\n {\n \"resource_group\": \"workload-rg\",\n \"name\": \"workload\",\n \"vpc\": \"workload\",\n \"rules\": [\n {\n \"action\": \"allow\",\n \"destination\": \"10.0.0.0/8\",\n \"direction\": \"inbound\",\n \"name\": \"allow-ibm-inbound\",\n \"source\": \"161.26.0.0/16\",\n \"acl\": \"workload\",\n \"vpc\": \"workload\",\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"tcp\": {\n \"port_min\": null,\n \"port_max\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n \"udp\": {\n \"port_min\": null,\n \"port_max\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n {\n \"action\": \"allow\",\n \"source\": \"10.0.0.0/8\",\n \"direction\": \"outbound\",\n \"name\": \"allow-ibm-outbound\",\n \"destination\": \"161.26.0.0/16\",\n \"acl\": \"workload\",\n \"vpc\": \"workload\",\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"tcp\": {\n \"port_min\": null,\n \"port_max\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n \"udp\": {\n \"port_min\": null,\n \"port_max\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n {\n \"action\": \"allow\",\n \"destination\": \"10.0.0.0/8\",\n \"direction\": \"inbound\",\n \"name\": \"allow-all-network-inbound\",\n \"source\": \"10.0.0.0/8\",\n \"acl\": \"workload\",\n \"vpc\": \"workload\",\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"tcp\": {\n \"port_min\": null,\n \"port_max\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n \"udp\": {\n \"port_min\": null,\n \"port_max\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n {\n \"action\": \"allow\",\n \"destination\": \"10.0.0.0/8\",\n \"direction\": \"outbound\",\n \"name\": \"allow-all-network-outbound\",\n \"source\": \"10.0.0.0/8\",\n \"acl\": \"workload\",\n \"vpc\": \"workload\",\n \"icmp\": {\n \"type\": null,\n \"code\": null\n },\n \"tcp\": {\n \"port_min\": null,\n \"port_max\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n \"udp\": {\n \"port_min\": null,\n \"port_max\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n },\n \"ruleProtocol\": \"all\",\n \"port_min\": null,\n \"port_max\": null,\n \"type\": null,\n \"code\": null,\n \"source_port_min\": null,\n \"source_port_max\": null\n }\n ],\n \"use_data\": false\n }\n ],\n \"subnetTiers\": [\n {\n \"name\": \"vsi\",\n \"zones\": 3\n },\n {\n \"name\": \"vpe\",\n \"zones\": 3\n }\n ],\n \"use_data\": false\n }\n ],\n \"vpn_gateways\": [\n {\n \"name\": \"management-gateway\",\n \"resource_group\": \"management-rg\",\n \"subnet\": \"vpn-zone-1\",\n \"vpc\": \"management\",\n \"connections\": [],\n \"policy_mode\": false,\n \"additional_prefixes\": []\n }\n ],\n \"vpn_servers\": [],\n \"vsi\": [\n {\n \"kms\": \"kms\",\n \"encryption_key\": \"vsi-volume-key\",\n \"image\": \"ibm-ubuntu-22-04-1-minimal-amd64-1\",\n \"profile\": \"cx2-4x8\",\n \"name\": \"management-server\",\n \"security_groups\": [\n \"management-vsi\"\n ],\n \"ssh_keys\": [\n \"ssh-key\"\n ],\n \"subnets\": [\n \"vsi-zone-1\",\n \"vsi-zone-2\",\n \"vsi-zone-3\"\n ],\n \"vpc\": \"management\",\n \"vsi_per_subnet\": 2,\n \"resource_group\": \"management-rg\",\n \"override_vsi_name\": null,\n \"user_data\": null,\n \"network_interfaces\": [],\n \"volumes\": [],\n \"image_name\": null,\n \"enable_floating_ip\": false,\n \"primary_interface_ip_spoofing\": false\n }\n ]\n}' + data: '{\n "_options": {\n "prefix": "iac",\n "region": "us-south",\n "tags": [\n "hello",\n "world"\n ],\n "zones": 3,\n "endpoints": "private",\n "account_id": null,\n "fs_cloud": false,\n "enable_classic": false,\n "dynamic_subnets": true,\n "enable_power_vs": false,\n "power_vs_zones": [],\n "craig_version": "1.12.0",\n "power_vs_high_availability": false,\n "no_vpn_secrets_manager_auth": false,\n "power_vs_ha_zone_1": null,\n "power_vs_ha_zone_2": null,\n "manual_power_vsi_naming": false\n },\n "access_groups": [],\n "appid": [],\n "atracker": {\n "enabled": true,\n "type": "cos",\n "name": "atracker",\n "target_name": "atracker-cos",\n "bucket": "atracker-bucket",\n "add_route": true,\n "cos_key": "cos-bind-key",\n "locations": [\n "global",\n "us-south"\n ],\n "instance": false,\n "plan": "lite",\n "resource_group": null,\n "archive": false\n },\n "cbr_rules": [],\n "cbr_zones": [],\n "classic_ssh_keys": [],\n "classic_vlans": [],\n "clusters": [\n {\n "kms": "kms",\n "cos": "cos",\n "entitlement": "cloud_pak",\n "kube_type": "openshift",\n "kube_version": "4.12.26_openshift",\n "flavor": "bx2.16x64",\n "name": "workload-cluster",\n "resource_group": "workload-rg",\n "encryption_key": "roks-key",\n "subnets": [\n "vsi-zone-1",\n "vsi-zone-2",\n "vsi-zone-3"\n ],\n "update_all_workers": false,\n "vpc": "workload",\n "worker_pools": [\n {\n "entitlement": "cloud_pak",\n "cluster": "workload-cluster",\n "flavor": "bx2.16x64",\n "name": "logging-worker-pool",\n "resource_group": "workload-rg",\n "subnets": [\n "vsi-zone-1",\n "vsi-zone-2",\n "vsi-zone-3"\n ],\n "vpc": "workload",\n "workers_per_subnet": 2\n }\n ],\n "opaque_secrets": [],\n "workers_per_subnet": 2,\n "private_endpoint": true\n }\n ],\n "dns": [],\n "event_streams": [],\n "f5_vsi": [],\n "iam_account_settings": {\n "enable": false,\n "mfa": null,\n "allowed_ip_addresses": null,\n "include_history": false,\n "if_match": null,\n "max_sessions_per_identity": null,\n "restrict_create_service_id": null,\n "restrict_create_platform_apikey": null,\n "session_expiration_in_seconds": null,\n "session_invalidation_in_seconds": null\n },\n "icd": [],\n "key_management": [\n {\n "name": "kms",\n "resource_group": "service-rg",\n "use_hs_crypto": false,\n "authorize_vpc_reader_role": true,\n "use_data": false,\n "keys": [\n {\n "key_ring": "ring",\n "name": "key",\n "root_key": true,\n "force_delete": true,\n "endpoint": "public",\n "rotation": 1,\n "dual_auth_delete": false\n },\n {\n "key_ring": "ring",\n "name": "atracker-key",\n "root_key": true,\n "force_delete": true,\n "endpoint": "public",\n "rotation": 1,\n "dual_auth_delete": false\n },\n {\n "key_ring": "ring",\n "name": "vsi-volume-key",\n "root_key": true,\n "force_delete": true,\n "endpoint": "public",\n "rotation": 1,\n "dual_auth_delete": false\n },\n {\n "key_ring": "ring",\n "name": "roks-key",\n "root_key": true,\n "force_delete": null,\n "endpoint": null,\n "rotation": 1,\n "dual_auth_delete": false\n }\n ]\n }\n ],\n "load_balancers": [],\n "logdna": {\n "name": "logdna",\n "archive": false,\n "enabled": false,\n "plan": "lite",\n "endpoints": "private",\n "platform_logs": false,\n "resource_group": "service-rg",\n "cos": "atracker-cos",\n "bucket": "atracker-bucket"\n },\n "object_storage": [\n {\n "buckets": [\n {\n "endpoint": "public",\n "force_delete": true,\n "kms_key": "atracker-key",\n "name": "atracker-bucket",\n "storage_class": "standard",\n "use_random_suffix": true\n }\n ],\n "keys": [\n {\n "name": "cos-bind-key",\n "role": "Writer",\n "enable_hmac": false,\n "use_random_suffix": true\n }\n ],\n "name": "atracker-cos",\n "plan": "standard",\n "resource_group": "service-rg",\n "use_data": false,\n "use_random_suffix": true,\n "kms": "kms"\n },\n {\n "buckets": [\n {\n "endpoint": "public",\n "force_delete": true,\n "kms_key": "key",\n "name": "management-bucket",\n "storage_class": "standard",\n "use_random_suffix": true\n },\n {\n "endpoint": "public",\n "force_delete": true,\n "kms_key": "key",\n "name": "workload-bucket",\n "storage_class": "standard",\n "use_random_suffix": true\n }\n ],\n "use_random_suffix": true,\n "keys": [],\n "name": "cos",\n "plan": "standard",\n "resource_group": "service-rg",\n "use_data": false,\n "kms": "kms"\n }\n ],\n "power": [],\n "power_instances": [],\n "power_volumes": [],\n "resource_groups": [\n {\n "use_prefix": true,\n "name": "service-rg",\n "use_data": false\n },\n {\n "use_prefix": true,\n "name": "management-rg",\n "use_data": false\n },\n {\n "use_prefix": true,\n "name": "workload-rg",\n "use_data": false\n }\n ],\n "routing_tables": [],\n "scc": {\n "credential_description": null,\n "id": null,\n "passphrase": null,\n "name": "",\n "location": "us",\n "collector_description": null,\n "is_public": false,\n "scope_description": null,\n "enable": false\n },\n "secrets_manager": [],\n "security_groups": [\n {\n "vpc": "management",\n "name": "management-vpe",\n "resource_group": "management-rg",\n "rules": [\n {\n "vpc": "management",\n "sg": "management-vpe",\n "direction": "inbound",\n "name": "allow-ibm-inbound",\n "source": "161.26.0.0/16",\n "tcp": {\n "port_max": null,\n "port_min": null\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n },\n {\n "vpc": "management",\n "sg": "management-vpe",\n "direction": "inbound",\n "name": "allow-vpc-inbound",\n "source": "10.0.0.0/8",\n "tcp": {\n "port_max": null,\n "port_min": null\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n },\n {\n "vpc": "management",\n "sg": "management-vpe",\n "direction": "outbound",\n "name": "allow-vpc-outbound",\n "source": "10.0.0.0/8",\n "tcp": {\n "port_max": null,\n "port_min": null\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n },\n {\n "vpc": "management",\n "sg": "management-vpe",\n "direction": "outbound",\n "name": "allow-ibm-tcp-53-outbound",\n "source": "161.26.0.0/16",\n "tcp": {\n "port_max": 53,\n "port_min": 53\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "tcp",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n },\n {\n "vpc": "management",\n "sg": "management-vpe",\n "direction": "outbound",\n "name": "allow-ibm-tcp-80-outbound",\n "source": "161.26.0.0/16",\n "tcp": {\n "port_max": 80,\n "port_min": 80\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "tcp",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n },\n {\n "vpc": "management",\n "sg": "management-vpe",\n "direction": "outbound",\n "name": "allow-ibm-tcp-443-outbound",\n "source": "161.26.0.0/16",\n "tcp": {\n "port_max": 443,\n "port_min": 443\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "tcp",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n }\n ],\n "use_data": false\n },\n {\n "vpc": "workload",\n "name": "workload-vpe",\n "resource_group": "workload-rg",\n "rules": [\n {\n "vpc": "workload",\n "sg": "workload-vpe",\n "direction": "inbound",\n "name": "allow-ibm-inbound",\n "source": "161.26.0.0/16",\n "tcp": {\n "port_max": null,\n "port_min": null\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n },\n {\n "vpc": "workload",\n "sg": "workload-vpe",\n "direction": "inbound",\n "name": "allow-vpc-inbound",\n "source": "10.0.0.0/8",\n "tcp": {\n "port_max": null,\n "port_min": null\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n },\n {\n "vpc": "workload",\n "sg": "workload-vpe",\n "direction": "outbound",\n "name": "allow-vpc-outbound",\n "source": "10.0.0.0/8",\n "tcp": {\n "port_max": null,\n "port_min": null\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n },\n {\n "vpc": "workload",\n "sg": "workload-vpe",\n "direction": "outbound",\n "name": "allow-ibm-tcp-53-outbound",\n "source": "161.26.0.0/16",\n "tcp": {\n "port_max": 53,\n "port_min": 53\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "tcp",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n },\n {\n "vpc": "workload",\n "sg": "workload-vpe",\n "direction": "outbound",\n "name": "allow-ibm-tcp-80-outbound",\n "source": "161.26.0.0/16",\n "tcp": {\n "port_max": 80,\n "port_min": 80\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "tcp",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n },\n {\n "vpc": "workload",\n "sg": "workload-vpe",\n "direction": "outbound",\n "name": "allow-ibm-tcp-443-outbound",\n "source": "161.26.0.0/16",\n "tcp": {\n "port_max": 443,\n "port_min": 443\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "tcp",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n }\n ],\n "use_data": false\n },\n {\n "vpc": "management",\n "name": "management-vsi",\n "resource_group": "management-rg",\n "rules": [\n {\n "vpc": "management",\n "sg": "management-vsi",\n "direction": "inbound",\n "name": "allow-ibm-inbound",\n "source": "161.26.0.0/16",\n "tcp": {\n "port_max": null,\n "port_min": null\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n },\n {\n "vpc": "management",\n "sg": "management-vsi",\n "direction": "inbound",\n "name": "allow-vpc-inbound",\n "source": "10.0.0.0/8",\n "tcp": {\n "port_max": null,\n "port_min": null\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n },\n {\n "vpc": "management",\n "sg": "management-vsi",\n "direction": "outbound",\n "name": "allow-vpc-outbound",\n "source": "10.0.0.0/8",\n "tcp": {\n "port_max": null,\n "port_min": null\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n },\n {\n "vpc": "management",\n "sg": "management-vsi",\n "direction": "outbound",\n "name": "allow-ibm-tcp-53-outbound",\n "source": "161.26.0.0/16",\n "tcp": {\n "port_max": 53,\n "port_min": 53\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "tcp",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n },\n {\n "vpc": "management",\n "sg": "management-vsi",\n "direction": "outbound",\n "name": "allow-ibm-tcp-80-outbound",\n "source": "161.26.0.0/16",\n "tcp": {\n "port_max": 80,\n "port_min": 80\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "tcp",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n },\n {\n "vpc": "management",\n "sg": "management-vsi",\n "direction": "outbound",\n "name": "allow-ibm-tcp-443-outbound",\n "source": "161.26.0.0/16",\n "tcp": {\n "port_max": 443,\n "port_min": 443\n },\n "udp": {\n "port_max": null,\n "port_min": null\n },\n "icmp": {\n "type": null,\n "code": null\n },\n "ruleProtocol": "tcp",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null\n }\n ],\n "use_data": false\n }\n ],\n "ssh_keys": [\n {\n "name": "ssh-key",\n "public_key": null,\n "resource_group": "management-rg",\n "use_data": false\n }\n ],\n "sysdig": {\n "enabled": false,\n "plan": "graduated-tier",\n "resource_group": "service-rg",\n "name": "sysdig",\n "platform_logs": false\n },\n "teleport_vsi": [],\n "transit_gateways": [\n {\n "name": "transit-gateway",\n "resource_group": "service-rg",\n "global": false,\n "connections": [\n {\n "tgw": "transit-gateway",\n "vpc": "management"\n },\n {\n "tgw": "transit-gateway",\n "vpc": "workload"\n }\n ],\n "use_data": false,\n "prefix_filters": [],\n "gre_tunnels": [],\n "crns": null,\n "classic": false\n }\n ],\n "virtual_private_endpoints": [\n {\n "name": "management-cos",\n "service": "cos",\n "vpc": "management",\n "resource_group": "management-rg",\n "security_groups": [\n "management-vpe"\n ],\n "subnets": [\n "vpe-zone-1",\n "vpe-zone-2",\n "vpe-zone-3"\n ],\n "instance": null\n },\n {\n "name": "workload-cos",\n "service": "cos",\n "vpc": "workload",\n "resource_group": "workload-rg",\n "security_groups": [\n "workload-vpe"\n ],\n "subnets": [\n "vpe-zone-1",\n "vpe-zone-2",\n "vpe-zone-3"\n ],\n "instance": null\n }\n ],\n "vpcs": [\n {\n "cos": "cos",\n "bucket": "management-bucket",\n "name": "management",\n "resource_group": "management-rg",\n "classic_access": false,\n "manual_address_prefix_management": true,\n "default_network_acl_name": null,\n "default_security_group_name": null,\n "default_routing_table_name": null,\n "publicGateways": [],\n "address_prefixes": [\n {\n "vpc": "management",\n "zone": 1,\n "name": "management-zone-1",\n "cidr": "10.10.0.0/22"\n },\n {\n "vpc": "management",\n "zone": 2,\n "name": "management-zone-2",\n "cidr": "10.20.0.0/22"\n },\n {\n "vpc": "management",\n "zone": 3,\n "name": "management-zone-3",\n "cidr": "10.30.0.0/22"\n }\n ],\n "subnets": [\n {\n "vpc": "management",\n "zone": 1,\n "cidr": "10.10.0.0/29",\n "name": "vsi-zone-1",\n "network_acl": "management",\n "resource_group": "management-rg",\n "public_gateway": false,\n "has_prefix": false\n },\n {\n "vpc": "management",\n "zone": 1,\n "cidr": "10.10.0.16/28",\n "name": "vpn-zone-1",\n "network_acl": "management",\n "resource_group": "management-rg",\n "public_gateway": false,\n "has_prefix": false\n },\n {\n "vpc": "management",\n "zone": 2,\n "cidr": "10.20.0.0/29",\n "name": "vsi-zone-2",\n "network_acl": "management",\n "resource_group": "management-rg",\n "public_gateway": false,\n "has_prefix": false\n },\n {\n "vpc": "management",\n "zone": 3,\n "cidr": "10.30.0.0/29",\n "name": "vsi-zone-3",\n "network_acl": "management",\n "resource_group": "management-rg",\n "public_gateway": false,\n "has_prefix": false\n },\n {\n "vpc": "management",\n "zone": 1,\n "cidr": "10.10.0.48/29",\n "name": "vpe-zone-1",\n "resource_group": "management-rg",\n "network_acl": "management",\n "public_gateway": false,\n "has_prefix": false\n },\n {\n "vpc": "management",\n "zone": 2,\n "cidr": "10.20.0.16/29",\n "name": "vpe-zone-2",\n "network_acl": "management",\n "resource_group": "management-rg",\n "public_gateway": false,\n "has_prefix": false\n },\n {\n "vpc": "management",\n "zone": 3,\n "cidr": "10.30.0.16/29",\n "name": "vpe-zone-3",\n "network_acl": "management",\n "resource_group": "management-rg",\n "public_gateway": false,\n "has_prefix": false\n }\n ],\n "public_gateways": [],\n "acls": [\n {\n "resource_group": "management-rg",\n "name": "management",\n "vpc": "management",\n "rules": [\n {\n "action": "allow",\n "destination": "10.0.0.0/8",\n "direction": "inbound",\n "name": "allow-ibm-inbound",\n "source": "161.26.0.0/16",\n "acl": "management",\n "vpc": "management",\n "icmp": {\n "type": null,\n "code": null\n },\n "tcp": {\n "port_min": null,\n "port_max": null,\n "source_port_min": null,\n "source_port_max": null\n },\n "udp": {\n "port_min": null,\n "port_max": null,\n "source_port_min": null,\n "source_port_max": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null,\n "source_port_min": null,\n "source_port_max": null\n },\n {\n "action": "allow",\n "source": "10.0.0.0/8",\n "direction": "outbound",\n "name": "allow-ibm-outbound",\n "destination": "161.26.0.0/16",\n "acl": "management",\n "vpc": "management",\n "icmp": {\n "type": null,\n "code": null\n },\n "tcp": {\n "port_min": null,\n "port_max": null,\n "source_port_min": null,\n "source_port_max": null\n },\n "udp": {\n "port_min": null,\n "port_max": null,\n "source_port_min": null,\n "source_port_max": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null,\n "source_port_min": null,\n "source_port_max": null\n },\n {\n "action": "allow",\n "destination": "10.0.0.0/8",\n "direction": "inbound",\n "name": "allow-all-network-inbound",\n "source": "10.0.0.0/8",\n "acl": "management",\n "vpc": "management",\n "icmp": {\n "type": null,\n "code": null\n },\n "tcp": {\n "port_min": null,\n "port_max": null,\n "source_port_min": null,\n "source_port_max": null\n },\n "udp": {\n "port_min": null,\n "port_max": null,\n "source_port_min": null,\n "source_port_max": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null,\n "source_port_min": null,\n "source_port_max": null\n },\n {\n "action": "allow",\n "destination": "10.0.0.0/8",\n "direction": "outbound",\n "name": "allow-all-network-outbound",\n "source": "10.0.0.0/8",\n "acl": "management",\n "vpc": "management",\n "icmp": {\n "type": null,\n "code": null\n },\n "tcp": {\n "port_min": null,\n "port_max": null,\n "source_port_min": null,\n "source_port_max": null\n },\n "udp": {\n "port_min": null,\n "port_max": null,\n "source_port_min": null,\n "source_port_max": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null,\n "source_port_min": null,\n "source_port_max": null\n }\n ],\n "use_data": false\n }\n ],\n "subnetTiers": [\n {\n "name": "vsi",\n "zones": 3\n },\n {\n "name": "vpn",\n "zones": 1\n },\n {\n "name": "vpe",\n "zones": 3\n }\n ],\n "use_data": false\n },\n {\n "cos": "cos",\n "bucket": "workload-bucket",\n "name": "workload",\n "resource_group": "workload-rg",\n "classic_access": false,\n "manual_address_prefix_management": true,\n "default_network_acl_name": null,\n "default_security_group_name": null,\n "default_routing_table_name": null,\n "publicGateways": [],\n "address_prefixes": [\n {\n "vpc": "workload",\n "zone": 1,\n "name": "workload-zone-1",\n "cidr": "10.40.0.0/22"\n },\n {\n "vpc": "workload",\n "zone": 2,\n "name": "workload-zone-2",\n "cidr": "10.50.0.0/22"\n },\n {\n "vpc": "workload",\n "zone": 3,\n "name": "workload-zone-3",\n "cidr": "10.60.0.0/22"\n }\n ],\n "subnets": [\n {\n "vpc": "workload",\n "zone": 1,\n "cidr": "10.40.0.0/28",\n "name": "vsi-zone-1",\n "network_acl": "workload",\n "resource_group": "workload-rg",\n "public_gateway": false,\n "has_prefix": false\n },\n {\n "vpc": "workload",\n "zone": 2,\n "cidr": "10.50.0.0/28",\n "name": "vsi-zone-2",\n "network_acl": "workload",\n "resource_group": "workload-rg",\n "public_gateway": false,\n "has_prefix": false\n },\n {\n "vpc": "workload",\n "zone": 3,\n "cidr": "10.60.0.0/28",\n "name": "vsi-zone-3",\n "network_acl": "workload",\n "resource_group": "workload-rg",\n "public_gateway": false,\n "has_prefix": false\n },\n {\n "vpc": "workload",\n "zone": 1,\n "cidr": "10.40.0.32/29",\n "name": "vpe-zone-1",\n "network_acl": "workload",\n "resource_group": "workload-rg",\n "public_gateway": false,\n "has_prefix": false\n },\n {\n "vpc": "workload",\n "zone": 2,\n "cidr": "10.50.0.32/29",\n "name": "vpe-zone-2",\n "network_acl": "workload",\n "resource_group": "workload-rg",\n "public_gateway": false,\n "has_prefix": false\n },\n {\n "vpc": "workload",\n "zone": 3,\n "cidr": "10.60.0.32/29",\n "name": "vpe-zone-3",\n "network_acl": "workload",\n "resource_group": "workload-rg",\n "public_gateway": false,\n "has_prefix": false\n }\n ],\n "public_gateways": [],\n "acls": [\n {\n "resource_group": "workload-rg",\n "name": "workload",\n "vpc": "workload",\n "rules": [\n {\n "action": "allow",\n "destination": "10.0.0.0/8",\n "direction": "inbound",\n "name": "allow-ibm-inbound",\n "source": "161.26.0.0/16",\n "acl": "workload",\n "vpc": "workload",\n "icmp": {\n "type": null,\n "code": null\n },\n "tcp": {\n "port_min": null,\n "port_max": null,\n "source_port_min": null,\n "source_port_max": null\n },\n "udp": {\n "port_min": null,\n "port_max": null,\n "source_port_min": null,\n "source_port_max": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null,\n "source_port_min": null,\n "source_port_max": null\n },\n {\n "action": "allow",\n "source": "10.0.0.0/8",\n "direction": "outbound",\n "name": "allow-ibm-outbound",\n "destination": "161.26.0.0/16",\n "acl": "workload",\n "vpc": "workload",\n "icmp": {\n "type": null,\n "code": null\n },\n "tcp": {\n "port_min": null,\n "port_max": null,\n "source_port_min": null,\n "source_port_max": null\n },\n "udp": {\n "port_min": null,\n "port_max": null,\n "source_port_min": null,\n "source_port_max": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null,\n "source_port_min": null,\n "source_port_max": null\n },\n {\n "action": "allow",\n "destination": "10.0.0.0/8",\n "direction": "inbound",\n "name": "allow-all-network-inbound",\n "source": "10.0.0.0/8",\n "acl": "workload",\n "vpc": "workload",\n "icmp": {\n "type": null,\n "code": null\n },\n "tcp": {\n "port_min": null,\n "port_max": null,\n "source_port_min": null,\n "source_port_max": null\n },\n "udp": {\n "port_min": null,\n "port_max": null,\n "source_port_min": null,\n "source_port_max": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null,\n "source_port_min": null,\n "source_port_max": null\n },\n {\n "action": "allow",\n "destination": "10.0.0.0/8",\n "direction": "outbound",\n "name": "allow-all-network-outbound",\n "source": "10.0.0.0/8",\n "acl": "workload",\n "vpc": "workload",\n "icmp": {\n "type": null,\n "code": null\n },\n "tcp": {\n "port_min": null,\n "port_max": null,\n "source_port_min": null,\n "source_port_max": null\n },\n "udp": {\n "port_min": null,\n "port_max": null,\n "source_port_min": null,\n "source_port_max": null\n },\n "ruleProtocol": "all",\n "port_min": null,\n "port_max": null,\n "type": null,\n "code": null,\n "source_port_min": null,\n "source_port_max": null\n }\n ],\n "use_data": false\n }\n ],\n "subnetTiers": [\n {\n "name": "vsi",\n "zones": 3\n },\n {\n "name": "vpe",\n "zones": 3\n }\n ],\n "use_data": false\n }\n ],\n "vpn_gateways": [\n {\n "name": "management-gateway",\n "resource_group": "management-rg",\n "subnet": "vpn-zone-1",\n "vpc": "management",\n "connections": [],\n "policy_mode": false,\n "additional_prefixes": []\n }\n ],\n "vpn_servers": [],\n "vsi": [\n {\n "kms": "kms",\n "encryption_key": "vsi-volume-key",\n "image": "ibm-ubuntu-22-04-1-minimal-amd64-1",\n "profile": "cx2-4x8",\n "name": "management-server",\n "security_groups": [\n "management-vsi"\n ],\n "ssh_keys": [\n "ssh-key"\n ],\n "subnets": [\n "vsi-zone-1",\n "vsi-zone-2",\n "vsi-zone-3"\n ],\n "vpc": "management",\n "vsi_per_subnet": 2,\n "resource_group": "management-rg",\n "override_vsi_name": null,\n "user_data": null,\n "network_interfaces": [],\n "volumes": [],\n "image_name": null,\n "enable_floating_ip": false,\n "primary_interface_ip_spoofing": false\n }\n ]\n}', }, { data: ' Apache License\nVersion 2.0, January 2004\nhttp://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n\n"License" shall mean the terms and conditions for use, reproduction,\nand distribution as defined by Sections 1 through 9 of this document.\n\n"Licensor" shall mean the copyright owner or entity authorized by\nthe copyright owner that is granting the License.\n\n"Legal Entity" shall mean the union of the acting entity and all\nother entities that control, are controlled by, or are under common\ncontrol with that entity. For the purposes of this definition,\n"control" means (i) the power, direct or indirect, to cause the\ndirection or management of such entity, whether by contract or\notherwise, or (ii) ownership of fifty percent (50%) or more of the\noutstanding shares, or (iii) beneficial ownership of such entity.\n\n"You" (or "Your") shall mean an individual or Legal Entity\nexercising permissions granted by this License.\n\n"Source" form shall mean the preferred form for making modifications,\nincluding but not limited to software source code, documentation\nsource, and configuration files.\n\n"Object" form shall mean any form resulting from mechanical\ntransformation or translation of a Source form, including but\nnot limited to compiled object code, generated documentation,\nand conversions to other media types.\n\n"Work" shall mean the work of authorship, whether in Source or\nObject form, made available under the License, as indicated by a\ncopyright notice that is included in or attached to the work\n(an example is provided in the Appendix below).\n\n"Derivative Works" shall mean any work, whether in Source or Object\nform, that is based on (or derived from) the Work and for which the\neditorial revisions, annotations, elaborations, or other modifications\nrepresent, as a whole, an original work of authorship. For the purposes\nof this License, Derivative Works shall not include works that remain\nseparable from, or merely link (or bind by name) to the interfaces of,\nthe Work and Derivative Works thereof.\n\n"Contribution" shall mean any work of authorship, including\nthe original version of the Work and any modifications or additions\nto that Work or Derivative Works thereof, that is intentionally\nsubmitted to Licensor for inclusion in the Work by the copyright owner\nor by an individual or Legal Entity authorized to submit on behalf of\nthe copyright owner. For the purposes of this definition, "submitted"\nmeans any form of electronic, verbal, or written communication sent\nto the Licensor or its representatives, including but not limited to\ncommunication on electronic mailing lists, source code control systems,\nand issue tracking systems that are managed by, or on behalf of, the\nLicensor for the purpose of discussing and improving the Work, but\nexcluding communication that is conspicuously marked or otherwise\ndesignated in writing by the copyright owner as "Not a Contribution."\n\n"Contributor" shall mean Licensor and any individual or Legal Entity\non behalf of whom a Contribution has been received by Licensor and\nsubsequently incorporated within the Work.\n\n2. Grant of Copyright License. Subject to the terms and conditions of\nthis License, each Contributor hereby grants to You a perpetual,\nworldwide, non-exclusive, no-charge, royalty-free, irrevocable\ncopyright license to reproduce, prepare Derivative Works of,\npublicly display, publicly perform, sublicense, and distribute the\nWork and such Derivative Works in Source or Object form.\n\n3. Grant of Patent License. Subject to the terms and conditions of\nthis License, each Contributor hereby grants to You a perpetual,\nworldwide, non-exclusive, no-charge, royalty-free, irrevocable\n(except as stated in this section) patent license to make, have made,\nuse, offer to sell, sell, import, and otherwise transfer the Work,\nwhere such license applies only to those patent claims licensable\nby such Contributor that are necessarily infringed by their\nContribution(s) alone or by combination of their Contribution(s)\nwith the Work to which such Contribution(s) was submitted. If You\ninstitute patent litigation against any entity (including a\ncross-claim or counterclaim in a lawsuit) alleging that the Work\nor a Contribution incorporated within the Work constitutes direct\nor contributory patent infringement, then any patent licenses\ngranted to You under this License for that Work shall terminate\nas of the date such litigation is filed.\n\n4. Redistribution. You may reproduce and distribute copies of the\nWork or Derivative Works thereof in any medium, with or without\nmodifications, and in Source or Object form, provided that You\nmeet the following conditions:\n\n(a) You must give any other recipients of the Work or\nDerivative Works a copy of this License; and\n\n(b) You must cause any modified files to carry prominent notices\nstating that You changed the files; and\n\n(c) You must retain, in the Source form of any Derivative Works\nthat You distribute, all copyright, patent, trademark, and\nattribution notices from the Source form of the Work,\nexcluding those notices that do not pertain to any part of\nthe Derivative Works; and\n\n(d) If the Work includes a "NOTICE" text file as part of its\ndistribution, then any Derivative Works that You distribute must\ninclude a readable copy of the attribution notices contained\nwithin such NOTICE file, excluding those notices that do not\npertain to any part of the Derivative Works, in at least one\nof the following places: within a NOTICE text file distributed\nas part of the Derivative Works; within the Source form or\ndocumentation, if provided along with the Derivative Works; or,\nwithin a display generated by the Derivative Works, if and\nwherever such third-party notices normally appear. The contents\nof the NOTICE file are for informational purposes only and\ndo not modify the License. You may add Your own attribution\nnotices within Derivative Works that You distribute, alongside\nor as an addendum to the NOTICE text from the Work, provided\nthat such additional attribution notices cannot be construed\nas modifying the License.\n\nYou may add Your own copyright statement to Your modifications and\nmay provide additional or different license terms and conditions\nfor use, reproduction, or distribution of Your modifications, or\nfor any such Derivative Works as a whole, provided Your use,\nreproduction, and distribution of the Work otherwise complies with\nthe conditions stated in this License.\n\n5. Submission of Contributions. Unless You explicitly state otherwise,\nany Contribution intentionally submitted for inclusion in the Work\nby You to the Licensor shall be under the terms and conditions of\nthis License, without any additional terms or conditions.\nNotwithstanding the above, nothing herein shall supersede or modify\nthe terms of any separate license agreement you may have executed\nwith Licensor regarding such Contributions.\n\n6. Trademarks. This License does not grant permission to use the trade\nnames, trademarks, service marks, or product names of the Licensor,\nexcept as required for reasonable and customary use in describing the\norigin of the Work and reproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty. Unless required by applicable law or\nagreed to in writing, Licensor provides the Work (and each\nContributor provides its Contributions) on an "AS IS" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\nimplied, including, without limitation, any warranties or conditions\nof TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\nPARTICULAR PURPOSE. You are solely responsible for determining the\nappropriateness of using or redistributing the Work and assume any\nrisks associated with Your exercise of permissions under this License.\n\n8. Limitation of Liability. In no event and under no legal theory,\nwhether in tort (including negligence), contract, or otherwise,\nunless required by applicable law (such as deliberate and grossly\nnegligent acts) or agreed to in writing, shall any Contributor be\nliable to You for damages, including any direct, indirect, special,\nincidental, or consequential damages of any character arising as a\nresult of this License or out of the use or inability to use the\nWork (including but not limited to damages for loss of goodwill,\nwork stoppage, computer failure or malfunction, or any and all\nother commercial damages or losses), even if such Contributor\nhas been advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability. While redistributing\nthe Work or Derivative Works thereof, You may choose to offer,\nand charge a fee for, acceptance of support, warranty, indemnity,\nor other liability obligations and/or rights consistent with this\nLicense. However, in accepting such obligations, You may act only\non Your own behalf and on Your sole responsibility, not on behalf\nof any other Contributor, and only if You agree to indemnify,\ndefend, and hold each Contributor harmless for any liability\nincurred by, or claims asserted against, such Contributor by reason\nof your accepting any such warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n\nAPPENDIX: How to apply the Apache License to your work.\n\nTo apply the Apache License to your work, attach the following\nboilerplate notice, with the fields enclosed by brackets "[]"\nreplaced with your own identifying information. (Don\'t include\nthe brackets!) The text should be enclosed in the appropriate\ncomment syntax for the file format. We also recommend that a\nfile or class name and description of purpose be included on the\nsame "printed page" as the copyright notice for easier\nidentification within third-party archives.\n\nCopyright [yyyy] [name of copyright owner]\n\nLicensed under the Apache License, Version 2.0 (the "License");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an "AS IS" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n', @@ -276,7 +276,7 @@ describe("craig api", () => { }, { name: "from-scratch/craig.json", - data: '{\n \"_options\": {\n \"prefix\": \"iac\",\n \"region\": \"us-south\",\n \"tags\": [\n \"hello\",\n \"world\"\n ],\n \"zones\": 3,\n \"endpoints\": \"private\",\n \"account_id\": null,\n \"fs_cloud\": false,\n \"enable_classic\": false,\n \"dynamic_subnets\": true,\n \"enable_power_vs\": false,\n \"craig_version\": \"1.12.0\",\n \"power_vs_zones\": [],\n \"power_vs_high_availability\": false,\n \"no_vpn_secrets_manager_auth\": false,\n \"power_vs_ha_zone_1\": null,\n \"power_vs_ha_zone_2\": null,\n \"manual_power_vsi_naming\": false\n },\n \"access_groups\": [],\n \"appid\": [],\n \"atracker\": {\n \"enabled\": false,\n \"type\": \"cos\",\n \"name\": \"atracker\",\n \"target_name\": \"atracker-cos\",\n \"bucket\": null,\n \"add_route\": true,\n \"cos_key\": null,\n \"locations\": [\n \"global\",\n \"us-south\"\n ],\n \"instance\": false,\n \"plan\": \"lite\",\n \"resource_group\": null,\n \"archive\": false\n },\n \"cbr_rules\": [],\n \"cbr_zones\": [],\n \"classic_ssh_keys\": [],\n \"classic_vlans\": [],\n \"clusters\": [],\n \"dns\": [],\n \"event_streams\": [],\n \"f5_vsi\": [],\n \"iam_account_settings\": {\n \"enable\": false,\n \"mfa\": null,\n \"allowed_ip_addresses\": null,\n \"include_history\": false,\n \"if_match\": null,\n \"max_sessions_per_identity\": null,\n \"restrict_create_service_id\": null,\n \"restrict_create_platform_apikey\": null,\n \"session_expiration_in_seconds\": null,\n \"session_invalidation_in_seconds\": null\n },\n \"icd\": [],\n \"key_management\": [],\n \"load_balancers\": [],\n \"logdna\": {\n \"name\": \"logdna\",\n \"archive\": false,\n \"enabled\": false,\n \"plan\": \"lite\",\n \"endpoints\": \"private\",\n \"platform_logs\": false,\n \"resource_group\": null,\n \"cos\": null,\n \"bucket\": null\n },\n \"object_storage\": [],\n \"power\": [],\n \"power_instances\": [],\n \"power_volumes\": [],\n \"resource_groups\": [\n {\n \"use_prefix\": true,\n \"name\": \"craig-rg\",\n \"use_data\": false\n }\n ],\n \"routing_tables\": [],\n \"scc\": {\n \"credential_description\": null,\n \"id\": null,\n \"passphrase\": null,\n \"name\": \"\",\n \"location\": \"us\",\n \"collector_description\": null,\n \"is_public\": false,\n \"scope_description\": null,\n \"enable\": false\n },\n \"secrets_manager\": [],\n \"security_groups\": [],\n \"ssh_keys\": [],\n \"sysdig\": {\n \"enabled\": false,\n \"plan\": \"graduated-tier\",\n \"resource_group\": null,\n \"name\": \"sysdig\",\n \"platform_logs\": false\n },\n \"teleport_vsi\": [],\n \"transit_gateways\": [],\n \"virtual_private_endpoints\": [],\n \"vpcs\": [],\n \"vpn_gateways\": [],\n \"vpn_servers\": [],\n \"vsi\": []\n}' + data: '{\n "_options": {\n "prefix": "iac",\n "region": "us-south",\n "tags": [\n "hello",\n "world"\n ],\n "zones": 3,\n "endpoints": "private",\n "account_id": null,\n "fs_cloud": false,\n "enable_classic": false,\n "dynamic_subnets": true,\n "enable_power_vs": false,\n "craig_version": "1.12.0",\n "power_vs_zones": [],\n "power_vs_high_availability": false,\n "no_vpn_secrets_manager_auth": false,\n "power_vs_ha_zone_1": null,\n "power_vs_ha_zone_2": null,\n "manual_power_vsi_naming": false\n },\n "access_groups": [],\n "appid": [],\n "atracker": {\n "enabled": false,\n "type": "cos",\n "name": "atracker",\n "target_name": "atracker-cos",\n "bucket": null,\n "add_route": true,\n "cos_key": null,\n "locations": [\n "global",\n "us-south"\n ],\n "instance": false,\n "plan": "lite",\n "resource_group": null,\n "archive": false\n },\n "cbr_rules": [],\n "cbr_zones": [],\n "classic_ssh_keys": [],\n "classic_vlans": [],\n "clusters": [],\n "dns": [],\n "event_streams": [],\n "f5_vsi": [],\n "iam_account_settings": {\n "enable": false,\n "mfa": null,\n "allowed_ip_addresses": null,\n "include_history": false,\n "if_match": null,\n "max_sessions_per_identity": null,\n "restrict_create_service_id": null,\n "restrict_create_platform_apikey": null,\n "session_expiration_in_seconds": null,\n "session_invalidation_in_seconds": null\n },\n "icd": [],\n "key_management": [],\n "load_balancers": [],\n "logdna": {\n "name": "logdna",\n "archive": false,\n "enabled": false,\n "plan": "lite",\n "endpoints": "private",\n "platform_logs": false,\n "resource_group": null,\n "cos": null,\n "bucket": null\n },\n "object_storage": [],\n "power": [],\n "power_instances": [],\n "power_volumes": [],\n "resource_groups": [\n {\n "use_prefix": true,\n "name": "craig-rg",\n "use_data": false\n }\n ],\n "routing_tables": [],\n "scc": {\n "credential_description": null,\n "id": null,\n "passphrase": null,\n "name": "",\n "location": "us",\n "collector_description": null,\n "is_public": false,\n "scope_description": null,\n "enable": false\n },\n "secrets_manager": [],\n "security_groups": [],\n "ssh_keys": [],\n "sysdig": {\n "enabled": false,\n "plan": "graduated-tier",\n "resource_group": null,\n "name": "sysdig",\n "platform_logs": false\n },\n "teleport_vsi": [],\n "transit_gateways": [],\n "virtual_private_endpoints": [],\n "vpcs": [],\n "vpn_gateways": [],\n "vpn_servers": [],\n "vsi": []\n}', }, { data: ' Apache License\nVersion 2.0, January 2004\nhttp://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n\n"License" shall mean the terms and conditions for use, reproduction,\nand distribution as defined by Sections 1 through 9 of this document.\n\n"Licensor" shall mean the copyright owner or entity authorized by\nthe copyright owner that is granting the License.\n\n"Legal Entity" shall mean the union of the acting entity and all\nother entities that control, are controlled by, or are under common\ncontrol with that entity. For the purposes of this definition,\n"control" means (i) the power, direct or indirect, to cause the\ndirection or management of such entity, whether by contract or\notherwise, or (ii) ownership of fifty percent (50%) or more of the\noutstanding shares, or (iii) beneficial ownership of such entity.\n\n"You" (or "Your") shall mean an individual or Legal Entity\nexercising permissions granted by this License.\n\n"Source" form shall mean the preferred form for making modifications,\nincluding but not limited to software source code, documentation\nsource, and configuration files.\n\n"Object" form shall mean any form resulting from mechanical\ntransformation or translation of a Source form, including but\nnot limited to compiled object code, generated documentation,\nand conversions to other media types.\n\n"Work" shall mean the work of authorship, whether in Source or\nObject form, made available under the License, as indicated by a\ncopyright notice that is included in or attached to the work\n(an example is provided in the Appendix below).\n\n"Derivative Works" shall mean any work, whether in Source or Object\nform, that is based on (or derived from) the Work and for which the\neditorial revisions, annotations, elaborations, or other modifications\nrepresent, as a whole, an original work of authorship. For the purposes\nof this License, Derivative Works shall not include works that remain\nseparable from, or merely link (or bind by name) to the interfaces of,\nthe Work and Derivative Works thereof.\n\n"Contribution" shall mean any work of authorship, including\nthe original version of the Work and any modifications or additions\nto that Work or Derivative Works thereof, that is intentionally\nsubmitted to Licensor for inclusion in the Work by the copyright owner\nor by an individual or Legal Entity authorized to submit on behalf of\nthe copyright owner. For the purposes of this definition, "submitted"\nmeans any form of electronic, verbal, or written communication sent\nto the Licensor or its representatives, including but not limited to\ncommunication on electronic mailing lists, source code control systems,\nand issue tracking systems that are managed by, or on behalf of, the\nLicensor for the purpose of discussing and improving the Work, but\nexcluding communication that is conspicuously marked or otherwise\ndesignated in writing by the copyright owner as "Not a Contribution."\n\n"Contributor" shall mean Licensor and any individual or Legal Entity\non behalf of whom a Contribution has been received by Licensor and\nsubsequently incorporated within the Work.\n\n2. Grant of Copyright License. Subject to the terms and conditions of\nthis License, each Contributor hereby grants to You a perpetual,\nworldwide, non-exclusive, no-charge, royalty-free, irrevocable\ncopyright license to reproduce, prepare Derivative Works of,\npublicly display, publicly perform, sublicense, and distribute the\nWork and such Derivative Works in Source or Object form.\n\n3. Grant of Patent License. Subject to the terms and conditions of\nthis License, each Contributor hereby grants to You a perpetual,\nworldwide, non-exclusive, no-charge, royalty-free, irrevocable\n(except as stated in this section) patent license to make, have made,\nuse, offer to sell, sell, import, and otherwise transfer the Work,\nwhere such license applies only to those patent claims licensable\nby such Contributor that are necessarily infringed by their\nContribution(s) alone or by combination of their Contribution(s)\nwith the Work to which such Contribution(s) was submitted. If You\ninstitute patent litigation against any entity (including a\ncross-claim or counterclaim in a lawsuit) alleging that the Work\nor a Contribution incorporated within the Work constitutes direct\nor contributory patent infringement, then any patent licenses\ngranted to You under this License for that Work shall terminate\nas of the date such litigation is filed.\n\n4. Redistribution. You may reproduce and distribute copies of the\nWork or Derivative Works thereof in any medium, with or without\nmodifications, and in Source or Object form, provided that You\nmeet the following conditions:\n\n(a) You must give any other recipients of the Work or\nDerivative Works a copy of this License; and\n\n(b) You must cause any modified files to carry prominent notices\nstating that You changed the files; and\n\n(c) You must retain, in the Source form of any Derivative Works\nthat You distribute, all copyright, patent, trademark, and\nattribution notices from the Source form of the Work,\nexcluding those notices that do not pertain to any part of\nthe Derivative Works; and\n\n(d) If the Work includes a "NOTICE" text file as part of its\ndistribution, then any Derivative Works that You distribute must\ninclude a readable copy of the attribution notices contained\nwithin such NOTICE file, excluding those notices that do not\npertain to any part of the Derivative Works, in at least one\nof the following places: within a NOTICE text file distributed\nas part of the Derivative Works; within the Source form or\ndocumentation, if provided along with the Derivative Works; or,\nwithin a display generated by the Derivative Works, if and\nwherever such third-party notices normally appear. The contents\nof the NOTICE file are for informational purposes only and\ndo not modify the License. You may add Your own attribution\nnotices within Derivative Works that You distribute, alongside\nor as an addendum to the NOTICE text from the Work, provided\nthat such additional attribution notices cannot be construed\nas modifying the License.\n\nYou may add Your own copyright statement to Your modifications and\nmay provide additional or different license terms and conditions\nfor use, reproduction, or distribution of Your modifications, or\nfor any such Derivative Works as a whole, provided Your use,\nreproduction, and distribution of the Work otherwise complies with\nthe conditions stated in this License.\n\n5. Submission of Contributions. Unless You explicitly state otherwise,\nany Contribution intentionally submitted for inclusion in the Work\nby You to the Licensor shall be under the terms and conditions of\nthis License, without any additional terms or conditions.\nNotwithstanding the above, nothing herein shall supersede or modify\nthe terms of any separate license agreement you may have executed\nwith Licensor regarding such Contributions.\n\n6. Trademarks. This License does not grant permission to use the trade\nnames, trademarks, service marks, or product names of the Licensor,\nexcept as required for reasonable and customary use in describing the\norigin of the Work and reproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty. Unless required by applicable law or\nagreed to in writing, Licensor provides the Work (and each\nContributor provides its Contributions) on an "AS IS" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\nimplied, including, without limitation, any warranties or conditions\nof TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\nPARTICULAR PURPOSE. You are solely responsible for determining the\nappropriateness of using or redistributing the Work and assume any\nrisks associated with Your exercise of permissions under this License.\n\n8. Limitation of Liability. In no event and under no legal theory,\nwhether in tort (including negligence), contract, or otherwise,\nunless required by applicable law (such as deliberate and grossly\nnegligent acts) or agreed to in writing, shall any Contributor be\nliable to You for damages, including any direct, indirect, special,\nincidental, or consequential damages of any character arising as a\nresult of this License or out of the use or inability to use the\nWork (including but not limited to damages for loss of goodwill,\nwork stoppage, computer failure or malfunction, or any and all\nother commercial damages or losses), even if such Contributor\nhas been advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability. While redistributing\nthe Work or Derivative Works thereof, You may choose to offer,\nand charge a fee for, acceptance of support, warranty, indemnity,\nor other liability obligations and/or rights consistent with this\nLicense. However, in accepting such obligations, You may act only\non Your own behalf and on Your sole responsibility, not on behalf\nof any other Contributor, and only if You agree to indemnify,\ndefend, and hold each Contributor harmless for any liability\nincurred by, or claims asserted against, such Contributor by reason\nof your accepting any such warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n\nAPPENDIX: How to apply the Apache License to your work.\n\nTo apply the Apache License to your work, attach the following\nboilerplate notice, with the fields enclosed by brackets "[]"\nreplaced with your own identifying information. (Don\'t include\nthe brackets!) The text should be enclosed in the appropriate\ncomment syntax for the file format. We also recommend that a\nfile or class name and description of purpose be included on the\nsame "printed page" as the copyright notice for easier\nidentification within third-party archives.\n\nCopyright [yyyy] [name of copyright owner]\n\nLicensed under the Apache License, Version 2.0 (the "License");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an "AS IS" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n', @@ -443,7 +443,7 @@ describe("craig api", () => { }, { name: "from-scratch/craig.json", - data: '{\n \"_options\": {\n \"prefix\": \"iac\",\n \"region\": \"us-south\",\n \"tags\": [\n \"hello\",\n \"world\"\n ],\n \"zones\": 3,\n \"endpoints\": \"private\",\n \"account_id\": null,\n \"fs_cloud\": false,\n \"enable_classic\": false,\n \"dynamic_subnets\": true,\n \"enable_power_vs\": false,\n \"craig_version\": \"1.12.0\",\n \"power_vs_zones\": [],\n \"power_vs_high_availability\": false,\n \"no_vpn_secrets_manager_auth\": false,\n \"power_vs_ha_zone_1\": null,\n \"power_vs_ha_zone_2\": null,\n \"manual_power_vsi_naming\": false\n },\n \"access_groups\": [],\n \"appid\": [],\n \"atracker\": {\n \"enabled\": false,\n \"type\": \"cos\",\n \"name\": \"atracker\",\n \"target_name\": \"atracker-cos\",\n \"bucket\": null,\n \"add_route\": true,\n \"cos_key\": null,\n \"locations\": [\n \"global\",\n \"us-south\"\n ],\n \"instance\": false,\n \"plan\": \"lite\",\n \"resource_group\": null,\n \"archive\": false\n },\n \"cbr_rules\": [],\n \"cbr_zones\": [],\n \"classic_ssh_keys\": [],\n \"classic_vlans\": [],\n \"clusters\": [],\n \"dns\": [],\n \"event_streams\": [],\n \"f5_vsi\": [],\n \"iam_account_settings\": {\n \"enable\": false,\n \"mfa\": null,\n \"allowed_ip_addresses\": null,\n \"include_history\": false,\n \"if_match\": null,\n \"max_sessions_per_identity\": null,\n \"restrict_create_service_id\": null,\n \"restrict_create_platform_apikey\": null,\n \"session_expiration_in_seconds\": null,\n \"session_invalidation_in_seconds\": null\n },\n \"icd\": [],\n \"key_management\": [],\n \"load_balancers\": [],\n \"logdna\": {\n \"name\": \"logdna\",\n \"archive\": false,\n \"enabled\": false,\n \"plan\": \"lite\",\n \"endpoints\": \"private\",\n \"platform_logs\": false,\n \"resource_group\": null,\n \"cos\": null,\n \"bucket\": null\n },\n \"object_storage\": [],\n \"power\": [],\n \"power_instances\": [],\n \"power_volumes\": [],\n \"resource_groups\": [\n {\n \"use_prefix\": true,\n \"name\": \"craig-rg\",\n \"use_data\": false\n },\n {\n \"use_prefix\": true,\n \"name\": \"added-rg\",\n \"use_data\": false\n }\n ],\n \"routing_tables\": [],\n \"scc\": {\n \"credential_description\": null,\n \"id\": null,\n \"passphrase\": null,\n \"name\": \"\",\n \"location\": \"us\",\n \"collector_description\": null,\n \"is_public\": false,\n \"scope_description\": null,\n \"enable\": false\n },\n \"secrets_manager\": [],\n \"security_groups\": [],\n \"ssh_keys\": [],\n \"sysdig\": {\n \"enabled\": false,\n \"plan\": \"graduated-tier\",\n \"resource_group\": null,\n \"name\": \"sysdig\",\n \"platform_logs\": false\n },\n \"teleport_vsi\": [],\n \"transit_gateways\": [],\n \"virtual_private_endpoints\": [],\n \"vpcs\": [],\n \"vpn_gateways\": [],\n \"vpn_servers\": [],\n \"vsi\": []\n}' + data: '{\n "_options": {\n "prefix": "iac",\n "region": "us-south",\n "tags": [\n "hello",\n "world"\n ],\n "zones": 3,\n "endpoints": "private",\n "account_id": null,\n "fs_cloud": false,\n "enable_classic": false,\n "dynamic_subnets": true,\n "enable_power_vs": false,\n "craig_version": "1.12.0",\n "power_vs_zones": [],\n "power_vs_high_availability": false,\n "no_vpn_secrets_manager_auth": false,\n "power_vs_ha_zone_1": null,\n "power_vs_ha_zone_2": null,\n "manual_power_vsi_naming": false\n },\n "access_groups": [],\n "appid": [],\n "atracker": {\n "enabled": false,\n "type": "cos",\n "name": "atracker",\n "target_name": "atracker-cos",\n "bucket": null,\n "add_route": true,\n "cos_key": null,\n "locations": [\n "global",\n "us-south"\n ],\n "instance": false,\n "plan": "lite",\n "resource_group": null,\n "archive": false\n },\n "cbr_rules": [],\n "cbr_zones": [],\n "classic_ssh_keys": [],\n "classic_vlans": [],\n "clusters": [],\n "dns": [],\n "event_streams": [],\n "f5_vsi": [],\n "iam_account_settings": {\n "enable": false,\n "mfa": null,\n "allowed_ip_addresses": null,\n "include_history": false,\n "if_match": null,\n "max_sessions_per_identity": null,\n "restrict_create_service_id": null,\n "restrict_create_platform_apikey": null,\n "session_expiration_in_seconds": null,\n "session_invalidation_in_seconds": null\n },\n "icd": [],\n "key_management": [],\n "load_balancers": [],\n "logdna": {\n "name": "logdna",\n "archive": false,\n "enabled": false,\n "plan": "lite",\n "endpoints": "private",\n "platform_logs": false,\n "resource_group": null,\n "cos": null,\n "bucket": null\n },\n "object_storage": [],\n "power": [],\n "power_instances": [],\n "power_volumes": [],\n "resource_groups": [\n {\n "use_prefix": true,\n "name": "craig-rg",\n "use_data": false\n },\n {\n "use_prefix": true,\n "name": "added-rg",\n "use_data": false\n }\n ],\n "routing_tables": [],\n "scc": {\n "credential_description": null,\n "id": null,\n "passphrase": null,\n "name": "",\n "location": "us",\n "collector_description": null,\n "is_public": false,\n "scope_description": null,\n "enable": false\n },\n "secrets_manager": [],\n "security_groups": [],\n "ssh_keys": [],\n "sysdig": {\n "enabled": false,\n "plan": "graduated-tier",\n "resource_group": null,\n "name": "sysdig",\n "platform_logs": false\n },\n "teleport_vsi": [],\n "transit_gateways": [],\n "virtual_private_endpoints": [],\n "vpcs": [],\n "vpn_gateways": [],\n "vpn_servers": [],\n "vsi": []\n}', }, { data: ' Apache License\nVersion 2.0, January 2004\nhttp://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n\n"License" shall mean the terms and conditions for use, reproduction,\nand distribution as defined by Sections 1 through 9 of this document.\n\n"Licensor" shall mean the copyright owner or entity authorized by\nthe copyright owner that is granting the License.\n\n"Legal Entity" shall mean the union of the acting entity and all\nother entities that control, are controlled by, or are under common\ncontrol with that entity. For the purposes of this definition,\n"control" means (i) the power, direct or indirect, to cause the\ndirection or management of such entity, whether by contract or\notherwise, or (ii) ownership of fifty percent (50%) or more of the\noutstanding shares, or (iii) beneficial ownership of such entity.\n\n"You" (or "Your") shall mean an individual or Legal Entity\nexercising permissions granted by this License.\n\n"Source" form shall mean the preferred form for making modifications,\nincluding but not limited to software source code, documentation\nsource, and configuration files.\n\n"Object" form shall mean any form resulting from mechanical\ntransformation or translation of a Source form, including but\nnot limited to compiled object code, generated documentation,\nand conversions to other media types.\n\n"Work" shall mean the work of authorship, whether in Source or\nObject form, made available under the License, as indicated by a\ncopyright notice that is included in or attached to the work\n(an example is provided in the Appendix below).\n\n"Derivative Works" shall mean any work, whether in Source or Object\nform, that is based on (or derived from) the Work and for which the\neditorial revisions, annotations, elaborations, or other modifications\nrepresent, as a whole, an original work of authorship. For the purposes\nof this License, Derivative Works shall not include works that remain\nseparable from, or merely link (or bind by name) to the interfaces of,\nthe Work and Derivative Works thereof.\n\n"Contribution" shall mean any work of authorship, including\nthe original version of the Work and any modifications or additions\nto that Work or Derivative Works thereof, that is intentionally\nsubmitted to Licensor for inclusion in the Work by the copyright owner\nor by an individual or Legal Entity authorized to submit on behalf of\nthe copyright owner. For the purposes of this definition, "submitted"\nmeans any form of electronic, verbal, or written communication sent\nto the Licensor or its representatives, including but not limited to\ncommunication on electronic mailing lists, source code control systems,\nand issue tracking systems that are managed by, or on behalf of, the\nLicensor for the purpose of discussing and improving the Work, but\nexcluding communication that is conspicuously marked or otherwise\ndesignated in writing by the copyright owner as "Not a Contribution."\n\n"Contributor" shall mean Licensor and any individual or Legal Entity\non behalf of whom a Contribution has been received by Licensor and\nsubsequently incorporated within the Work.\n\n2. Grant of Copyright License. Subject to the terms and conditions of\nthis License, each Contributor hereby grants to You a perpetual,\nworldwide, non-exclusive, no-charge, royalty-free, irrevocable\ncopyright license to reproduce, prepare Derivative Works of,\npublicly display, publicly perform, sublicense, and distribute the\nWork and such Derivative Works in Source or Object form.\n\n3. Grant of Patent License. Subject to the terms and conditions of\nthis License, each Contributor hereby grants to You a perpetual,\nworldwide, non-exclusive, no-charge, royalty-free, irrevocable\n(except as stated in this section) patent license to make, have made,\nuse, offer to sell, sell, import, and otherwise transfer the Work,\nwhere such license applies only to those patent claims licensable\nby such Contributor that are necessarily infringed by their\nContribution(s) alone or by combination of their Contribution(s)\nwith the Work to which such Contribution(s) was submitted. If You\ninstitute patent litigation against any entity (including a\ncross-claim or counterclaim in a lawsuit) alleging that the Work\nor a Contribution incorporated within the Work constitutes direct\nor contributory patent infringement, then any patent licenses\ngranted to You under this License for that Work shall terminate\nas of the date such litigation is filed.\n\n4. Redistribution. You may reproduce and distribute copies of the\nWork or Derivative Works thereof in any medium, with or without\nmodifications, and in Source or Object form, provided that You\nmeet the following conditions:\n\n(a) You must give any other recipients of the Work or\nDerivative Works a copy of this License; and\n\n(b) You must cause any modified files to carry prominent notices\nstating that You changed the files; and\n\n(c) You must retain, in the Source form of any Derivative Works\nthat You distribute, all copyright, patent, trademark, and\nattribution notices from the Source form of the Work,\nexcluding those notices that do not pertain to any part of\nthe Derivative Works; and\n\n(d) If the Work includes a "NOTICE" text file as part of its\ndistribution, then any Derivative Works that You distribute must\ninclude a readable copy of the attribution notices contained\nwithin such NOTICE file, excluding those notices that do not\npertain to any part of the Derivative Works, in at least one\nof the following places: within a NOTICE text file distributed\nas part of the Derivative Works; within the Source form or\ndocumentation, if provided along with the Derivative Works; or,\nwithin a display generated by the Derivative Works, if and\nwherever such third-party notices normally appear. The contents\nof the NOTICE file are for informational purposes only and\ndo not modify the License. You may add Your own attribution\nnotices within Derivative Works that You distribute, alongside\nor as an addendum to the NOTICE text from the Work, provided\nthat such additional attribution notices cannot be construed\nas modifying the License.\n\nYou may add Your own copyright statement to Your modifications and\nmay provide additional or different license terms and conditions\nfor use, reproduction, or distribution of Your modifications, or\nfor any such Derivative Works as a whole, provided Your use,\nreproduction, and distribution of the Work otherwise complies with\nthe conditions stated in this License.\n\n5. Submission of Contributions. Unless You explicitly state otherwise,\nany Contribution intentionally submitted for inclusion in the Work\nby You to the Licensor shall be under the terms and conditions of\nthis License, without any additional terms or conditions.\nNotwithstanding the above, nothing herein shall supersede or modify\nthe terms of any separate license agreement you may have executed\nwith Licensor regarding such Contributions.\n\n6. Trademarks. This License does not grant permission to use the trade\nnames, trademarks, service marks, or product names of the Licensor,\nexcept as required for reasonable and customary use in describing the\norigin of the Work and reproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty. Unless required by applicable law or\nagreed to in writing, Licensor provides the Work (and each\nContributor provides its Contributions) on an "AS IS" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\nimplied, including, without limitation, any warranties or conditions\nof TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\nPARTICULAR PURPOSE. You are solely responsible for determining the\nappropriateness of using or redistributing the Work and assume any\nrisks associated with Your exercise of permissions under this License.\n\n8. Limitation of Liability. In no event and under no legal theory,\nwhether in tort (including negligence), contract, or otherwise,\nunless required by applicable law (such as deliberate and grossly\nnegligent acts) or agreed to in writing, shall any Contributor be\nliable to You for damages, including any direct, indirect, special,\nincidental, or consequential damages of any character arising as a\nresult of this License or out of the use or inability to use the\nWork (including but not limited to damages for loss of goodwill,\nwork stoppage, computer failure or malfunction, or any and all\nother commercial damages or losses), even if such Contributor\nhas been advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability. While redistributing\nthe Work or Derivative Works thereof, You may choose to offer,\nand charge a fee for, acceptance of support, warranty, indemnity,\nor other liability obligations and/or rights consistent with this\nLicense. However, in accepting such obligations, You may act only\non Your own behalf and on Your sole responsibility, not on behalf\nof any other Contributor, and only if You agree to indemnify,\ndefend, and hold each Contributor harmless for any liability\nincurred by, or claims asserted against, such Contributor by reason\nof your accepting any such warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n\nAPPENDIX: How to apply the Apache License to your work.\n\nTo apply the Apache License to your work, attach the following\nboilerplate notice, with the fields enclosed by brackets "[]"\nreplaced with your own identifying information. (Don\'t include\nthe brackets!) The text should be enclosed in the appropriate\ncomment syntax for the file format. We also recommend that a\nfile or class name and description of purpose be included on the\nsame "printed page" as the copyright notice for easier\nidentification within third-party archives.\n\nCopyright [yyyy] [name of copyright owner]\n\nLicensed under the Apache License, Version 2.0 (the "License");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an "AS IS" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n', diff --git a/unit-tests/api/vsi-api.test.js b/unit-tests/api/vsi-api.test.js index 445cfb17..4b9a0edb 100644 --- a/unit-tests/api/vsi-api.test.js +++ b/unit-tests/api/vsi-api.test.js @@ -110,4 +110,35 @@ describe("vsi api", () => { }); }); }); + describe("vsiSnapShots", () => { + let data; + beforeEach(() => { + data = [{ name: "frog" }, { name: "toad" }]; + }); + it("should respond with the correct data", () => { + let { axios } = initMockAxios({ snapshots: data }); + let testController = new controller(axios); + testController.getBearerToken = () => { + return new Promise((resolve) => resolve("token")); + }; + return testController + .vsiSnapShots({ params: { region: "us-south" } }, res) + .then(() => { + assert.isTrue(res.send.calledOnce); + assert.isTrue( + res.send.calledOnceWith(["frog", "toad"]), + "it should get images" + ); + }); + }); + it("should respond with error", () => { + let { axios } = initMockAxios(vsiImagesRaw, true); + let testController = new controller(axios); + return testController + .vsiSnapShots({ params: { region: "us-south" } }, res) + .then(() => { + assert.isTrue(res.send.calledOnce); + }); + }); + }); }); diff --git a/unit-tests/json-to-iac/vsi.test.js b/unit-tests/json-to-iac/vsi.test.js index f440cb90..43e18420 100644 --- a/unit-tests/json-to-iac/vsi.test.js +++ b/unit-tests/json-to-iac/vsi.test.js @@ -1362,6 +1362,191 @@ resource "ibm_is_instance" "management_vpc_management_server_vsi_3_2" { ] } +############################################################################## +`; + assert.deepEqual( + actualData, + expectedData, + "it should return correct data" + ); + }); + it("should create vsi terraform with server deployment from boot volume", () => { + let nw = {}; + transpose(slzNetwork, nw); + nw.vsi = [ + { + kms: "slz-kms", + encryption_key: "slz-vsi-volume-key", + profile: "cx2-4x8", + name: "management-server", + security_groups: ["management-vpe-sg"], + ssh_keys: ["slz-ssh-key"], + subnets: ["vsi-zone-1", "vsi-zone-2", "vsi-zone-3"], + vpc: "management", + vsi_per_subnet: 2, + resource_group: "slz-management-rg", + snapshot: "example-snapshot", + }, + ]; + let actualData = vsiTf(nw); + let expectedData = `############################################################################## +# Snapshot Sources +############################################################################## + +data "ibm_is_snapshot" "snapshot_example_snapshot" { + name = "example-snapshot" +} + +############################################################################## + +############################################################################## +# Management VPC Management Server Deployment +############################################################################## + +resource "ibm_is_instance" "management_vpc_management_server_vsi_1_1" { + name = "\${var.prefix}-management-management-server-vsi-zone-1-1" + profile = "cx2-4x8" + resource_group = ibm_resource_group.slz_management_rg.id + vpc = module.management_vpc.id + zone = "\${var.region}-1" + tags = [ + "slz", + "landing-zone" + ] + primary_network_interface { + subnet = module.management_vpc.vsi_zone_1_id + security_groups = [ + module.management_vpc.management_vpe_sg_id + ] + } + boot_volume { + snapshot = data.ibm_is_snapshot.snapshot_example_snapshot.id + } + keys = [ + ibm_is_ssh_key.slz_ssh_key.id + ] +} + +resource "ibm_is_instance" "management_vpc_management_server_vsi_1_2" { + name = "\${var.prefix}-management-management-server-vsi-zone-1-2" + profile = "cx2-4x8" + resource_group = ibm_resource_group.slz_management_rg.id + vpc = module.management_vpc.id + zone = "\${var.region}-1" + tags = [ + "slz", + "landing-zone" + ] + primary_network_interface { + subnet = module.management_vpc.vsi_zone_1_id + security_groups = [ + module.management_vpc.management_vpe_sg_id + ] + } + boot_volume { + snapshot = data.ibm_is_snapshot.snapshot_example_snapshot.id + } + keys = [ + ibm_is_ssh_key.slz_ssh_key.id + ] +} + +resource "ibm_is_instance" "management_vpc_management_server_vsi_2_1" { + name = "\${var.prefix}-management-management-server-vsi-zone-2-1" + profile = "cx2-4x8" + resource_group = ibm_resource_group.slz_management_rg.id + vpc = module.management_vpc.id + zone = "\${var.region}-2" + tags = [ + "slz", + "landing-zone" + ] + primary_network_interface { + subnet = module.management_vpc.vsi_zone_2_id + security_groups = [ + module.management_vpc.management_vpe_sg_id + ] + } + boot_volume { + snapshot = data.ibm_is_snapshot.snapshot_example_snapshot.id + } + keys = [ + ibm_is_ssh_key.slz_ssh_key.id + ] +} + +resource "ibm_is_instance" "management_vpc_management_server_vsi_2_2" { + name = "\${var.prefix}-management-management-server-vsi-zone-2-2" + profile = "cx2-4x8" + resource_group = ibm_resource_group.slz_management_rg.id + vpc = module.management_vpc.id + zone = "\${var.region}-2" + tags = [ + "slz", + "landing-zone" + ] + primary_network_interface { + subnet = module.management_vpc.vsi_zone_2_id + security_groups = [ + module.management_vpc.management_vpe_sg_id + ] + } + boot_volume { + snapshot = data.ibm_is_snapshot.snapshot_example_snapshot.id + } + keys = [ + ibm_is_ssh_key.slz_ssh_key.id + ] +} + +resource "ibm_is_instance" "management_vpc_management_server_vsi_3_1" { + name = "\${var.prefix}-management-management-server-vsi-zone-3-1" + profile = "cx2-4x8" + resource_group = ibm_resource_group.slz_management_rg.id + vpc = module.management_vpc.id + zone = "\${var.region}-3" + tags = [ + "slz", + "landing-zone" + ] + primary_network_interface { + subnet = module.management_vpc.vsi_zone_3_id + security_groups = [ + module.management_vpc.management_vpe_sg_id + ] + } + boot_volume { + snapshot = data.ibm_is_snapshot.snapshot_example_snapshot.id + } + keys = [ + ibm_is_ssh_key.slz_ssh_key.id + ] +} + +resource "ibm_is_instance" "management_vpc_management_server_vsi_3_2" { + name = "\${var.prefix}-management-management-server-vsi-zone-3-2" + profile = "cx2-4x8" + resource_group = ibm_resource_group.slz_management_rg.id + vpc = module.management_vpc.id + zone = "\${var.region}-3" + tags = [ + "slz", + "landing-zone" + ] + primary_network_interface { + subnet = module.management_vpc.vsi_zone_3_id + security_groups = [ + module.management_vpc.management_vpe_sg_id + ] + } + boot_volume { + snapshot = data.ibm_is_snapshot.snapshot_example_snapshot.id + } + keys = [ + ibm_is_ssh_key.slz_ssh_key.id + ] +} + ############################################################################## `; assert.deepEqual( From bc6fed2b7defc095c1779132123d3e7380f269c2 Mon Sep 17 00:00:00 2001 From: jvallexm Date: Tue, 26 Mar 2024 16:04:53 -0400 Subject: [PATCH 06/17] Issue 1671: Get ansible script to run as a schematics action (#1737) * rm vars_files for schematics * rm vars_files for schematics * gitignore * rm /vars * timeout for download_tar * rm async from wait for tar * chagne command to uri * timeout * rm timeout * quotes * register upload_tar * uri again * use shell * variabletore to not use template_map * template-vars * add vars.yml for map * naming * naming * comments * clearer comments * use ansible.builtin * accept 404 * typo * tf_var * tags * change tags and action vars * spelling --------- Co-authored-by: Connor Terech --- .gitignore | 4 +--- ansible/template-test/main.yml | 23 ++++++------------- .../template-test/roles/action/tasks/main.yml | 6 ++--- .../roles/await_action/tasks/main.yml | 2 +- .../tasks/main.yml | 4 ++-- .../tasks/main.yml | 2 +- .../roles/download_tar/tasks/main.yml | 2 +- .../roles/get_iam_token/tasks/main.yml | 2 +- .../roles/update_variablestore/tasks/main.yml | 4 ++-- .../vars/{vars.template.yml => vars.yml} | 20 ++++++++-------- 10 files changed, 30 insertions(+), 39 deletions(-) rename ansible/template-test/vars/{vars.template.yml => vars.yml} (63%) diff --git a/.gitignore b/.gitignore index f18d8ac0..cfe36b94 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,4 @@ tfxjs.tfvars /build .icse/ tf-test/ -dev/ - -vars.yml \ No newline at end of file +dev/ \ No newline at end of file diff --git a/ansible/template-test/main.yml b/ansible/template-test/main.yml index 292a6cd6..76f2c765 100644 --- a/ansible/template-test/main.yml +++ b/ansible/template-test/main.yml @@ -16,19 +16,17 @@ - role: create_schematics_workspace vars: description: Automated CRAIG Testing Workspace - tags: ["craig"] - name: TODO - convert to roles hosts: localhost vars_files: ./vars/vars.yml tasks: - name: Upload {{template}}.tar to Schematics Workspace - command: "curl -s --request PUT \ + ansible.builtin.shell: "curl -s --request PUT \ --url 'https://schematics.cloud.ibm.com/v1/workspaces/{{ workspace.json.id }}/template_data/{{ workspace.json.template_data[0].id }}/template_repo_upload' \ -H 'Authorization: Bearer {{ token.json.access_token }}' \ -H 'Content-Type: multipart/form-data' \ --form 'file=@{{playbook_dir}}/{{template}}.tar'" - async: 120 - name: Wait until {{template}}.tar has been successfully uploaded uri: url: https://schematics.cloud.ibm.com/v1/workspaces/{{ workspace.json.id }} @@ -45,13 +43,6 @@ vars_files: ./vars/vars.yml roles: - role: update_variablestore - vars: - # Additional variables can be added to the variablestore by adding elements to the array below. - # Each element must be a map of the following key/value pairs: - # {'name': string, 'secure': bool, 'use_default': bool, 'value': variable_value} - # Note: If using a variable defined in /vars/vars.yml, specify the map using the following syntax: - # {'name': string, 'secure': bool, 'use_default': bool, 'value': "{{variable}}"} - additional_variables: [{'name': ssh_key_public_key, 'secure': true, 'use_default': false, 'value': "{{ssh_key}}"}] - role: update_workspace_variables - name: Start generate plan action hosts: localhost @@ -60,29 +51,29 @@ - role: get_iam_token - role: action vars: - action: plan + action_type: plan - role: get_iam_token - role: await_action vars: - action: plan + action_type: plan register_name: await_plan - role: get_iam_token - role: action vars: - action: apply + action_type: apply - role: get_iam_token - role: await_action vars: - action: apply + action_type: apply register_name: await_apply - role: get_iam_token - role: action vars: - action: destroy + action_type: destroy - role: get_iam_token - role: await_action vars: - action: destroy + action_type: destroy register_name: await_destroy - role: get_iam_token - role: delete_schematics_workspace \ No newline at end of file diff --git a/ansible/template-test/roles/action/tasks/main.yml b/ansible/template-test/roles/action/tasks/main.yml index 9ad4bec3..661382e8 100644 --- a/ansible/template-test/roles/action/tasks/main.yml +++ b/ansible/template-test/roles/action/tasks/main.yml @@ -1,9 +1,9 @@ --- # tasks file for action -- name: Start {{ action }} action +- name: Start {{ action_type }} action uri: - url: https://schematics.cloud.ibm.com/v1/workspaces/{{ workspace.json.id }}/{{ action }} - method: "{{ 'POST' if action == 'plan' else 'PUT' }}" + url: https://schematics.cloud.ibm.com/v1/workspaces/{{ workspace.json.id }}/{{ action_type }} + method: "{{ 'POST' if action_type == 'plan' else 'PUT' }}" body_format: json headers: Authorization: Bearer {{token.json.access_token}} diff --git a/ansible/template-test/roles/await_action/tasks/main.yml b/ansible/template-test/roles/await_action/tasks/main.yml index 969284ae..8fd981d2 100644 --- a/ansible/template-test/roles/await_action/tasks/main.yml +++ b/ansible/template-test/roles/await_action/tasks/main.yml @@ -1,4 +1,4 @@ -- name: Ensure {{ action }} finishes +- name: Ensure {{ action_type }} finishes uri: url: https://schematics.cloud.ibm.com/v2/jobs/{{ action_result.json.activityid }} method: GET diff --git a/ansible/template-test/roles/create_schematics_workspace/tasks/main.yml b/ansible/template-test/roles/create_schematics_workspace/tasks/main.yml index 6f9e9b49..3e286dca 100644 --- a/ansible/template-test/roles/create_schematics_workspace/tasks/main.yml +++ b/ansible/template-test/roles/create_schematics_workspace/tasks/main.yml @@ -12,8 +12,8 @@ "resource_group": "{{ resource_group }}" "type": ["terraform_v1.5"] "location": "{{ region }}" - "description": "{{ description }}" - "tags": "{{ tags }}" + "description": "Automated CRAIG Testing Workspace" + "tags": ["craig"] "template_data": [{ "type": "terraform_v1.5"}] status_code: 201 register: workspace \ No newline at end of file diff --git a/ansible/template-test/roles/delete_schematics_workspace/tasks/main.yml b/ansible/template-test/roles/delete_schematics_workspace/tasks/main.yml index 9a02962b..7b98c631 100644 --- a/ansible/template-test/roles/delete_schematics_workspace/tasks/main.yml +++ b/ansible/template-test/roles/delete_schematics_workspace/tasks/main.yml @@ -8,6 +8,6 @@ Authorization: Bearer {{token.json.access_token}} status_code: 200 register: delete_response - until: delete_response.status == 200 + until: delete_response.status == 200 or delete_response.status == 404 retries: 2 delay: 120 \ No newline at end of file diff --git a/ansible/template-test/roles/download_tar/tasks/main.yml b/ansible/template-test/roles/download_tar/tasks/main.yml index 35686117..f941132c 100644 --- a/ansible/template-test/roles/download_tar/tasks/main.yml +++ b/ansible/template-test/roles/download_tar/tasks/main.yml @@ -4,5 +4,5 @@ get_url: url: "{{craig_url}}/{{template}}" dest: "{{playbook_dir}}/{{template}}.tar" - async: 120 + timeout: 300 retries: 10 \ No newline at end of file diff --git a/ansible/template-test/roles/get_iam_token/tasks/main.yml b/ansible/template-test/roles/get_iam_token/tasks/main.yml index 2e1c2090..1019ca86 100644 --- a/ansible/template-test/roles/get_iam_token/tasks/main.yml +++ b/ansible/template-test/roles/get_iam_token/tasks/main.yml @@ -6,5 +6,5 @@ method: POST headers: Content-Type: application/x-www-form-urlencoded - body: "grant_type=urn:ibm:params:oauth:grant-type:apikey&apikey={{api_key}}" + body: "grant_type=urn:ibm:params:oauth:grant-type:apikey&apikey={{tf_var_api_key}}" register: token diff --git a/ansible/template-test/roles/update_variablestore/tasks/main.yml b/ansible/template-test/roles/update_variablestore/tasks/main.yml index 315992d8..92c9f9af 100644 --- a/ansible/template-test/roles/update_variablestore/tasks/main.yml +++ b/ansible/template-test/roles/update_variablestore/tasks/main.yml @@ -1,6 +1,6 @@ --- # tasks file for update_variablestore -- name: Add variable to variable store +- name: Update variablestore set_fact: - variablestore: "{{ variablestore + additional_variables }}" + variablestore: "{{ variablestore + [{'name': item, 'secure': true, 'use_default': false, 'value': tf_var_ssh_key}] }}" loop: "{{template_map[template]}}" \ No newline at end of file diff --git a/ansible/template-test/vars/vars.template.yml b/ansible/template-test/vars/vars.yml similarity index 63% rename from ansible/template-test/vars/vars.template.yml rename to ansible/template-test/vars/vars.yml index bc4626c0..0be0931d 100644 --- a/ansible/template-test/vars/vars.template.yml +++ b/ansible/template-test/vars/vars.yml @@ -1,11 +1,13 @@ --- -# Copy this file to `vars.yml` and fill in your data +# To run this in schematics actions, you will need to update the below commented out variables inside of schematics +# DO NOT ENTER YOUR VARIBLES HERE. THIS FILE SHOULD NEVER BE EDITED +# Do not alter the other variables. -api_key: -ssh_key: -prefix: -template: