My Corrected OCI-IAM-Compartment Terraform Module

Share on:

oracle

oracle2

Introduction

So, turns out I’ve been living in the Stone Age of Terraform. I thought keeping my code lean and mean was the way to go, but apparently, the cool kids are all about terraform modules. They’re all like, “Modularity! Reusability! It’s the secret sauce of Infrastructure as Code!”. Up until now, with my resources being simple, I learned to just leverage dynamic blocks (for each) or variable interpolations through locals to keep it light, but not for long it seems.

 

Are Modules just hype or a real necessity?

This is what I wanted to figure out after getting my HashiCorp certification to see what all the hype was about. And for that, I picked a simple OCI Iam module available in the terraform registry of the Oracle Provider.

 

What’s wrong with the OCI IAM module anyway?

Just like any software, Terraform is constantly evolving. Staying up to date with the latest versions is crucial, as new releases can bring significant changes to the syntax and supported attributes. Failing to prove your code against these updates could break your stack. This applies to Terraform module maintainers too (Oracle TF Modules).

oracle3

The module in question is iam-compartment under: https://github.com/oracle-terraform-modules/terraform-oci-iam

oracle4

At the time of my correction back in Feb, the following errors were not fixed and I was too lazy for a pull request, hence my local module creation. Fortunately for OCI users, recent fixes were added to the iam module.
I didn’t try it yet but feel free to do so.

 

1. Duplicate Required providers configuration (versions.tf & main.tf)

I faced this `iam-compartment` issue with Terraform v1.0.3 but it occurs even with v0.13. Right from the init step.

# terraform init

Initializing modules...
Downloading oracle-terraform-modules/iam/oci 2.0.2 for iam_compartment_x...
- iam_compartment_x in .terraform/modules/iam_compartment_x/modules/iam-compartment
  There are some problems with the configuration, described below.
  The Terraform configuration must be valid before initialization so that Terraform can 
  determine which modules and providers need to be installed.
│ Error: Duplicate required providers configuration
│ on .terraform/modules/iam_compartment_x/modules/iam-compartment/versions.tf line 2, 
| in terraform:
│    2:  required_providers {..
│  A module may have only one required providers configuration. 
| The required providers were previously configured at
 .terraform/modules/iam_compartment_x/modules/iam-compartment/main.tf : line 5,3-21  

 

CAUSE:  See issue #33 

  • In the above error terraform complains that the required_provider block was defined twice

    • versions.tf => line 2  & main.tf  => line 5

oracle5
Reason: In 2022 Oracle moved their terraform provider out of HashiCorp which led to the introduction of required_provider block, to update oci provider source to “oracle/oci“. 

Solution:
Only keep one required_provider block in the compartment module (i.e: version.tf  over main.tf)

# vi ~/modules/iam-compartment/version.tf  terraform {
  required_providers {
    oci = {
      source  = "oracle/oci"  <---- Provider maintained/hosted by Oracle not Hashicorp
      version = ">=4.67.3"
    }
  }
  required_version = ">= 1.0.0"
}

 

2. Deprecated list and map function calls from iam-compartment

Another issue due to deprecated functions (list/map) that were no longer supported by Terraform 

main.tf
..
  compartment_ids   = concat(flatten(data.oci_identity_compartments.this.*.compartments), list(map("id", "")))
  …

Error > main.tf
│ Call to function "list" failed: the "list" function was deprecated in │ Terraform v0.12 and is no longer available; use tolist([ ... ]) syntax to │ write a literal list.

Error >  output.tf
│ Call to function "map" failed: the "map" function was deprecated 
| in Terraform v0.12 and is no longer available; use tomap({ ... }) syntax to
| write a literal map.

CAUSE:  See issue #27 

  • As described in the docs, list() and map() function are deprecated in v012 & removed in v015 (read here)

Solution:
Terraform can infer the necessary type conversions automatically from context. In those cases, you can just use the [...] or {...} syntax directly, without a conversion function.

 

Another option would be to just convert the functions into their new equivalent (map=> tomap, list=>tolist).

 Example: main.tf line 27-28  --- Before
compartment_ids = concat(flatten(data.oci_identity_compartments.this.*.compartments), 
list(map("id", "")))
... --- Option 1 
compartment_ids = concat(flatten(data.oci_identity_compartments.this.*.compartments), 
[{ id = "" }])
...


--- Option2 :  using tomap and tolist 

compartment_ids = concat(flatten(data.oci_identity_compartments.this.*.compartments), 
tolist( [tomap({"id" = ""})]))

 

My corrected version (local module)

It was easier to create a corrected version in my git repo that you can use locally. see folder iam-compartment

oracle6


How to call it
 

Same as if you would for the official registry module (oracle-terraform-modules/terraform-oci-iam)

 module "My_compartments" {

  source   = "./modules/iam-compartment"
  #tenancy_ocid           = var.tenancy_ocid            # optional
  compartment_id          = var.comp_id                 # Parent compartment 
  compartment_name        = var.comp_name
  compartment_description = var.comp_description
  compartment_create      = true 
  enable_delete           = true 

}

 

What you need to know about modules

  • Registry Modules

    • One single resource block per module: you’ll have as many folders as module blocks

    • Even if you use for_each loop say i=10, you will have 10 downloads under .terraform folder

    • You depend on the maintainer’s goodwill for code sanity/integrity checks

  • Local Modules

    • Reuse a single instance of the module for all your module calls, including dynamic blocks

    • Code-proofing responsibility against new updates falls on you

 

Conclusion:

  • This goes to show how important it is to keep the code up-to-date and compatible, especially for tf modules

  • Whether you choose a local or 3rd party module, there are positives and negatives as with all things

  • Due diligence is always welcome to decide if the code is high quality, secure, and is maintained

  • The same is just as true for modules you make yourself

  • There’s a style of Terraform programming where people try to make everything a module. Some consider this to be an antipattern

  • As for me, I’m glad I always tried tuning with dynamic blocks and locals to reduce my code footprint first

Share on:

More from this Author

OCI FortiGate HA Cluster – Reference Architecture Code Review and Fixes

OCI FortiGate HA Cluster – Reference Architecture: Code Review and Fixes

Introduction OCI Quick Start repositories on GitHub are collections of Terraform scripts and configurations provided by Oracle. These repositories ... Read More

What Autoupgrade Won’t Catch for You when Moving to 19c Part1 Ghost OLAP

What Autoupgrade Won’t Catch for You when Moving to 19c Part1: Ghost OLAP

Introduction So far, I have used Oracle AutoUpgrade, many times in 3 different OS’. Yet the more you think you’ve seen it all and reached the ... Read More

Back to Top