Improving OCI Stacks with Schema Documents

oci Sep 23, 2024

In a previous post, I talked about using Stacks in OCI Resource Manager. Stacks allow you to automate provisioning using Terraform. This is basically adding another layer on top of Terraform to help manage your code and the deployment process. While you can interact with a Stack via CLI tools or REST API, the main use case is the OCI Console. This allows for a nice GUI to easily deploy infrastructure reliably and repeatably.

A nice feature of Stacks is the Configure variables page. This page automatically pulls in your Terraform variables and lists them in a form so you can edit them as needed. If your variables are configured in Terraform with a default, that will be displayed and the variable will be listed as Optional.

Also, a few variables will be automatically prepopulated even if they aren’t configured with defaults. These are special variables that use values pulled from your current OCI Console session.

  • tenancy_ocid (tenancy OCID)
  • compartment_ocid (compartment OCID)
  • region (region)
  • current_user_ocid (OCID of the current user)

While this is nice and convenient, you can see the resulting page is a little rough. The labels are not the best, some of these variables are missing descriptions and the order is not ideal.

Schema Documents

What would be great is a way to edit the labels and layout of this variables page. That is where Schema Documents come in. These documents give you a way to extend pages in the OCI Console and allow for very user friendly variable entry for Stacks.

A Schema Document is written in YAML format, named schema.yaml, and placed under the root directory of the Resource Manager Terraform configuration. The document should be written to organize and layout the variable configuration page. The variables and their attributes should be consistent between the schema document and the Terraform configuration.

Let’s write a simple Schema Document example. First, there are a few attributes every schema should have. A title, a description and some version settings.

title: oci-stack-schema
description: Example Schema Document
schemaVersion: 1.0.0
version: "1.20240921"

Next, let’s layout how we want to group our variables. The variableGroups attribute allows for organizing and ordering how variables are displayed on our page. You can even make a group hidden if you don’t want to allow the variable to be overridden.

variableGroups:
  - title: "Console Defaults"
    visible: true
    variables:
      - ${tenancy_ocid}
      - ${compartment_ocid}
      - ${region}
  - title: "Networking"
    visible: true
    variables:
      - ${network_compartment_ocid}
      - ${vcn_ocid}
      - ${subnet_ocid}
  - title: "Hidden"
    visible: false
    variables:
      - ${current_user_ocid}

Lastly, we will list our variables. Again, these should be consistent with your Terraform variables. If you declare a variable as a number in the schema, it needs to be declared as a number in Terraform as well. By specifying the variable type, Resource Manager will dynamically prepopulate fields and offers validation controls. For certain types, using a dependsOn attribute will dynamically populate drop downs and filter options depending on what is selected for other variables. An example, selecting a VCN can then control what Subnet options are available in that variable drop down.

variables:
# Console Defaults
  tenancy_ocid:
    title: Tenancy OCID
    type: string
    required: true
  compartment_ocid:
    title: Compartment OCID
    type: oci:identity:compartment:id
    required: true
  region:
    title: Region
    required: true
    type: oci:identity:region:name
  current_user_ocid:
    title: User OCID
    required: true
# Network
  network_compartment_ocid:
    title: Network Compartment OCID
    type: oci:identity:compartment:id
    required: true
  vcn_ocid:
    title: VCN
    required: true
    type: oci:core:vcn:id	
    dependsOn:
      compartmentId: network_compartment_ocid
  subnet_ocid:
    required: true
    type: oci:core:subnet:id
    dependsOn:
      compartmentId: network_compartment_ocid
      vcnId: vcn_ocid

If we put that all together, we get a schema.yaml file as shown below. This file should be saved in the root terraform directory. 

title: oci-stack-schema
description: Example Schema Document
schemaVersion: 1.0.0
version: "1.20240921"

variableGroups:
  - title: "Console Defaults"
    visible: true
    variables:
      - ${tenancy_ocid}
      - ${compartment_ocid}
      - ${region}
  - title: "Networking"
    visible: true
    variables:
      - ${network_compartment_ocid}
      - ${vcn_ocid}
      - ${subnet_ocid}
  - title: "Hidden"
    visible: false
    variables:
      - ${current_user_ocid}

variables:
# Console Defaults
  tenancy_ocid:
    title: Tenancy OCID
    type: string
    required: true
  compartment_ocid:
    title: Compartment OCID
    type: oci:identity:compartment:id
    required: true
  region:
    title: Region
    required: true
    type: oci:identity:region:name
  current_user_ocid:
    title: User OCID
    required: true
# Network
  network_compartment_ocid:
    title: Network Compartment OCID
    type: oci:identity:compartment:id
    required: true
  vcn_ocid:
    title: VCN
    required: true
    type: oci:core:vcn:id	
    dependsOn:
      compartmentId: network_compartment_ocid
  subnet_ocid:
    required: true
    type: oci:core:subnet:id
    dependsOn:
      compartmentId: network_compartment_ocid
      vcnId: vcn_ocid

Now we go back to our Stack and adjust our configuration to point to the latest Terraform changes, which includes this new schema.yaml file. When we click next and go to the Configure variables page, we now see a more user friendly page that matches our schema configuration. You can see some of the variable drop down menus have prepopulated and user friendly values to select from.

This is a very simple schema, but you can make ones with much greater complexity. Follow the documentation for more examples of greater control of Console items. There are even more advanced options to be used when packaging up a Stack for the OCI Marketplace. Once you get a feel for how the schema works, it is very quick and easy to setup a user friendly variable entry page for your Stacks.