1

I've seen Terraform workspaces recommended for managing different stages (staging, production). That seems to work well with most things as you generally create different resources that have the stage/workspace in the name or, if it's a shared resource, you import it into each workspace state.

However, I'm not sure how I should proceed with API Gateways. This type of resource can't be imported in the state which means if you create it in staging, you have to delete it and re-import it in production.

How do you deal with stages and API Gateways?

  • My team is struggling with a similar problem. I'm curious if you found any good solutions? We have separate AWS accounts for "production" and "everything else", so one thing we are considering is separating Terraform into a "per environment" module and "per account" module, so things like API Gateway which are shared across environments (basically, anything that is global to the account regardless of number of environments) goes into a separate Terraform state. – Jarrod Carlson Dec 19 '18 at 23:33
  • @JarrodCarlson Nothing we found was entirely satisfactory. The Terraform model is not compatible with how some AWS resources were intended to be used. In the end, we decided to just setup different gateways for staging and production. Seems redundant but we'd rather take that, than risk affecting our production environment by mistake. We did the same thing for Lambda functions. – Cristian Vrabie Dec 22 '18 at 12:13

2 Answers2

2

Use "count" and "splat syntax". "splat syntax" is "*" in front of variable. (e.g. shared_resource.example.*.id) When using this syntax, terraform doesn't get an error using resource that is not created because of count:0. I think, this is like a bug.

For example

In the first step, CI job uses development workspace, then the shared resource is created. In the following example, a aws_api_gateway_rest_api resource named "example" is created. Next, using production workspace, the resource is not created but terraform read the data of "aws_api_gateway_rest_api.example".

# this resource is created when using development workspace
resource "aws_api_gateway_rest_api" "example" {
    count = "${terraform.workspace == "development" ? 1 : 0}"
    name  = "this is example"
}

data "aws_api_gateway_rest_api" "example" {
    count = "${terraform.workspace == "production" ? 1 : 0}"
    name  = "this is example"
}

Using the resource, you must specify the resource value as following.

resource "sample_resource" "example" {
    rest_api_id = "${terraform.workspace == "production" ? join("", data.aws_api_gateway_rest_api.example.*.id) : join("", aws_api_gateway_rest_api.example.*.id)}"
}
komatta
  • 21
  • 1
  • I upvoted this but now regret. I don't like thtat this says "this is like a bug". I think a separate shared resources backend as in https://stackoverflow.com/a/52608146/4971151 is the way to go. – samlaf Feb 23 '23 at 19:38
0

First, Tfstate Should Be Stored in Remote. multiple backend available

Terraform starts with a single workspace named "default".

Setup S3 as backend backend.tf

terraform {
  backend "s3" {
    region = "eu-south-1"
    bucket = "backend.terraform"
    key = "state.tfstate"

  }
}

It’s recommended to enable versioning for state files. Push local state to S3

terraform state push

Create workspace

 terraform workspace new dev

Created and switched to workspace 'dev'

 terraform workspace new preprod

Select the dev workspace:

terraform workspace select dev

now once you applied terraform apply your tfstate file will be store in S3

Then call a variable depending on the current workspace

bucket = "${terraform.workspace == "prod" ? var.bucket_demo_prod : var.bucket_demo}"
sanjayparmar
  • 633
  • 8
  • 19
  • 1
    I don't think this answers the question at all. We do use a remote state and know how to create workspaces. As mentioned in the original question, we are actually using workspaces quite successfully. The question is how to share an AWS resource between these workspace states (API gateway in particular), when that resource is not really designed to be shared. – Cristian Vrabie Aug 30 '18 at 11:57