This time I wanted to show how simple it is to create multiple compartments with one module using Terraform 0.12.

Compartments in OCI are way to separate your resources and control access on them, you can also move resources around from one compartment to another if needed.

Remember one of the reasons one would like to use modules is the reusability. You don’t need to copy&paste same code over and over again but can rather utilize the existing code with all of your projects. And if you need an update, just use versioning and the other projects using same code can stick into existing version.

For this project I have a very simple folder/file structure as we are only creating the compartments we need.

➜  demo-compartments tree
.
├── create-compartments
│   ├── main.tf
│   ├── outputs.tf
│   ├── terraform.tfvars
│   └── variables.tf
└── modules
    └── module-compartments
        ├── main.tf
        └── outputs.tf

I have only one module, module-compartments which creates necessary compartments and sends output to the project.

The other folder, create-compartments has the variables defined in terraform.tfvars, variables just listed in variables.tf and actual code in main.tf. If I would use same folder to run different environments/compartments I could make several tfvars files and then run only the one which I would like.

Let’s take a look on the terraform.tfvars.

// Variables to create compartments 

root_compartment_variables = {
  c1 = { 
     compartment_name = "network_compartment" 
     compartment_description = "Compartment for Network resources"
     }
  c2 = { 
     compartment_name = "ebs_compartment" 
     compartment_description = "Compartment for EBS resources"
      }
  c3 = { 
     compartment_name = "peoplesoft_compartment" 
     compartment_description = "Compartment for PeopleSoft resources"
}
}

ebs_compartment_variables = {
  c1 = { 
     compartment_name = "ebs_apps_compartment" 
     compartment_description = "Compartment for EBS Apps resources"
     }
  c2 = { 
     compartment_name = "ebs_db_compartment" 
     compartment_description = "Compartment for EBS DB resources"
      }
  }

peoplesoft_compartment_variables = {
  c1 = { 
     compartment_name = "peoplesoft_apps_compartment" 
     compartment_description = "Compartment for PeopleSoft Apps resources"
     }
  c2 = { 
     compartment_name = "peoplesoft_db_compartment" 
     compartment_description = "Compartment for Peoplesoft DB resources"
      }
  }

As you can see I’m creating three root level compartments: Network, eBS and Peoplesoft. For eBS and Peoplesoft I’m creating then two child compartments for each. I’m providing multiple maps to my module which will then handle the creation accordingly.

Now on the main.tf I have following code.

provider "oci" {
  tenancy_ocid     = var.tenancy_ocid
  user_ocid        = var.user_ocid
  fingerprint      = var.fingerprint
  private_key_path = var.private_key_path
  region           = var.region
}

// Create Root Compartment
module "CreateRootCompartment" {
  source                = "../modules/module-compartments"
  parent_ocid           = var.tenancy_ocid
  compartment_variables = var.root_compartment_variables
}

// Get the OCID for the parent ebs compartment

locals {
  ebs_root_compartment_id = [
    for i in module.CreateRootCompartment.compartmentinfo : i.id if i.name == "ebs_compartment"
  ]
}

module "CreateCompartmentEBS" {
  source                ="../modules/module-compartments"
  parent_ocid           = local.ebs_root_compartment_id[0]
  compartment_variables = var.ebs_compartment_variables
}
// Get the OCID for the parent peoplesoft compartment

locals {
  peoplesoft_root_compartment_id = [
    for i in module.CreateRootCompartment.compartmentinfo : i.id if i.name == "peoplesoft_compartment"
  ]
}

module "CreateCompartmentPeopleSoft" {
  source                = "../modules/module-compartments"
  parent_ocid           = local.peoplesoft_root_compartment_id[0]
  compartment_variables = var.peoplesoft_compartment_variables
}

I’m creating each “set” of compartments on their own module call. The module will return everything it created and due to fact I will need parent compartment OCID when creating it (notice I’m supplying tenancy OCID in the root compartment creation as it’s their “root”) I will take the OCID of created compartment always into a local.

There are probably better ways to do this as well, if you’ve using one let me know!

Once I have the local defined I will pass that to the module as well as the map I defined in terraform.tfvars in a single variable.

So how does the module look like?

It’s very simple!

variable "parent_ocid" {}
variable "compartment_variables" {type = map}

resource "oci_identity_compartment" "CreateCompartment" {
  for_each      =  var.compartment_variables 
  compartment_id = var.parent_ocid
  name           = each.value.compartment_name
  description    = each.value.compartment_description
  }
  

I use for_each to go through compartment_variables and as you can see when you take the values from the map I need to use “each.value.variable_name” to get desired values.

And once I execute terraform apply I have my compartments created!

Summary

If you start using modules think on the use cases you might have, create modules so they help you on resources which you might need to create over and over again. This example is a really simple but I’ve found it useful when there are many sub-compartments required.

If you want to play around with this or use the code, you can download it from my Git repo which has also instructions how to use it with Terraform. Play around and let me know if you find it useful!

Leave a Reply

Your email address will not be published. Required fields are marked *