« Back to Index

Terraform: Modules for structuring your resources

View original Gist on GitHub

Tags: #terraform #modules #fastly

Terraform Modules for structuring your resources.md

.
├── main.tf
├── modules
│   ├── compute.example.com
│   │   ├── main.tf
│   │   ├── package-built-locally-via-cli.tar.gz
│   │   └── provider.tf
│   └── www.example.com
│       ├── main.tf
│       ├── provider.tf
│       └── vcl
│           └── main.vcl
└── provider.tf

The provider.tf is the same file across the entire project, but we have to duplicate it as each module needs its own provider dependency graph (otherwise terraform init will fail).

IMPORTANT: if you use a ‘known’ provider (e.g. a hashicorp provider, like hashicorp/aws), then child modules don’t need to define those dependencies in a required_providers block. But as fastly/fastly isn’t a hashicorp provider (not any more it’s not; it used to be) it means we need a provider.tf in every child module. See https://www.terraform.io/docs/language/modules/develop/providers.html#implicit-provider-inheritance for details.

The package-built-locally-via-cli.tar.gz was something I generated using the Fastly CLI with fastly compute build.

NOTE: the use of path.module is documented here https://www.terraform.io/docs/language/expressions/references.html#filesystem-and-workspace-info

If using more providers and with more complex structuring (e.g. you reuse your modules), then it’s strongly recommended you implement a “module composition” approach to using Terraform modules, as this allows for greater flexibility and code reuse.

HashiCorp also provides their own guidelines on when to write a module.

compute-main.tf

resource "fastly_service_compute" "service" {
  name = "Compute Service"

  domain {
    name = "compute.example.com"
  }

  package {
    filename         = "${path.module}/package-built-locally-via-cli.tar.gz"
    source_code_hash = filesha512("${path.module}/package-built-locally-via-cli.tar.gz")
  }

  backend {
    address = "httpbin.org"
    name    = "httpbin"
  }

  force_destroy = true
}

main.tf

module "www" {
  source = "./modules/www.example.com"
}

module "compute" {
  source = "./modules/compute.example.com"
}

provider.tf

terraform {
  required_providers {
    fastly = {
      source  = "fastly/fastly"
      version = "0.27.0"
    }
  }
}

www-main.tf

resource "fastly_service_v1" "service" {
  name = "Example Service"

  domain {
    name = "www.example.com"
  }

  backend {
    address = "httpbin.org"
    name    = "httpbin"
  }

  vcl {
    content = file("${path.module}/vcl/main.vcl")
    main    = true
    name    = "custom_vcl"
  }

  force_destroy = true
}