GithubHelp home page GithubHelp logo

cloud-native-toolkit / iascable Goto Github PK

View Code? Open in Web Editor NEW
13.0 5.0 8.0 2.27 MB

IasCable is a node/typescript library to build installable component infrastructure components from a catalog of available modules

License: MIT License

TypeScript 94.97% JavaScript 0.61% Shell 1.04% Liquid 3.38%

iascable's Introduction

IasCable

Library and CLI used to generate Infrastructure as Code installable components composed of available modules from a catalog.

CLI Usage

Installation (non-M1 Macbook)

To install the latest version of iascable into /usr/local/bin, run the following:

curl -sL https://iascable.cloudnativetoolkit.dev/install.sh | sh

If you would like to install a different version of the CLI and/or put it in a different directory, use the following:

curl -sL https://iascable.cloudnativetoolkit.dev/install.sh | RELEASE=2.15.1 DEST_DIR=~/bin sh

Installation on M1 Macbook

The M1 Macbook version will install the AMD64 binary and requires Rosetta to be installed. If you do not have Rosetta installed, see this link.

To install the latest version of iascable into /usr/local/bin, as above for non-M1 Macbooks, however add a sudo to write to /usr/local/bin as follows:

curl -sL https://iascable.cloudnativetoolkit.dev/install.sh | sudo sh

If you would like to install a different version of the CLI and/or put it in a different directory, use the following:

curl -sL https://iascable.cloudnativetoolkit.dev/install.sh | RELEASE=2.15.1 DEST_DIR=~/bin sh

Note that the install script creates a new binary for the downloaded version and creates a symbolic link to it. Over time, you may build up multiple versions in your destination directory which may need to be manually removed if not required. This also allows for using a prior version by updating the symbolic link to point to a different version as follows:

sudo ln -s /usr/local/bin/iascable-2.25.5 /usr/local/bin/iascable

Install beta version

If you would like to install the latest beta release of the cli, use the following:

curl -sL https://iascable.cloudnativetoolkit.dev/install.sh | RELEASE=beta sh

If you would like to put the beta version of the cli in another directory you can provide a value for the DEST_DIR argument.

Commands

To build a Terraform template from a Bill of Materials or Solution Bill of Materials, run the following command:

iascable build [-c {CATALOG_URL}] [-c {CATALOG_URL}] -i {BOM_INPUT} [-i {BOM_INPUT}] [-o {OUTPUT_DIR}]

where:

  • CATALOG_URL is the url of the module catalog. The default module catalog is https://modules.cloudnativetoolkit.dev/index.yaml. Multiple module catalogs can be provided. The catalogs are combined, with the last one taking precedence in the case of duplicate modules.
  • BOM_INPUT is the input file containing the Bill of Material or Solution Bill of Material definition. Multiple bom files can be provided at the same time.
  • OUTPUT_DIR is the directory where the output terraform template will be generated.

Library usage

The Iascable cli can be added to any npm application using the normal npm install process:

npm install --save iascable

Install beta

If you want to install the beta release of the cli, include the dist-tag with the package name. E.g.:

npm install --save iascable@beta

Getting started

First Bill of Materials

  1. Copy the following yaml into a file named firstbom.yaml
apiVersion: cloudnativetoolkit.dev/v1alpha1
kind: BillOfMaterial
metadata:
  name: ibm-vpc
spec:
  modules:
    - name: ibm-vpc
    - name: ibm-vpc-subnets
  1. Generate the terraform with:
iascable build -i firstbom.yaml
  1. The command will look up the modules from the catalog and generate the output in a folder named output/ibm-vpc/terraform. Take a look at the main.tf. You will see a number of modules defined there. Some of the variables in the ibm-vpc-subnets module will come from the output of the ibm-vpc module.
  2. Look at the ibm-roks.auto.tfvars file. This file will contain a listing of the variables that must be provided. They can either be provided in the ibm-roks.auto.tfvars file or the terraform cli will prompt for them when terraform plan or terraform apply are run.
  3. If you have an IBM Cloud account, you can provision the VPC and Subnets by running the following:
terraform init
terraform apply -auto-approve
  1. To destroy the provisioned resources, run the following:
terraform destroy -auto-approve

Provide configuration for the VPCs

One of the common values that will be configured in the VPCs and Subnets are the network IP addresses or CIDR blocks that will be used by the VPC network. We can configure those values in the BOM.

  1. Copy the following yaml into a file named secondbom.yaml
apiVersion: cloudnativetoolkit.dev/v1alpha1
kind: BillOfMaterial
metadata:
  name: ibm-vpc2
