Skip to content

LAB 46 ‐ Create compartment using modular approach

DevWithNehaCloud edited this page Jul 14, 2026 · 13 revisions

OCI Compartment Architecture: Multi-Tier Hierarchical Setup using Terraform Modules

This documentation covers the design and deployment of a multi-tier compartment structure for the Swiggy Dev Environment. The architecture consists of a main parent environment compartment containing isolated sub-compartments for core infrastructure pillars: Network and Storage.

To make the code simple and easy to manage, we used a Direct Root Module Parameter approach. The module defines the required variables in variables.tf, and the actual values for each environment are provided directly in the root module file (for example, dev/compartment.tf).

1. Directory Structure

The project is hosted under the identity_service repository. Environment layers (dev, test, uat, prod) execute independently by pulling generic source logic from the centralized compartment_module.

identity_service/
│
├── compartment_module/          # Core Shared Module
│   ├── main.tf                 # Resource definitions
│   ├── variables.tf            # Module inputs
│   └── outputs.tf              # Module exports (Critical for dynamic mapping)
│
└── dev/                        # Dev Environment Execution Folder
    ├── compartment.tf          # Core topology (1 Parent + 2 Children)
    ├── provider.tf             # OCI Authentication Config
    └── privkey.pem             # API Private Key (Git-ignored)

image

2. Core Module Definitions (modules/compartment_module)

A. variables.tf

Declares the strict explicit schema required to construct any safe compartment instance on OCI.

variable "compartment_parent_id" {
  type        = string
  description = "OCI Parent Compartment OCID"
}

variable "compartment_name" {
  type        = string
  description = "Name of the compartment"
}

variable "compartment_description" {
  type        = string
  description = "Description for the compartment"
}

image

B. main.tf

Utilizes an explicit resource label (my_compartment). The safety lock enable_delete is configured to true to ensure agile lifecycle teardowns inside non-production tracks.

resource "oci_identity_compartment" "my_compartment" {
  compartment_id = var.compartment_parent_id
  name           = var.compartment_name
  description    = var.compartment_description
  enable_delete  = true
}
image

C. outputs.tf

Captures the runtime metadata from the created OCI resource. This exported ID allows cascading dependencies dynamically into child blocks.

output "compartment_id" {
  value       = oci_identity_compartment.my_compartment.id
  description = "The OCID of the created compartment"
}
image

3. Environment Workspace Layout (dev/)

A. provider.tf

Handles regional scope boundaries and points directly to the workspace-enclosed API key asset.

provider "oci" {
  auth             = "APIKey"
  tenancy_ocid     = "ocid1.tenancy.oc1..aaaaaaaacxrxza63ajbfdhvukzuxpv4y3oksxh256migpqx6lazpbbejuuga"
  user_ocid        = "ocid1.user.oc1..aaaaaaaa5m4rn7uj5exypqxsz54tmkqctcuzd7o4ehy2f35flcdzznncw77a"
  private_key_path = "/home/ngsoftlook/identity_service/dev/privkey.pem"
  fingerprint      = "4c:bb:0e:8b:6e:b1:df:51:59:bf:c6:e3:60:2c:d6:29"
  region           = "us-ashburn-1"
}
image

B. compartment.tf

Builds the dynamic chain structure. Notice how the Storage and Network blocks implicitly rely on the outputs of the Parent block, eliminating hardcoded IDs or loose external variables files.

# =======================================================
# # 1. PARENT COMPARTMENT: swiggy-dev-compartment
# =======================================================
module "swiggy_dev_parent" {
  source = "/home/ngsoftlook/identity_service/compartment_module"

  compartment_parent_id = "ocid1.tenancy.oc1..aaaaaaaacxrxza63ajbfdhvukzuxpv4y3oksxh256migpqx6lazpbbejuuga" # OCID of the tenancy
  compartment_name      = "swiggy-dev-compartment"
  compartment_description = "Main Parent Compartment for Dev Environment"
}

# =======================================================
# # 2. CHILD COMPARTMENT: swiggy-dev-compute-and-storage-compartment
# =======================================================
module "swiggy_dev_compute_and_storage" {
  source = "/home/ngsoftlook/identity_service/compartment_module"

  # It will dynamically retrieve the ID from the parent module's output.
  compartment_parent_id = module.swiggy_dev_parent.compartment_id

