Lab 1: Getting started with the basics¶
As a starting point use [IasCable](https://github.com/cloud-native-toolkit/iascable).
1. The IasCable framework¶
 Let us look at the basic components of the IasCable framework.
Bill of Material and Modules¶
The IasCable uses a Bill of Material and Modules(from the TechZone Accelerator Toolkit), this is an important point to understand. Bill of Material (BOM) and Modules are the heart of the framework to realize the objective to build an installable component infrastructure based on components from a catalog of available modules.
Please visit the linked resources for more details.
In a simplified way, we can say a BOM is specified by modules it uses, variables you can define and providers you can define. In addition you have the option to use variables and providers definitions related to a BOM specification. It is good to know that Modules can have dependencies to other modules, if this is the case the related modules will be included by the framework, as far as I understand.
We can simply say a BOM is specified by modules it uses. In addition you have the option to use variables and providers definitions related to a BOM specification. It is good to know that Modules can have dependencies to other modules, if this is the case, the related modules will be included by the framework, as far as I understand.
Here is a simplified overview diagram of the dependencies:

Here is a simplified activity diagram that shows the activities carried out by the user and the IasCable framework.

Realize Technology Zone Accelerator Toolkit with Bill of Material and Modules¶
Simplified we can say, we have two basic roles in that context:
- Creators(Architect, Developer or Operator) defining Bill of Materials to create Terraform automation for creating specific infrastructure based on reusing existing Terraform modules.
- Consumerswho using the created Terraform automation based on the- BOMdefinition.
And we have two major elements to define and create the needed Terraform automation.
- The BOMconfiguresIasCableto point to right Terraform modules in a module catalog to create the Terraform automation code.
- IasCableis uses Terraform modules to create a Terraform automation which will be consumed.
The following diagram shows some high level dependencies.

2. Pre-requisites for the example¶
Following tools need to be installed on your local computer to follow the step by step instructions.
- Terraform
- Git
That is the cloud environment we will use.
3. Step-by-step example setup¶
 This is a step by step set up example to create a Virtual Private Cloud with three Subnets on IBM Cloud.
- 1 x Virtual Private Cloud
- 3 x Subnets
- 2 x Access Control Lists
- 1 x Routing Table
-  2 x Security Groups
-  Simplified architecture overview 

Step 1: Install CLI¶
curl -sL https://iascable.cloudnativetoolkit.dev/install.sh | sh
Step 2: Verify the installation¶
iascable build --help
- Example output:
Configure (and optionally deploy) the iteration zero assets
Options:
      --version                   Show version number   [boolean]
      --help                      Show help             [boolean]
  -u, --catalogUrl                The url of the module catalog.
                                  Can be https:// or file:/
                                  protocol.
   [default: "https://modules.cloudnativetoolkit.dev/index.yaml"]
  -i, --input                     The path to the bill of
                                  materials to use as input
                                                          [array]
  -r, --reference                 The reference BOM to use for
                                  the build               [array]
  -o, --outDir                    The base directory where the
                                  command output will be written
                                            [default: "./output"]
      --platform                  Filter for the platform
                                  (kubernetes or ocp4)
      --provider                  Filter for the provider (ibm or
                                  k8s)
      --tileLabel                 The label for the tile.
                                  Required if you want to
                                  generate the tile metadata.
      --name                      The name used to override the
                                  module name in the bill of
                                  material.               [array]
      --tileDescription           The description of the tile.
      --flattenOutput, --flatten  Flatten the generated output
                                  into a single directory (i.e.
                                  remove the terraform folder).
                                                        [boolean]
      --debug                     Flag to turn on more detailed
                                  output message        [boolean]
Step 3: Create a Bill of Materials(BOM) file¶
 nano firstbom.yaml
Copy following content into the new file:
apiVersion: cloudnativetoolkit.dev/v1alpha1
kind: BillOfMaterial
metadata:
  name: ibm-vpc
spec:
  modules:
    - name: ibm-vpc
    - name: ibm-vpc-subnets
Step 4: Execute following command¶
iascable build -i firstbom.yaml
Step 5: Verify the created content¶
├── firstbom.yaml
└── output
    ├── ibm-vpc
    │   ├── apply.sh
    │   ├── bom.yaml
    │   ├── dependencies.dot
    │   ├── destroy.sh
    │   └── terraform
    │       ├── docs
    │       │   ├── ibm-resource-group.md
    │       │   ├── ibm-vpc-subnets.md
    │       │   └── ibm-vpc.md
    │       ├── ibm-vpc.auto.tfvars
    │       ├── main.tf
    │       ├── providers.tf
    │       ├── variables.tf
    │       └── version.tf
    └── launch.sh
- outputfolder
The folder output contains all the content created by the iascable build command
- output/ibm-vpcfolder
The folder ibm-vpc is the name we used in our own BOM file. Let us call that folder project folder, which was defined in meta data.
metadata:
  name: ibm-vpc
- output/ibm-vpc/terraformfolder
This is the table which contains the list of files in the terraform folder.
| Filename | Content | 
|---|---|
| output/ibm-vpc/terraform/main.tf | Here you see a number of modules defined including the defined ibm-vpcandibm-vpc-subnetsfrom the BOM file. | 
| output/ibm-vpc/terraform/providers.tf | Simply contains the needed cloud provider information. In that case what we need to specify for IBM Cloud. | 
| output/ibm-vpc/terraform/variables.ft | Contains the specification for the used variable in the main.tfor other Terraform files. | 
| output/ibm-vpc/terraform/version.ft | Contains the specification for the used Terraform provider sources and versions. In that case only IBM is listed. | 
| output/ibm-vpc/terraform/ibm-vpc.auto.tfvars | That file can be used to configure the variable values. (maybe add to .gitignore) During the execution of terraform planandterraform applyyou will be ask for input, if you didn't specify that values. | 
- The output/launch.shfile
That script downloads and starts a container on your local machine. The objective is to ensure that the right environment is used for applying the Terraform configuration.
It attaches the local path to the container as a volume.
Note: Need to ensure you have a container engine on your machine. Best Docker! Because by default is uses Docker. Attach doesn't work for
podmanon macOS.
- The output/ibm-vpc/apply.shfile
That file converts an existing variable.yaml file or variable in the BOM file to a variables.tf and then executes terraform init and terraform apply.
- The output/ibm-vpc/destroy.shfile
That file simply executes the terraform init and terraform destroy -auto-approve commands.
- The output/ibm-vpc/dependencies.dotfile
That file contains the dependencies which can be visualized for example with Graphviz Online.
Example: 
- The output/bom.yamlfile
That file was created by our own BOM file. That file now contains all needed variables. These variables are also reflected in the output/ibm-vpc/terraform/variables.ft file.
Here is the content of the newly created bom.yaml file.
apiVersion: cloudnativetoolkit.dev/v1alpha1
kind: BillOfMaterial
metadata:
  name: ibm-vpc
spec:
  modules:
    - name: ibm-vpc
      alias: ibm-vpc
      version: v1.16.0
    - name: ibm-vpc-subnets
      alias: ibm-vpc-subnets
      version: v1.13.2
    - name: ibm-resource-group
      alias: resource_group
      version: v3.2.16
  variables:
    - name: region
      type: string
      description: The IBM Cloud region where the cluster will be/has been installed.
    - name: ibmcloud_api_key
      type: string
    - name: ibm-vpc-subnets__count
      type: number
      description: The number of subnets that should be provisioned
      defaultValue: 3
    - name: resource_group_name
      type: string
      description: The name of the resource group
Step 6: Execute the terraform init command¶
 Navigate to the output/ibm-vpc/terraform folder and execute the terraform init command.
cd output/ibm-vpc/terraform
terraform init
Step 7: Execute the terraform plan command¶
 Execute the terraform plan command.
terraform plan
Here you can see the interaction:
var.ibmcloud_api_key
  the value of ibmcloud_api_key
  Enter a value: 
Note: You can create an
IBM Cloud API Keywith following command:ibmcloud iam api-key-create iascable-example.
Step 8: Execute the terraform apply¶
 Execute the terraform apply command.
terraform apply -auto-approve
- Input of your variables:
var.ibmcloud_api_key
  the value of ibmcloud_api_key
  Enter a value: xxx
var.region
  The IBM Cloud region where the cluster will be/has been installed.
  Enter a value: us-south 
var.resource_group_name
  The name of the resource group
  Enter a value: default
- Output overview of the resources which will be created:
Terraform used the selected providers to generate the following
execution plan. Resource actions are indicated with the
following symbols:
  + create
 <= read (data resources)
Terraform will perform the following actions:
  # module.ibm-vpc.data.ibm_is_security_group.base will be read during apply
  # (config refers to values not yet known)
 <= data "ibm_is_security_group" "base"  {
      + crn                     = (known after apply)
      + id                      = (known after apply)
      + name                    = "default-vpc-base"
      + resource_controller_url = (known after apply)
      + resource_crn            = (known after apply)
      + resource_group_name     = (known after apply)
      + resource_name           = (known after apply)
      + rules                   = (known after apply)
      + tags                    = (known after apply)
      + vpc                     = (known after apply)
    }
  # module.ibm-vpc.data.ibm_is_vpc.vpc will be read during apply
  # (config refers to values not yet known)
 <= data "ibm_is_vpc" "vpc"  {
      + classic_access              = (known after apply)
      + crn                         = (known after apply)
      + cse_source_addresses        = (known after apply)
      + default_network_acl         = (known after apply)
      + default_network_acl_crn     = (known after apply)
      + default_network_acl_name    = (known after apply)
      + default_routing_table       = (known after apply)
      + default_routing_table_name  = (known after apply)
      + default_security_group      = (known after apply)
      + default_security_group_crn  = (known after apply)
      + default_security_group_name = (known after apply)
      + id                          = (known after apply)
      + name                        = "default-vpc"
      + resource_controller_url     = (known after apply)
      + resource_crn                = (known after apply)
      + resource_group              = (known after apply)
      + resource_group_name         = (known after apply)
      + resource_name               = (known after apply)
      + resource_status             = (known after apply)
      + security_group              = (known after apply)
      + status                      = (known after apply)
      + subnets                     = (known after apply)
      + tags                        = (known after apply)
    }
  # module.ibm-vpc.data.ibm_resource_group.resource_group will be read during apply
  # (config refers to values not yet known)
 <= data "ibm_resource_group" "resource_group"  {
      + account_id          = (known after apply)
      + created_at          = (known after apply)
      + crn                 = (known after apply)
      + id                  = (known after apply)
      + is_default          = (known after apply)
      + name                = "default"
      + payment_methods_url = (known after apply)
      + quota_id            = (known after apply)
      + quota_url           = (known after apply)
      + resource_linkages   = (known after apply)
      + state               = (known after apply)
      + teams_url           = (known after apply)
      + updated_at          = (known after apply)
    }
  # module.ibm-vpc.ibm_is_network_acl_rule.allow_internal_egress[0] will be created
  + resource "ibm_is_network_acl_rule" "allow_internal_egress" {
      + action      = "allow"
      + before      = (known after apply)
      + destination = "10.0.0.0/8"
      + direction   = "outbound"
      + href        = (known after apply)
      + id          = (known after apply)
      + ip_version  = (known after apply)
      + name        = "allow-internal-egress"
      + network_acl = (known after apply)
      + protocol    = (known after apply)
      + rule_id     = (known after apply)
      + source      = "10.0.0.0/8"
    }
  # module.ibm-vpc.ibm_is_network_acl_rule.allow_internal_ingress[0] will be created
  + resource "ibm_is_network_acl_rule" "allow_internal_ingress" {
      + action      = "allow"
      + before      = (known after apply)
      + destination = "10.0.0.0/8"
      + direction   = "inbound"
      + href        = (known after apply)
      + id          = (known after apply)
      + ip_version  = (known after apply)
      + name        = "allow-internal-ingress"
      + network_acl = (known after apply)
      + protocol    = (known after apply)
      + rule_id     = (known after apply)
      + source      = "10.0.0.0/8"
    }
  # module.ibm-vpc.ibm_is_network_acl_rule.deny_external_ingress[0] will be created
  + resource "ibm_is_network_acl_rule" "deny_external_ingress" {
      + action      = "deny"
      + before      = (known after apply)
      + destination = "0.0.0.0/0"
      + direction   = "inbound"
      + href        = (known after apply)
      + id          = (known after apply)
      + ip_version  = (known after apply)
      + name        = "deny-external-ingress"
      + network_acl = (known after apply)
      + protocol    = (known after apply)
      + rule_id     = (known after apply)
      + source      = "0.0.0.0/0"
    }
  # module.ibm-vpc.ibm_is_network_acl_rule.deny_external_rdp[0] will be created
  + resource "ibm_is_network_acl_rule" "deny_external_rdp" {
      + action      = "deny"
      + before      = (known after apply)
      + destination = "0.0.0.0/0"
      + direction   = "inbound"
      + href        = (known after apply)
      + id          = (known after apply)
      + ip_version  = (known after apply)
      + name        = "deny-external-rdp"
      + network_acl = (known after apply)
      + protocol    = (known after apply)
      + rule_id     = (known after apply)
      + source      = "0.0.0.0/0"
      + tcp {
          + port_max        = 3389
          + port_min        = 3389
          + source_port_max = 3389
          + source_port_min = 3389
        }
    }
  # module.ibm-vpc.ibm_is_network_acl_rule.deny_external_ssh[0] will be created
  + resource "ibm_is_network_acl_rule" "deny_external_ssh" {
      + action      = "deny"
      + before      = (known after apply)
      + destination = "0.0.0.0/0"
      + direction   = "inbound"
      + href        = (known after apply)
      + id          = (known after apply)
      + ip_version  = (known after apply)
      + name        = "deny-external-ssh"
      + network_acl = (known after apply)
      + protocol    = (known after apply)
      + rule_id     = (known after apply)
      + source      = "0.0.0.0/0"
      + tcp {
          + port_max        = 22
          + port_min        = 22
          + source_port_max = 22
          + source_port_min = 22
        }
    }
  # module.ibm-vpc.ibm_is_security_group.base[0] will be created
  + resource "ibm_is_security_group" "base" {
      + crn                     = (known after apply)
      + id                      = (known after apply)
      + name                    = "default-vpc-base"
      + resource_controller_url = (known after apply)
      + resource_crn            = (known after apply)
      + resource_group          = (known after apply)
      + resource_group_name     = (known after apply)
      + resource_name           = (known after apply)
      + rules                   = (known after apply)
      + tags                    = (known after apply)
      + vpc                     = (known after apply)
    }
  # module.ibm-vpc.ibm_is_security_group_rule.cse_dns_1[0] will be created
  + resource "ibm_is_security_group_rule" "cse_dns_1" {
      + direction   = "outbound"
      + group       = (known after apply)
      + id          = (known after apply)
      + ip_version  = "ipv4"
      + protocol    = (known after apply)
      + related_crn = (known after apply)
      + remote      = "161.26.0.10"
      + rule_id     = (known after apply)
      + udp {
          + port_max = 53
          + port_min = 53
        }
    }
  # module.ibm-vpc.ibm_is_security_group_rule.cse_dns_1[1] will be created
  + resource "ibm_is_security_group_rule" "cse_dns_1" {
      + direction   = "outbound"
      + group       = (known after apply)
      + id          = (known after apply)
      + ip_version  = "ipv4"
      + protocol    = (known after apply)
      + related_crn = (known after apply)
      + remote      = "161.26.0.10"
      + rule_id     = (known after apply)
      + udp {
          + port_max = 53
          + port_min = 53
        }
    }
  # module.ibm-vpc.ibm_is_security_group_rule.cse_dns_2[0] will be created
  + resource "ibm_is_security_group_rule" "cse_dns_2" {
      + direction   = "outbound"
      + group       = (known after apply)
      + id          = (known after apply)
      + ip_version  = "ipv4"
      + protocol    = (known after apply)
      + related_crn = (known after apply)
      + remote      = "161.26.0.11"
      + rule_id     = (known after apply)
      + udp {
          + port_max = 53
          + port_min = 53
        }
    }
  # module.ibm-vpc.ibm_is_security_group_rule.cse_dns_2[1] will be created
  + resource "ibm_is_security_group_rule" "cse_dns_2" {
      + direction   = "outbound"
      + group       = (known after apply)
      + id          = (known after apply)
      + ip_version  = "ipv4"
      + protocol    = (known after apply)
      + related_crn = (known after apply)
      + remote      = "161.26.0.11"
      + rule_id     = (known after apply)
      + udp {
          + port_max = 53
          + port_min = 53
        }
    }
  # module.ibm-vpc.ibm_is_security_group_rule.default_inbound_http[0] will be created
  + resource "ibm_is_security_group_rule" "default_inbound_http" {
      + direction   = "inbound"
      + group       = (known after apply)
      + id          = (known after apply)
      + ip_version  = "ipv4"
      + protocol    = (known after apply)
      + related_crn = (known after apply)
      + remote      = "0.0.0.0/0"
      + rule_id     = (known after apply)
      + tcp {
          + port_max = 80
          + port_min = 80
        }
    }
  # module.ibm-vpc.ibm_is_security_group_rule.default_inbound_ping[0] will be created
  + resource "ibm_is_security_group_rule" "default_inbound_ping" {
      + direction   = "inbound"
      + group       = (known after apply)
      + id          = (known after apply)
      + ip_version  = "ipv4"
      + protocol    = (known after apply)
      + related_crn = (known after apply)
      + remote      = "0.0.0.0/0"
      + rule_id     = (known after apply)
      + icmp {
          + type = 8
        }
    }
  # module.ibm-vpc.ibm_is_security_group_rule.private_dns_1[0] will be created
  + resource "ibm_is_security_group_rule" "private_dns_1" {
      + direction   = "outbound"
      + group       = (known after apply)
      + id          = (known after apply)
      + ip_version  = "ipv4"
      + protocol    = (known after apply)
      + related_crn = (known after apply)
      + remote      = "161.26.0.7"
      + rule_id     = (known after apply)
      + udp {
          + port_max = 53
          + port_min = 53
        }
    }
  # module.ibm-vpc.ibm_is_security_group_rule.private_dns_1[1] will be created
  + resource "ibm_is_security_group_rule" "private_dns_1" {
      + direction   = "outbound"
      + group       = (known after apply)
      + id          = (known after apply)
      + ip_version  = "ipv4"
      + protocol    = (known after apply)
      + related_crn = (known after apply)
      + remote      = "161.26.0.7"
      + rule_id     = (known after apply)
      + udp {
          + port_max = 53
          + port_min = 53
        }
    }
  # module.ibm-vpc.ibm_is_security_group_rule.private_dns_2[0] will be created
  + resource "ibm_is_security_group_rule" "private_dns_2" {
      + direction   = "outbound"
      + group       = (known after apply)
      + id          = (known after apply)
      + ip_version  = "ipv4"
      + protocol    = (known after apply)
      + related_crn = (known after apply)
      + remote      = "161.26.0.8"
      + rule_id     = (known after apply)
      + udp {
          + port_max = 53
          + port_min = 53
        }
    }
  # module.ibm-vpc.ibm_is_security_group_rule.private_dns_2[1] will be created
  + resource "ibm_is_security_group_rule" "private_dns_2" {
      + direction   = "outbound"
      + group       = (known after apply)
      + id          = (known after apply)
      + ip_version  = "ipv4"
      + protocol    = (known after apply)
      + related_crn = (known after apply)
      + remote      = "161.26.0.8"
      + rule_id     = (known after apply)
      + udp {
          + port_max = 53
          + port_min = 53
        }
    }
  # module.ibm-vpc.ibm_is_vpc.vpc[0] will be created
  + resource "ibm_is_vpc" "vpc" {
      + address_prefix_management   = "auto"
      + classic_access              = false
      + crn                         = (known after apply)
      + cse_source_addresses        = (known after apply)
      + default_network_acl         = (known after apply)
      + default_network_acl_crn     = (known after apply)
      + default_network_acl_name    = "default-vpc-default"
      + default_routing_table       = (known after apply)
      + default_routing_table_name  = "default-vpc-default"
      + default_security_group      = (known after apply)
      + default_security_group_crn  = (known after apply)
      + default_security_group_name = "default-vpc-default"
      + id                          = (known after apply)
      + name                        = "default-vpc"
      + resource_controller_url     = (known after apply)
      + resource_crn                = (known after apply)
      + resource_group              = (known after apply)
      + resource_group_name         = (known after apply)
      + resource_name               = (known after apply)
      + resource_status             = (known after apply)
      + security_group              = (known after apply)
      + status                      = (known after apply)
      + subnets                     = (known after apply)
      + tags                        = (known after apply)
    }
  # module.ibm-vpc.ibm_resource_tag.nacl-tag[0] will be created
  + resource "ibm_resource_tag" "nacl-tag" {
      + acccount_id = (known after apply)
      + id          = (known after apply)
      + resource_id = (known after apply)
      + tag_type    = (known after apply)
      + tags        = (known after apply)
    }
  # module.ibm-vpc.ibm_resource_tag.sg-tag[0] will be created
  + resource "ibm_resource_tag" "sg-tag" {
      + acccount_id = (known after apply)
      + id          = (known after apply)
      + resource_id = (known after apply)
      + tag_type    = (known after apply)
      + tags        = (known after apply)
    }
  # module.ibm-vpc.null_resource.print_names will be created
  + resource "null_resource" "print_names" {
      + id = (known after apply)
    }
  # module.ibm-vpc-subnets.data.ibm_is_vpc.vpc will be read during apply
  # (config refers to values not yet known)
 <= data "ibm_is_vpc" "vpc"  {
      + classic_access              = (known after apply)
      + crn                         = (known after apply)
      + cse_source_addresses        = (known after apply)
      + default_network_acl         = (known after apply)
      + default_network_acl_crn     = (known after apply)
      + default_network_acl_name    = (known after apply)
      + default_routing_table       = (known after apply)
      + default_routing_table_name  = (known after apply)
      + default_security_group      = (known after apply)
      + default_security_group_crn  = (known after apply)
      + default_security_group_name = (known after apply)
      + id                          = (known after apply)
      + name                        = "default-vpc"
      + resource_controller_url     = (known after apply)
      + resource_crn                = (known after apply)
      + resource_group              = (known after apply)
      + resource_group_name         = (known after apply)
      + resource_name               = (known after apply)
      + resource_status             = (known after apply)
      + security_group              = (known after apply)
      + status                      = (known after apply)
      + subnets                     = (known after apply)
      + tags                        = (known after apply)
    }
  # module.ibm-vpc-subnets.data.ibm_resource_group.resource_group will be read during apply
  # (config refers to values not yet known)
 <= data "ibm_resource_group" "resource_group"  {
      + account_id          = (known after apply)
      + created_at          = (known after apply)
      + crn                 = (known after apply)
      + id                  = (known after apply)
      + is_default          = (known after apply)
      + name                = "default"
      + payment_methods_url = (known after apply)
      + quota_id            = (known after apply)
      + quota_url           = (known after apply)
      + resource_linkages   = (known after apply)
      + state               = (known after apply)
      + teams_url           = (known after apply)
      + updated_at          = (known after apply)
    }
  # module.ibm-vpc-subnets.ibm_is_network_acl.subnet_acl[0] will be created
  + resource "ibm_is_network_acl" "subnet_acl" {
      + crn                     = (known after apply)
      + id                      = (known after apply)
      + name                    = "default-vpc-subnet-default"
      + resource_controller_url = (known after apply)
      + resource_crn            = (known after apply)
      + resource_group          = (known after apply)
      + resource_group_name     = (known after apply)
      + resource_name           = (known after apply)
      + tags                    = (known after apply)
      + vpc                     = (known after apply)
      + rules {
          + action      = (known after apply)
          + destination = (known after apply)
          + direction   = (known after apply)
          + id          = (known after apply)
          + ip_version  = (known after apply)
          + name        = (known after apply)
          + source      = (known after apply)
          + subnets     = (known after apply)
          + icmp {
              + code = (known after apply)
              + type = (known after apply)
            }
          + tcp {
              + port_max        = (known after apply)
              + port_min        = (known after apply)
              + source_port_max = (known after apply)
              + source_port_min = (known after apply)
            }
          + udp {
              + port_max        = (known after apply)
              + port_min        = (known after apply)
              + source_port_max = (known after apply)
              + source_port_min = (known after apply)
            }
        }
    }
  # module.ibm-vpc-subnets.ibm_is_network_acl_rule.acl_rule[0] will be created
  + resource "ibm_is_network_acl_rule" "acl_rule" {
      + action      = "allow"
      + before      = (known after apply)
      + destination = "10.0.0.0/8"
      + direction   = "inbound"
      + href        = (known after apply)
      + id          = (known after apply)
      + ip_version  = (known after apply)
      + name        = "default-vpc-subnet-default-allow-ingress-internal"
      + network_acl = (known after apply)
      + protocol    = (known after apply)
      + rule_id     = (known after apply)
      + source      = "10.0.0.0/8"
    }
  # module.ibm-vpc-subnets.ibm_is_network_acl_rule.acl_rule[1] will be created
  + resource "ibm_is_network_acl_rule" "acl_rule" {
      + action      = "allow"
      + before      = (known after apply)
      + destination = "10.0.0.0/8"
      + direction   = "inbound"
      + href        = (known after apply)
      + id          = (known after apply)
      + ip_version  = (known after apply)
      + name        = "default-vpc-subnet-default-allow-roks-ingress"
      + network_acl = (known after apply)
      + protocol    = (known after apply)
      + rule_id     = (known after apply)
      + source      = "166.8.0.0/14"
    }
  # module.ibm-vpc-subnets.ibm_is_network_acl_rule.acl_rule[2] will be created
  + resource "ibm_is_network_acl_rule" "acl_rule" {
      + action      = "allow"
      + before      = (known after apply)
      + destination = "10.0.0.0/8"
      + direction   = "inbound"
      + href        = (known after apply)
      + id          = (known after apply)
      + ip_version  = (known after apply)
      + name        = "default-vpc-subnet-default-allow-vse-ingress"
      + network_acl = (known after apply)
      + protocol    = (known after apply)
      + rule_id     = (known after apply)
      + source      = "161.26.0.0/16"
    }
  # module.ibm-vpc-subnets.ibm_is_network_acl_rule.acl_rule[3] will be created
  + resource "ibm_is_network_acl_rule" "acl_rule" {
      + action      = "allow"
      + before      = (known after apply)
      + destination = "10.0.0.0/8"
      + direction   = "outbound"
      + href        = (known after apply)
      + id          = (known after apply)
      + ip_version  = (known after apply)
      + name        = "default-vpc-subnet-default-allow-egress-internal"
      + network_acl = (known after apply)
      + protocol    = (known after apply)
      + rule_id     = (known after apply)
      + source      = "10.0.0.0/8"
    }
  # module.ibm-vpc-subnets.ibm_is_network_acl_rule.acl_rule[4] will be created
  + resource "ibm_is_network_acl_rule" "acl_rule" {
      + action      = "allow"
      + before      = (known after apply)
      + destination = "166.8.0.0/14"
      + direction   = "outbound"
      + href        = (known after apply)
      + id          = (known after apply)
      + ip_version  = (known after apply)
      + name        = "default-vpc-subnet-default-allow-roks-egress"
      + network_acl = (known after apply)
      + protocol    = (known after apply)
      + rule_id     = (known after apply)
      + source      = "10.0.0.0/8"
    }
  # module.ibm-vpc-subnets.ibm_is_network_acl_rule.acl_rule[5] will be created
  + resource "ibm_is_network_acl_rule" "acl_rule" {
      + action      = "allow"
      + before      = (known after apply)
      + destination = "161.26.0.0/16"
      + direction   = "outbound"
      + href        = (known after apply)
      + id          = (known after apply)
      + ip_version  = (known after apply)
      + name        = "default-vpc-subnet-default-allow-vse-egress"
      + network_acl = (known after apply)
      + protocol    = (known after apply)
      + rule_id     = (known after apply)
      + source      = "10.0.0.0/8"
    }
  # module.ibm-vpc-subnets.ibm_is_subnet.vpc_subnets[0] will be created
  + resource "ibm_is_subnet" "vpc_subnets" {
      + access_tags                  = (known after apply)
      + available_ipv4_address_count = (known after apply)
      + crn                          = (known after apply)
      + id                           = (known after apply)
      + ip_version                   = "ipv4"
      + ipv4_cidr_block              = (known after apply)
      + name                         = "default-vpc-subnet-default01"
      + network_acl                  = (known after apply)
      + public_gateway               = (known after apply)
      + resource_controller_url      = (known after apply)
      + resource_crn                 = (known after apply)
      + resource_group               = (known after apply)
      + resource_group_name          = (known after apply)
      + resource_name                = (known after apply)
      + resource_status              = (known after apply)
      + routing_table                = (known after apply)
      + status                       = (known after apply)
      + tags                         = (known after apply)
      + total_ipv4_address_count     = 256
      + vpc                          = (known after apply)
      + zone                         = "us-south-1"
    }
  # module.ibm-vpc-subnets.ibm_is_subnet.vpc_subnets[1] will be created
  + resource "ibm_is_subnet" "vpc_subnets" {
      + access_tags                  = (known after apply)
      + available_ipv4_address_count = (known after apply)
      + crn                          = (known after apply)
      + id                           = (known after apply)
      + ip_version                   = "ipv4"
      + ipv4_cidr_block              = (known after apply)
      + name                         = "default-vpc-subnet-default02"
      + network_acl                  = (known after apply)
      + public_gateway               = (known after apply)
      + resource_controller_url      = (known after apply)
      + resource_crn                 = (known after apply)
      + resource_group               = (known after apply)
      + resource_group_name          = (known after apply)
      + resource_name                = (known after apply)
      + resource_status              = (known after apply)
      + routing_table                = (known after apply)
      + status                       = (known after apply)
      + tags                         = (known after apply)
      + total_ipv4_address_count     = 256
      + vpc                          = (known after apply)
      + zone                         = "us-south-2"
    }
  # module.ibm-vpc-subnets.ibm_is_subnet.vpc_subnets[2] will be created
  + resource "ibm_is_subnet" "vpc_subnets" {
      + access_tags                  = (known after apply)
      + available_ipv4_address_count = (known after apply)
      + crn                          = (known after apply)
      + id                           = (known after apply)
      + ip_version                   = "ipv4"
      + ipv4_cidr_block              = (known after apply)
      + name                         = "default-vpc-subnet-default03"
      + network_acl                  = (known after apply)
      + public_gateway               = (known after apply)
      + resource_controller_url      = (known after apply)
      + resource_crn                 = (known after apply)
      + resource_group               = (known after apply)
      + resource_group_name          = (known after apply)
      + resource_name                = (known after apply)
      + resource_status              = (known after apply)
      + routing_table                = (known after apply)
      + status                       = (known after apply)
      + tags                         = (known after apply)
      + total_ipv4_address_count     = 256
      + vpc                          = (known after apply)
      + zone                         = "us-south-3"
    }
  # module.ibm-vpc-subnets.null_resource.print_names will be created
  + resource "null_resource" "print_names" {
      + id = (known after apply)
    }
  # module.resource_group.data.ibm_resource_group.resource_group will be read during apply
  # (config refers to values not yet known)
 <= data "ibm_resource_group" "resource_group"  {
      + account_id          = (known after apply)
      + created_at          = (known after apply)
      + crn                 = (known after apply)
      + id                  = (known after apply)
      + is_default          = (known after apply)
      + name                = "default"
      + payment_methods_url = (known after apply)
      + quota_id            = (known after apply)
      + quota_url           = (known after apply)
      + resource_linkages   = (known after apply)
      + state               = (known after apply)
      + teams_url           = (known after apply)
      + updated_at          = (known after apply)
    }
  # module.resource_group.data.ibm_resource_tag.resource_group_tags will be read during apply
  # (config refers to values not yet known)
 <= data "ibm_resource_tag" "resource_group_tags"  {
      + id          = (known after apply)
      + resource_id = (known after apply)
      + tags        = (known after apply)
    }
  # module.resource_group.null_resource.resource_group will be created
  + resource "null_resource" "resource_group" {
      + id       = (known after apply)
      + triggers = (known after apply)
    }
  # module.resource_group.null_resource.wait_for_sync will be created
  + resource "null_resource" "wait_for_sync" {
      + id = (known after apply)
    }
  # module.resource_group.random_uuid.tag will be created
  + resource "random_uuid" "tag" {
      + id     = (known after apply)
      + result = (known after apply)
    }
  # module.resource_group.module.clis.data.external.setup-binaries will be read during apply
  # (config refers to values not yet known)
 <= data "external" "setup-binaries"  {
      + id      = (known after apply)
      + program = [
          + "bash",
          + ".terraform/modules/resource_group.clis/scripts/setup-binaries.sh",
        ]
      + query   = {
          + "bin_dir" = "/Users/thomassuedbroecker/Downloads/dev/iascable-starting-point/examples/output/ibm-vpc/terraform/bin2"
          + "clis"    = "yq,jq,igc"
          + "uuid"    = (known after apply)
        }
      + result  = (known after apply)
    }
  # module.resource_group.module.clis.null_resource.print will be created
  + resource "null_resource" "print" {
      + id = (known after apply)
    }
  # module.resource_group.module.clis.random_string.uuid will be created
  + resource "random_string" "uuid" {
      + id          = (known after apply)
      + length      = 16
      + lower       = true
      + min_lower   = 0
      + min_numeric = 0
      + min_special = 0
      + min_upper   = 0
      + number      = false
      + numeric     = (known after apply)
      + result      = (known after apply)
      + special     = false
      + upper       = false
    }
Plan: 36 to add, 0 to change, 0 to destroy.
╷
│ Warning: Experimental feature "module_variable_optional_attrs" is active
│ 
│   on .terraform/modules/ibm-vpc-subnets/version.tf line 10, in terraform:
│   10:   experiments = [module_variable_optional_attrs]
│ 
│ Experimental features are subject to breaking changes in
│ future minor or patch releases, based on feedback.
│ 
│ If you have feedback on the design of this feature, please
│ open a GitHub issue to discuss it.
╵
╷
│ Warning: Argument is deprecated
│ 
│   with module.resource_group.module.clis.random_string.uuid,
│   on .terraform/modules/resource_group.clis/main.tf line 15, in resource "random_string" "uuid":
│   15:   number  = false
│ 
│ Use numeric instead.
│ 
│ (and one more similar warning elsewhere)
Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.
  Enter a value: yes
- Final result of the creation
Apply complete! Resources: 36 added, 0 changed, 0 destroyed.
Step 9: Execute the terraform destroy command¶
 Note: Ensure you didn't delete the
terraform.tfstateand the.terraform.lock.hclfiles before.
To destroy the provisioned resources, run the following:
terraform destroy -auto-approve
You need to ensure to provide the IBM Cloud API Key, the region and the resource group name.
var.ibmcloud_api_key
  the value of ibmcloud_api_key
  Enter a value: xxxx
var.region
  The IBM Cloud region where the cluster will be/has been installed.
  Enter a value: us-south
var.resource_group_name
  The name of the resource group
  Enter a value: default
- Output overview:
╷
│ Warning: Experimental feature "module_variable_optional_attrs" is active
│ 
│   on .terraform/modules/ibm-vpc-subnets/version.tf line 10, in terraform:
│   10:   experiments = [module_variable_optional_attrs]
│ 
│ Experimental features are subject to breaking changes in
│ future minor or patch releases, based on feedback.
│ 
│ If you have feedback on the design of this feature, please
│ open a GitHub issue to discuss it.
╵
╷
│ Warning: Argument is deprecated
│ 
│   with module.resource_group.module.clis.random_string.uuid,
│   on .terraform/modules/resource_group.clis/main.tf line 15, in resource "random_string" "uuid":
│   15:   number  = false
│ 
│ Use numeric instead.
│ 
│ (and one more similar warning elsewhere)
╵
Destroy complete! Resources: 36 destroyed.
4. Summary¶
The IasCable and the Modules (from the TechZone Accelerator Toolkit) are all from the Cloud Native Toolkit providing a good concept for a framework. This helps to provide reusable components to install and configure cloud infrastructure. What you have learned so far is just helping you to get started, there is more to learn.