spec:
  modules:
    - name: ibm-vpc
      variables:
        - name: address_prefix_count
          value: 3
        - name: address_prefixes
          value:
            - 10.1.0.0/18
            - 10.2.0.0/18
            - 10.3.0.0/18
    - name: ibm-vpc-subnets
      variables:
        - name: _count
          value: 3
        - name: ipv4_cidr_blocks
          value:
            - 10.1.10.0/24
            - 10.2.10.0/24
            - 10.3.10.0/24
  1. Generate the terraform with:
iascable build -i secondbom.yaml
  1. The generated output will be in a folder named output/ibm-vpc2/terraform. The main.tf file will look the same. However, you will see that the variables.tf file has different values for the address_prefixes and ipv4_cidr_blocks variables.

  2. If you have an IBM Cloud account, you can provision the VPC and Subnets by running the following:

terraform init
terraform apply -auto-approve
  1. To destroy the provisioned resources, run the following:
terraform destroy -auto-approve

IBM ROKS Bill of Materials

The following BOM will provision a VPC, VPC Subnet set, VPC Gateways, and a Red Hat OpenShift cluster.

apiVersion: cloudnativetoolkit.dev/v1alpha1
kind: BillOfMaterial
metadata:
  name: ibm-roks
spec:
  modules:
    - name: ibm-vpc
    - name: ibm-vpc-subnets
    - name: ibm-vpc-gateways
    - name: ibm-ocp-vpc
      variables:
        - name: worker_count
          value: 1

Bill of Material structure

The Bill Of Materials (BOM) yaml has been modeled after a Kubernetes Custom Resource Definition. It is used to define the modules from the module catalog that should be included in the generated terraform template. As appropriate the Bill of Materials can also be used to define the relationships between the modules and the default variables that should be supplied to the modules for the architecture.

The terraform template is generated from the BOM using the iascable build command. The build process relies on metadata for each of the modules stored in the module catalog to understand each module's dependencies and the relationships between the different modules. By default, the module entries for the Bill of Material are pulled from the Cloud Native Toolkit module catalog - https://modules.cloudnativetoolkit.dev/

BOM metadata

The first part of the BOM defines the name and other descriptive information about the terraform that will be generated.

apiVersion: cloudnativetoolkit.dev/v1alpha1
kind: BillOfMaterial
metadata:
  name: 100-shared-services
  labels:
    platform: ibm
    code: '100'
  annotations:
    displayName: Shared Services
    description: Provisions a set of shared services in the IBM Cloud account

Note: The labels and annotations sections can contain any number of values. The common values are shown in the example.