  compartment_name        = "swiggy-dev-compute-and-storage-compartment"
  compartment_description = "Child Compartment for swiggy Dev Storage Resources"
}

# =======================================================
# # 3. CHILD COMPARTMENT: swiggy-dev-network-compartment
# =======================================================
module "swiggy_dev_network" {
  source = "../compartment_module"

  # It will also dynamically retrieve the ID from the parent module's output.
  compartment_parent_id = module.swiggy_dev_parent.compartment_id

  compartment_name        = "swiggy-dev-network-compartment"
  compartment_description = "Child Compartment for swiggy Dev Network Resources"
}
image image

📌 Terraform Module Paths: Absolute vs Relative Path

When defining the source attribute inside a Terraform module block, Terraform provides two different ways to specify the location of the module folder. In our project setup, both methods work perfectly without throwing any errors, but they handle file system navigation differently.

📁 Project Folder Structure

identity_service/
├── compartment_module/   <-- (Target Module)
└── dev/                  
    └── compartment.tf    <-- (Current Working Directory)

1️⃣ Absolute Path

  • Example: source = "/home/ngsoftlook/identity_service/compartment_module"
  • What it is: This is the complete and fixed path starting right from the system's root directory (/).
  • How it works: No matter which folder you are currently inside when running the code, this path remains unchanged because it explicitly spells out the entire journey from the very top of the computer's file system.

2️⃣ Relative Path

  • Example: source = "../compartment_module"
  • What it is: This path is calculated relative to your Current Working Directory (the folder where your executing code resides).
  • How it works:
    • While working inside compartment.tf under the dev folder, Terraform treats . (single dot) as the current dev directory.
    • When we use .. (double dot), Terraform steps out of the dev folder (moves one level up) and enters the parent identity_service folder.
    • Following it up with /compartment_module routes Terraform straight into the intended module folder.

💡 Why did Terraform accept both paths without errors?

Terraform successfully accepted both pathing styles because, ultimately, both directions lead to the exact same target compartment_module folder on the machine.

🌟 Production Best Practice

In real-world Cloud Architecture projects, always prefer using Relative Paths (../).

  • Why? If you push this repository to GitHub or clone the identity_service directory onto another machine or a CI/CD runner, the absolute system path (like /home/ngsoftlook) will change, breaking the configuration. Relative paths keep the code dynamic and portable because the shared structural relationship between the folders remains identical across all systems.

4. Execution & Validation Steps

Step 1: Initialize Workspace

Run initialization inside the target environment folder to pull specific providers and properly wire regional relative modules path links.

cd identity_service/dev/

terraform init

Add your terminal screenshot here showing successful init: image

image

Step 2: Dry Run Compilation Check

Run a speculative plan validation to confirm that the sequential execution paths evaluate correctly, showing exactly 3 resources ready to be deployed.

terraform plan
image

Step 3: Execute and Deploy Infrastructure

Once the speculative dry-run plan is verified, execute the active deployment to build the multi-tier compartment structure inside your live OCI tenancy.

terraform apply
image

Now, verifying in console

image image

Step 4: Infrastructure Teardown and Cleanup

When the development environment resources are no longer needed (or during environment resets), you can securely decommission the entire hierarchical compartment tree using the destroy command.

terraform destroy
image image image image

Key Architectural Benefits Realized

Implicit Dependency Graphing: Passing module.swiggy_dev_parent.compartment_id instructs Terraform's scheduler to block child creations until the core environment zone settles securely.


💡 Technical Note: Deep-Dive into Dynamic Resource Linking (Why outputs.tf is Critical)

To avoid hardcoding and manual copy-pasting of OCI OCIDs, this architecture relies heavily on Terraform's implicit dependency mapping via outputs. Here is the exact lifecycle breakdown of how IDs flow across runtime:

1. The Internal Attribute Generation (.id)

Inside our core module (main.tf), we defined our resource with a local identifier: oci_identity_compartment.my_compartment.

  • The .id suffix is a fixed, built-in system attribute of the Oracle OCI provider.
  • The moment Oracle Cloud successfully provisions the parent compartment, it generates a unique runtime OCID. Terraform captures this value inside oci_identity_compartment.my_compartment.id.

2. The Packaging Layer (outputs.tf)

Because variables inside a module are encapsulated (isolated), the root execution workspace cannot see this internal .id natively. We expose it by creating an output block:

output "compartment_id" {
  value = oci_identity_compartment.my_compartment.id
}

compartment_id acts as a custom public label/envelope holding that dynamic runtime value.

  1. Consuming the Variable in Child Modules (compartment.tf) When provisioning the sequential downstream tracks (swiggy_dev_storage and swiggy_dev_network), we reference that specific exposed envelope:

compartment_parent_id = module.swiggy_dev_parent.compartment_id

🧠 Architectural Summary for Future Reference

Here is the exact data flow chain during execution:

  1. 🚀 OCI Cloud Infrastructure Engine └── Generates the real live OCID string as a built-in attribute: .id

  2. 📦 Shared Module Wrapper (outputs.tf) └── Packs that raw ID into a clean public envelope named: compartment_id

  3. 🛠️ Dev Workspace Caller (compartment.tf) └── Child modules catch that envelope instantly using: module.swiggy_dev_parent.compartment_id

Without this automated chain, deploying a multi-tier infrastructure in a single execution track is impossible because child layers cannot look into the cloud or see other modules without a public output envelope.

Note: Creating Parent and Child Compartments With or Without output.tf

When creating a compartment hierarchy in Terraform, there are two possible approaches.

Approach 1: Using output.tf (Single Terraform Execution)

In our implementation, we created the parent compartment (Swiggy Dev) and both child compartments (Swiggy Dev Container Storage and Swiggy Dev Network) in a single Terraform execution.

Since the child compartments require the OCID of the parent compartment, Terraform first creates the parent compartment and then uses an output value to expose the runtime-generated OCID. This OCID is then consumed by the child compartment resources during the same deployment.

Benefits

  • Parent and child compartments are created in a single terraform apply.

  • No manual copying of OCIDs is required.

  • The entire deployment remains automated and reusable.

  • Ideal for Infrastructure as Code (IaC) workflows.

Flow

Parent Compartment
       │
       ▼
Runtime OCID Generated
       │
       ▼
output.tf Exposes OCID
       │
       ▼
Child Compartments Consume OCID

Approach 2: Without Using output.tf (Manual Two-Step Process)

It is also possible to create the same compartment hierarchy without using output.tf.

In this approach:

  1. Create only the parent compartment first.

  2. Run terraform apply.

  3. After the parent compartment is created, copy its OCID from the OCI Console.

  4. Paste the OCID into the Terraform configuration as the parent compartment ID.

  5. Run terraform apply again to create the child compartments.

Benefits

  • Simpler configuration for small environments.

  • No output values are required.

  • Useful when the parent compartment already exists.

Flow

Create Parent Compartment
           │
           ▼
Copy Parent OCID From OCI Console
           │
           ▼
Paste OCID Into Terraform Configuration
           │
           ▼
Create Child Compartments

Why We Used output.tf

In our project, the parent compartment (Swiggy Dev) and its child compartments (Swiggy Dev Container Storage and Swiggy Dev Network) were created together in a single Terraform execution.

Because the parent compartment OCID did not exist until runtime, Terraform needed a way to capture that newly generated OCID and pass it to the child compartments automatically. This is why output.tf was used.

Without output.tf, we would have had to:

  1. Create the parent compartment first.

  2. Retrieve its OCID manually from the OCI Console.

  3. Update the Terraform configuration with that OCID.

  4. Run Terraform again to create the child compartments.


Key Takeaway

output.tf is not mandatory for creating parent-child compartment relationships. It becomes useful when the parent and child compartments must be created together in a single automated Terraform execution and the parent OCID is only available at runtime.

Method Parent & Child Created Together Manual OCID Copy Required Automation Level
Using output.tf ✅ Yes ❌ No High
Without output.tf ❌ No (Two-Step Process) ✅ Yes Low

Summary

Using output.tf

  • Creates parent and child compartments in a single Terraform execution.
  • Automatically passes the runtime-generated parent OCID to child compartments.
  • Eliminates manual intervention.
  • Recommended for fully automated Infrastructure as Code (IaC) deployments.

Without output.tf

  • Requires creating the parent compartment first.
  • The parent OCID must be copied manually from the OCI Console.
  • Child compartments are created in a separate Terraform execution.
  • Suitable for small or one-time deployments where automation is not a priority.

Clone this wiki locally