Field Description
apiVersion the schema version of the BOM (always cloudnativetoolkit.dev/v1alpha1 at the moment)
kind the kind of resource (always BillOfMaterial for a BOM)
name the name of the architecture that will be built
platform label the cloud platform targeted by the architecture
code label the code used to index the BOM
displayName annotation the user-friendly display name for the BOM
description annotation the description of the provisioned architecture
path annotation the sub-path that should be appended to the output (e.g. {output}/{path}/{name}
catalogUrls annotation comma-separated list of urls for the catalogs containing the BOM modules
deployment-type/gitops annotation flag indicating the BOM describes gitops modules
vpn/required annotation flag indicating a VPN connection is required before applying the terraform

BOM spec

The meat of the BOM is defined in the spec block. The spec can contain the following top level elements:

  • modules - an array of Bill of Material module definitions
  • variables - (optional) an array of Bill of Material variables used to define the global variables in the terraform template
  • providers - (optional) an array of terraform provider configurations

BOM module definition

A BOM module is used to define a module that should be added to the generated terraform template. At a minimum, the BOM Module must define name of the module from the module catalog. Optionally, the module can also define an alias that will be used for the module identifier in the generated terraform and will also be used as the identifier when defining dependencies between modules.

BOM Module dependencies

If the module depends on other modules, the relationships can be defined in the dependencies block. However, in most cases it is not necessary to explicitly define the dependencies. Through the module metadata, the iascable tool knows the required dependencies for each module and can "auto-wire" the modules together. If necessary, iascable will automatically add modules to the BOM if they are required to satisfy a required module dependency.

If there are multiple instances of a dependent module defined in the BOM then iascable will "auto-wire" the dependency to the "default" dependent module. The "default" dependent module is the one that uses the default alias name OR has the default: true attribute added to it. If a default cannot be identified then ANOTHER instance of the module will be automatically added to the BOM. If this behavior is not desired then the desired dependent module can be referenced in the dependencies block.

For example:

spec:
  modules:
  - name: ibm-vpc
  - name: ibm-vpc-subnets
    alias: edge_subnets
  - name: ibm-vpc-subnets
    alias: cluster_subnets
  - name: ibm-vpc-subnets
    alias: vpe_subnets
  - name: ibm-vpc-ocp

The ibm-vpc-subnets module depends on ibm-vpc. An explicit declaration of the dependency is not required here though because the ibm-vpc module is the default instance and all of the ibm-vpc-subnets are auto-wired to that instance. (In fact the ibm-vpc module doesn't even need to be explictly listed in the BOM in this case, but it is added for completeness.) The ibm-vpc-ocp module depends on ibm-vpc-subnets to identify where the cluster should be deployed. In this configuration, a default ibm-vpc-subnets instance has not been defined. As a result, iascable will automatically pull in 4th ibm-vpc-subnets instance to satisfy the dependency. This is probably not the desired result and we will want to explicitly define the dependency in the BOM. The updated BOM would look like the following:

spec:
  modules:
  - name: ibm-vpc
  - name: ibm-vpc-subnets
    alias: edge_subnets
  - name: ibm-vpc-subnets
    alias: cluster_subnets
  - name: ibm-vpc-subnets
    alias: vpe_subnets
  - name: ibm-vpc-ocp
    dependencies:
      - id: subnets
        ref: cluster_subnets

The subnets identifier in the dependencies array refers to the dependency identifier in the module metadata for the ibm-vpc-ocp module. The clsuter_subnets value refers to the alias of the target ibm-vpc-subnets module instance.

Note: The only exception to iascable automatically pulling dependent modules into the BOM is if there are multiple module options that satisfy the dependency. In this case one of the modules that satisfies dependency must be explicitly added to the BOM. Otherwise the iasable build command will give an error that the dependency cannot be resolved.

BOM Module variables

The Bill of Materials also allows the module variables to be configured in a variables block. The variables block is an array of variable definitions. At a minimum the variable name must be provided. The available variable names are defined in the module metadata. For each variable, the following values can be provided:

Field Description
value The default value of the variable. This value will override the default in the module.
scope The scope of the variable that defines how the variable will be handled in the global variable namespace. Allowed values are global or module. If the value is global the variable will be added as-is to the global namespace. If the value is module then the variable name will be prefixed with the module alias (e.g. the flavor variable in the cluster module would be named cluster_flavor with module scope and flavor with global scope).
alias The alias name that should be given to the variable in the global variable namespace. This alias works in conjunction with the scope value. For example, if the name variable is set to global scope and alias of my_name then a variable named my_name will be added to the global variable namespace and the generated module terraform will map the my_name global variable to the name module variable (name = var.my_name)
important Flag that indicates the variable should be presented to the user in the generated *.auto.tfvars file even though it has a default value. By default, only required fields (i.e. fields that don't have a default value) are presented to the user. Selectively, other variables can be exposed using this flag for significant configuration values. The objective is to balance flexibility of configuration options with the simplicity of a small number of required inputs

Note: The module metadata defines how the outputs from the dependent modules should be wired into a module's input variables. It is not necessary to define any of the "wired" variables in the BOM.

Example Bill of Material

apiVersion: cloudnativetoolkit.dev/v1alpha1
kind: BillOfMaterial
metadata:
  name: 130-management-vpc-openshift
  labels:
    type: infrastructure
    platform: ibm
    code: '130'
  annotations:
    displayName: Management VPC OpenShift
    description: Management VPC and Red Hat OpenShift servers
spec:
  modules:
    - name: ibm-resource-group
      alias: kms_resource_group
      variables:
        - name: provision
          value: false
    - name: ibm-resource-group
      alias: at_resource_group
      variables:
        - name: provision
          value: false
    - name: ibm-kms
      alias: kms
      variables:
        - name: provision
          value: false
        - name: region
          alias: kms_region
        - name: name_prefix
          alias: kms_name_prefix
          scope: global
          value: ""
      dependencies:
        - name: resource_group
          ref: kms_resource_group
    - name: ibm-resource-group
      variables:
        - name: resource_group_name
          alias: mgmt_resource_group_name
          scope: global
        - name: provision
          alias: mgmt_resource_group_provision
          scope: global
    - name: ibm-access-group
    - name: ibm-vpc
      variables:
        - name: address_prefix_count
          value: 3
        - name: address_prefixes
          value:
            - 10.10.0.0/18
            - 10.20.0.0/18
            - 10.30.0.0/18
    - name: ibm-flow-logs
      dependencies:
        - name: target
          ref: ibm-vpc
        - name: cos_bucket
          ref: flow_log_bucket
    - name: ibm-vpc-gateways
    - name: ibm-vpc-subnets
      alias: worker-subnets
      variables:
        - name: _count
          alias: mgmt_worker_subnet_count
          scope: global
          value: 3
        - name: label
          value: worker
        - name: ipv4_cidr_blocks
          value:
            - 10.10.10.0/24
            - 10.20.10.0/24
            - 10.30.10.0/24
      dependencies:
        - name: gateways
          ref: ibm-vpc-gateways
    - name: ibm-ocp-vpc
      alias: cluster
      variables:
        - name: disable_public_endpoint
          value: true
        - name: kms_enabled
          value: true
        - name: worker_count
          alias: mgmt_worker_count
        - name: ocp_version
          value: 4.8
      dependencies:
        - name: subnets
          ref: worker-subnets
        - name: kms_key
          ref: kms_key
    - name: ibm-vpc-subnets
      alias: vpe-subnets
      variables:
        - name: _count
          value: 3
        - name: label
          value: vpe
        - name: ipv4_cidr_blocks
          value:
            - 10.10.20.0/24
            - 10.20.20.0/24
            - 10.30.20.0/24
    - name: ibm-vpc-subnets
      alias: ingress-subnets
      variables:
        - name: _count
          value: 3
        - name: label
          value: ingress
        - name: ipv4_cidr_blocks
          value:
            - 10.10.30.0/24
            - 10.20.30.0/24
            - 10.30.30.0/24
    - name: ibm-vpc-vpn-gateway
      dependencies:
        - name: subnets
          ref: vpn-subnets
    - name: ibm-resource-group
      alias: cs_resource_group
      variables:
        - name: provision
          value: false
    - name: ibm-object-storage
      alias: cos
      variables:
        - name: provision
          value: false
        - name: name_prefix
          alias: cs_name_prefix
          scope: global
      dependencies:
        - name: resource_group
          ref: cs_resource_group
    - name: ibm-kms-key
      variables:
        - name: provision
          value: true
      dependencies:
        - name: kms
          ref: kms
    - name: ibm-activity-tracker
      variables:
        - name: provision
          value: false
      dependencies:
        - name: resource_group
          ref: at_resource_group
    - name: ibm-object-storage-bucket
      alias: flow_log_bucket
      variables:
        - name: label
          value: flow-logs
        - name: allowed_ip
          value:
            - 0.0.0.0/0
    - name: ibm-vpe-gateway
      alias: vpe-cos
      dependencies:
        - name: resource
          ref: cos
        - name: subnets
          ref: vpe-subnets
        - name: sync
          ref: cluster
    - name: ibm-transit-gateway
      variables:
        - name: provision
          value: false
        - name: name_prefix
          alias: cs_name_prefix
          scope: global
      dependencies:
        - name: resource-group
          ref: cs_resource_group
    - name: logdna
      variables:
        - name: provision
          value: false
        - name: name_prefix
          alias: cs_name_prefix
          scope: global
      dependencies:
        - name: resource_group
          ref: cs_resource_group
    - name: sysdig
      variables:
        - name: provision
          value: false
        - name: name_prefix
          alias: cs_name_prefix
          scope: global
      dependencies:
        - name: resource_group
          ref: cs_resource_group
    - name: ibm-logdna-bind
    - name: sysdig-bind
  variables:
    - name: mgmt_resource_group_name
    - name: mgmt_resource_group_provision
    - name: region
    - name: ibmcloud_api_key
    - name: name_prefix
      alias: mgmt_name_prefix
      required: true
    - name: cs_resource_group_name
    - name: cs_name_prefix
    - name: worker_count
    - name: kms_service

API Usage

Development

Basic flow

The IasCable application is built with JavaScript/Typescript. The development process follows standard JavaScript development activities with perhaps one small deviation. To make development updates to IasCable, do the following (all of this assumes you have already cloned the repository):

  1. Before starting, make sure you have installed the latest dependencies by running npm ci
  2. Create a branch for your work by running git checkout -b {branch_name}
  3. Start the tests by running npm run tdd
  4. Make updates to the unit tests and the application code. The unit tests should re-run every time the code is changed
  5. When you are done with the code changes, press Ctrl-C to stop the tdd process
  6. Build the application code with npm run build
  7. To run your local build of IasCable, use the iascable script in the repository directory. E.g. ./iascable build -i examples/baseline-ocp2.yaml
  8. Commit and push your branch to the repo
  9. Create a pull request for the branch. Add a release tag (major, minor, or patch) to the pull request based on the type/complexity of the change. Add a changelog tag (enhancement, bug, or chore) based on the type of change
  10. When the checks pass, the pull request can be squashed and merged to the main branch

General code structure

All of the source code can be found under the src/ directory.

  • src/commands contains the command-line logic based on the Yargs package. This is a thin wrapper to translate command-line arguments into service requests
  • src/errors contains the different error types
  • src/models contains the data models
  • src/services contains the api layer with the business logic for the package. The services are sub-divided into functional areas - catalog-loader, module-selector, terraform-builder, dependency-graph, module-documentation, etc
  • src/util contains common utilities

NPM scripts

  • npm t: Run test suite
  • npm start: Run npm run build in watch mode
  • npm run test:watch: Run test suite in interactive watch mode
  • npm run test:prod: Run linting and generate coverage
  • npm run build: Generate bundles and typings, create docs
  • npm run lint: Lints code
  • npm run commit: Commit using conventional commit style (husky will tell you to use it if you haven't 😉)

Creating a beta release

Currently, the process of tagging a beta release is somewhat manual because the release-drafter action doesn't handle calculating the version numbers across different branches with different naming schemes. In order to create a beta release, do the following:

  1. Check out the beta branch and pull the latest, if a beta branch does not exist (because we have merged the results) create a new beta branch off of main

  2. Create a branch for your changes

  3. Create a PR for your branch and set it to merge to beta

  4. In your branch changes, update the version value in package.json. Increment the base version number as appropriate (e.g. 2.5.2 to 2.6.0 or 3.0.0) and add -beta.x to the end. The idea is for the x in -beta.x to increment as updates to your beta changes are made.

  5. When your branch is ready, merge the PR into beta. (Note: this will not trigger an automatic release so you have an opportunity to make updates before the next step)

  6. Change to the beta branch and create an annotated tag on the beta branch that matches the version number in package.json.

    git tag -a v{version} -m {message}

    where:

    • {version} is the version number in package.json
    • {message} is a message about the release (e.g. the first line of the commit message)
  7. Push the tag to the remote

    git push --tags
  8. In the browser, create a new release. Be sure to pick the tag you just created for the release tag and check the "pre-release" box. Provide the tag name as the release title and press the "Generate changelog"

  9. Once the release is created, it will trigger a workflow to push the new version to the npm registry and to attach the assets to the release.

iascable's People

Contributors

actions-user avatar balasgit avatar csantanapr avatar nheidloff avatar noesamaille avatar rich-ehrhardt avatar seansund avatar timroster avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

iascable's Issues

The generated BOM should contain all the modules in the generated terraform

The generated BOM contains only the entries from the original BOM with the versions added. The idea is to make BOM that can be used repeatably to produce the same output. However, if the dependent modules are missing there is a very good chance of changes if any of those modules change.

The terraform generation process resolves all the module dependencies when it runs. We should include all of the resolved modules and their versions in the generated BOM.

Problems with variables generated for terraform output

The variables generated for terraform output have two problems that don't allow the modules to execute properly:

  • Default values are provided for every variable, even if one is not set in the parent module
  • The default values are always created as strings

Install script fails to install the binary

The install script fails to install the iascable binary into /usr/local/bin. No error is reported, however, the binary is not installed into the directory.

Manually downloading the binary and attempting to copy gives a permission denied error. Using sudo to copy the binary does work. /usr/local/bin is owned by root by default.

OS: MacOS 12.3

Tammy would like a business-user friendly printable error message returned if the BOM is not found

Display a friendly error if the BOM provided via the -i argument is not found

Currently things blow up if a bom is not found. We should make it friendlier:

iascable build -i boms/infrastructure/ibmcloud/ibmcloud-cloudnative-squad-test-cluster/setup-gitops.yaml -o output/new-setup-gitops
iascable build

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
  -r, --reference        The reference BOM to use for the build
  -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 for the tile. Required if you want to generate
                         the tile metadata.
      --tileDescription  The description of the tile.
      --ci                                                             [boolean]
      --prompt                                                         [boolean]
      --debug            Flag to turn on more detailed output message  [boolean]

[Error: ENOENT: no such file or directory, open 'boms/infrastructure/ibmcloud/ibmcloud-cloudnative-squad-test-cluster/setup-gitops.yaml'] {
  errno: -2,
  code: 'ENOENT',
  syscall: 'open',
  path: 'boms/infrastructure/ibmcloud/ibmcloud-cloudnative-squad-test-cluster/setup-gitops.yaml'
}

This does show the root cause, but its overwhelming.

Don't show command reference.
Pretty-print the error message

Tammy would like to know that the automated BOM has been tested successfully recently

It'd be good to set up github actions to set up github actions to validate that:

  • BOMs has proper format & metadata
  • BOMs generate cleanly w/ iascable to spot those errors on existing BOMs when checking out changes

Recently failing BOMs from 160 to 170 fail e.g.:

❯ iascable build -i 160-openshift-dev-tools.yaml
Name: 160-openshift-dev-tools
Loading catalog from url: https://modules.cloudnativetoolkit.dev/index.yaml

Error: More than one module resolves dependency for module: module=artifactory, dependency=namespace, refs=[{"source":"github.com/cloud-native-toolkit/terraform-k8s-namespace","version":">= 2.1.0"}], matchingModules=namespace,openshift-gitops

Add support for enum lists in variable values

  • Add enum to the options for the module variables
  • Append the enum values to the generated description for the variable
  • As a stretch goal, generate a validation block on the variable to ensure the value matches the provided enum list

Return warning for variable name and dependency name mismatches

Variable names provided in BOM modules that don't match module variables are currently silently ignored. Instead a warning should be returned with the api call that those variables did not match values in the module so action can be taken.

The same applies for dependencies that don't match.

Perhaps the warning should return all the available variables or dependencies so the user can see what to change it to.

Maureen would like to be able to use the same variable name for multiple modules

Feature request: Ability to have common variable names between combination of modules

Currently we have ability to have global variable names or local to a module. The global variable names are taken directly from the module variable name. It will be good to have variable names shared across a few modules.

Example:

In the following BOM, two modules need name_prefix defined as variable mgmt_name_prefix whereas the other two as workload_name_prefix

   - name: ibm-kms-key
      alias: mgmt_kms_key
      variables:
        - name: provision
          value: true
        - name: name_prefix
          alias: mgmt_name_prefix
    - name: ibm-object-storage
      alias: mgmt_cos
      dependencies:
        - name: resource_group
          ref: mgmt_resource_group
      variables:
        - name: name_prefix
          ref: mgmt_name_prefix

   - name: ibm-kms-key
      alias: mgmt_kms_key
      variables:
        - name: provision
          value: true
        - name: name_prefix
          alias: workload_name_prefix
    - name: ibm-object-storage
      alias: mgmt_cos
      dependencies:
        - name: resource_group
          ref: workload_resource_group
      variables:
        - name: name_prefix
          ref: workload_name_prefix

Variable conflict in 170-openshift-argocd.yaml, for module ocp-login

Got the following error when validating yaml config for module ocp-login in ref. architecture 170:

{
  message: 'YAML module config error for module ocp-login',
  architecture: '170-openshift-argocd',
  details: BillOfMaterialModuleConfigError: Variables and/or dependencies provided in config but not defined in module.
      ... {
    availableDependencyNames: [],
    availableVariableNames: [
      'server_url',
      'login_user',
      'login_password',
      'login_token',
      'skip',
      'cluster_version',
      'ingress_subdomain',
      'tls_secret_name'
    ],
    unmatchedDependencyNames: [],
    unmatchedVariableNames: [ 'user', 'password' ]
  }
}

Since there are login_user and login_password in the available variable names I'm guessing we want to replace user and password by these in 170-openshift-argocd.yaml.

Dependency that is a list pulls all module instances, not just the one referenced

Dependency that is a list/array pulls all module instances, not just the one referenced

In 150 bom, There are 2 vpcs:

    - name: ibm-vpc
      alias: management-vpc
      dependencies:
        - name: resource_group
          ref: mgmt_resource_group
      variables:
        - name: provision
          value: false
        - name: name
          required: true
        - name: name_prefix
          alias: mgmt_name_prefix
          scope: global

    - name: ibm-vpc
      variables:
        - name: address_prefix_count
          value: 3
        - name: address_prefixes
          value:
            - 10.40.0.0/18
            - 10.50.0.0/18
            - 10.60.0.0/18
}

Further down in the bom, I am referencing only the second (non-aliased) instance:

    - name: ibm-transit-gateway
      variables:
        - name: provision
          value: false
        - name: name_prefix
          alias: cs_name_prefix
          scope: global
      dependencies:
        - name: resource-group
          ref: cs_resource_group
        - name: connections
          ref: ibm-vpc

However, the generated output terraform contains a reference to both ibm-vpc modules, so it appears to be too aggressive when handling arrays/lists:


module "ibm-transit-gateway" {
  source = "github.com/cloud-native-toolkit/terraform-ibm-transit-gateway?ref=v0.2.2"

  resource_group_name = module.cs_resource_group.name
  connections = [module.ibm-vpc.crn,module.management-vpc.crn]
  region = var.region
  name = var.ibm-transit-gateway_name
  name_prefix = var.cs_name_prefix
  provision = var.ibm-transit-gateway_provision
}

(notice there are 2 connections when I only expected 1.

Maureen would like to simplify the way namespaces are configured in the bill of materials

Bill of Material should allow short hand for namespaces

Currently to specify a particular namespace for a module, a lot of configuration is required.

modules:
  - name: gitops-namespace
    alias: tools
    variables:
      - name: name
        value: tools
  - name: gitops-mymodule
    dependencies:
      - id: namespace
        ref: tools

We should be able to provide shorthand to reduce the number of elements required. E.g.

modules:
  - name: gitops-mymodule
    namespace: tools
    dependencies:
      - id: namespace
        ref: tools

Support version numbers in BOM

  • Generate the output BOM with the version numbers of the resolved modules
  • Use provided version numbers to resolve module versions

Maureen would like to be able to define different sets of default variables values for a single BOM

The current BOM will generate a xxx.auto.tfvars file containing the variables and descriptions that need to be provided as input to the terraform templates. There are some situations where we will want multiple versions of the auto.tfvars files for different default value settings and suggestions. For example, for Turbonomic and Maximo the storage class values will change whether the deployment is AWS, Azure, or IBM Cloud. It is desirable to have aws.auto.tfvars, azure.auto.tfvars, and ibmcloud.auto.tfvars files with suggested defaults (or to have one file with different sections depending on the hyperscaler).

Generate terraform using `string`, `bool` and `number` types

As a result of a design decision made a while ago to accommodate the Private Catalog Tile input restrictions, the generator exposes all global variables as strings and performs a transformation when the value is passed to the module.

For example:

  • bool is transformed using var.something == "true"
  • number is transformed using built in transformation
  • list(string) is expected to be provided as a comma-delimited string and is transformed with split(",", var.something)
  • list(object({})) is expected to be provided as a JSON string and is transformed with jsondecode(var.something)

However, Schematics does not currently have these restrictions (at least not for bool and number) and converting to string actually makes it harder to use. (Not sure about the current Tile implementation.)

Instead of converting boolean and number types to string we should expose them as-is so they can be handled properly in Schematics.

Raised by @jachtermann

Variables of type list(string) are being improperly serialized.

Here is an example. Look at the client_dns variable in the BOM:

module "ibm-vpn-server" {
  source = "github.com/cloud-native-toolkit/terraform-ibm-vpn-server?ref=v0.0.7"

  resource_group_name = module.resource_group.name
  certificate_manager_id = module.ibm-cert-manager.id
  vpc_id = module.ingress-subnets.vpc_id
  subnet_ids = module.ingress-subnets.ids
  region = var.region
  ibmcloud_api_key = var.ibmcloud_api_key
  resource_label = var.ibm-vpn-server_resource_label
  name_prefix = var.edge_name_prefix
  vpnclient_ip = var.ibm-vpn-server_vpnclient_ip
  client_dns = var.ibm-vpn-server_client_dns == null ? null : jsondecode(var.ibm-vpn-server_client_dns)
  auth_method = var.ibm-vpn-server_auth_method
  vpn_server_proto = var.ibm-vpn-server_vpn_server_proto
  vpn_server_port = var.ibm-vpn-server_vpn_server_port
  vpn_client_timeout = var.ibm-vpn-server_vpn_client_timeout
  enable_split_tunnel = var.ibm-vpn-server_enable_split_tunnel
}

In the module's variables.tf you can see that this is an array of strings, and has terraform type list(string):

variable "client_dns" {
  type        = list(string)
  description = "Comma-separated DNS IPs for VPN Client Use ['161.26.0.10','161.26.0.11'] for public endpoints, or ['161.26.0.7','161.26.0.8'] for private endpoints"
  default     =  ["161.26.0.7","161.26.0.8"]
}

However, when the bom is generated using the iascable command, you can see the generated terraform has changed this to a string value, instead of an array of strings:

variable "ibm-vpn-server_client_dns" {
  type = string
  description = "Comma-separated DNS IPs for VPN Client Use ['161.26.0.10','161.26.0.11'] for public endpoints, or ['161.26.0.7','161.26.0.8'] for private endpoints"
  default = "\"[161.26.0.7,161.26.0.8]\""
}

This results in an error at terraform execution time b/c it is unalbe to deserialize the "\"[161.26.0.7,161.26.0.8]\"" b/c of improper encoding. It should instead have been "[\"161.26.0.7\",\"161.26.0.8\"]" (an array of strings, instead of just a string).

iascable build gives confusing error when not specifying input file

I cloned isacable, ran npm install, then ./iascable build. I was expecting either it would default to bom.yaml (I'd copied in one from here), or give me an error, but I saw this:

Name: component
Loading catalog from url: https://modules.cloudnativetoolkit.dev/index.yaml
? Which ai-ml module(s) should be used?
❯◯ gitops-cp-bas: Module to populate a gitops repo with the resources to provision cp-bas

I'm definitely not doing ai-ml or cp-bas ;) Not sure what this is defaulting to but this doesn't seem quite right?

The apply.sh script should not save sensitive values to variables.yaml

The apply.sh script will prompt for variable values and write them to variables.yaml. If the value is sensitive then the prompt is masked but we still write the value in clear text to variables.yaml. The sensitive variables shouldn't be written.

Also, the prompt will check for the presence of a TF_VAR environment variable first. This should be included in the prompt info.

Carlos would like to see a diagram of the module dependencies for the Bill of Materials

Add the generated png file for the dependency graph to the output and add documentation

Currently we generate a dependencies.dot file that contains the dependency graph for the modules in the BOM but we do not include the diagram or any information about the file. Even though the DOT notation is a well established standard, we should also include some documentation about it as well.

Maureen would like to be able to store the Terraform state information - including the BOM file and/or iascable CLI - in backend locations beyond the local filesystem

Add support for configuring terraform backends

The state information in Terraform can be stored in a number of different locations. If not provided, the state defaults to a file in the local filesystem. However, in many cases it is preferred to store the state in a remote backend like an S3 bucket or postgresql database.

The BOM file/iascable cli should support configuration for different backends.

Maureen would like default values for all namespaces in the BOM

Pull the default value from parent module dependency in a BOM

Example:

spec:
  modules:
    - name: ocp-login
    - name: openshift-cicd

When this generates you get 3 namespaces created (gitops, tools, sealed-secreates), but generated without default values. In openshift-cicd we have default values, but they're not being applied/propagated.

Using example baseline-ocp.yaml give subnet errors

Use the following example

apiVersion: cloud.ibm.com/v1alpha1
kind: BillOfMaterial
metadata:
  name: baseline-ocp
spec:
  modules:
    - name: ibm-vpc-gateways
    - name: ibm-ocp-vpc
      variables:
        - name: flavor
          important: true
    - name: openshift-cicd

Run iascable

iascable build -i baseline-ocp.yaml

Run terraform

terraform init
terraform plan

Errors

│ 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.
╵
╷
│ Error: Invalid value for module argument
│
│   on main.tf line 64, in module "ibm-vpc-subnets":
│   64:   acl_rules = var.ibm-vpc-subnets_acl_rules == null ? null : jsondecode(var.ibm-vpc-subnets_acl_rules)
│
│ The given value is not suitable for child module variable "acl_rules" defined at .terraform/modules/ibm-vpc-subnets/variables.tf:59,1-21: list of object required.

Cleanup ref-arch logic and duplicate content in ref-arch/

We have two options:

  • either pull from automation solutions
  • get rid of ref-arch flag, make generation explicit on a specific file using -i

Another approach:

  • iascable list prints contents of automation-solutions
  • -r points to url from automation-solutions file

Eventually:

  • generate entire solution

Maureen would like an easier way to describe dependencies in the BOM

Currently we have to do this:

spec:
  modules:
    - name: ocp-login
    - name: openshift-cicd
    - name: console-link-job
      dependencies:
        - name: namespace
          ref: tools
    - name: cluster-config
      alias: config
      dependencies:
        - name: namespace
          ref: tools
    - name: namespace
      alias: tools
      variables:
        - name: name
          value: tools

Ideally we could do this:

spec:
  modules:
    - name: ocp-login
    - name: openshift-cicd
    - name: console-link-job
      dependsOn: tools
    - name: cluster-config
      alias: config
      dependsOn: 
        - tools
    - name: namespace
      alias: tools
      variables:
        - name: name
          value: tools

Tammy would like to know what security permissions are needed to run each module

document the ibm cloud IAM roles for the api key

Document what level of access is required for each module in order to execute. Also, include instructions (where?) for how to create a service id on IBM Cloud, grant the proper permissions, and generate an API Key. Perhaps we can provide a script to generate a Service ID, generate an Access Group, and add the Service ID to the Access Group. If the required permissions are general enough, perhaps we can also add the necessary policies to the Access Group.

Replace dashes with underscores when creating global variables

In terraform, global variables can be provided via environment variables by prefixing the variable name with TF_VAR_. So if the variable name is test-value a value can be provided via environment variables using TF_VAR_test-value. However, bash does not allow dashes (-) to appear in environment variable names.

We should replace all dashes with underscores when the global environment variables are defined to prevent this issue.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.