2
votes

I have used Terragrunt to orchestrate the creation of a non-default AWS VPC. I've got S3/DynamoDB state mgmt, and the VPC code is a module. I have the 'VPC environment' terraform.tfvars code checked into a second repo as per the terragrunt README.md.

I created a second module which will eventually create hosts in this VPC but for now just aims to output its ID. I have created a separate 'hosts environment' / terraform.tfvars for the instantiation of this module.

  1. I run terragrunt apply in the VPC environment directory - VPC created
  2. I run terragrunt apply a second time in the hosts environment directory - output directive doesn't work (no error, but incorrect, see below).

This is a precursor to one day running a terragrunt apply-all in the parent directory of the VPC/hosts environment directories; my reading of the docs suggest using a terraform_remote_state data source to expose the VPC ID, so I specified access like this in the data.tf file of the hosts module:

data "terraform_remote_state" "vpc" {
    backend = "s3"
    config {
        bucket  = "myBucket"
        key     = "keyToMy/vpcEnvironment.tfstate"
        region  = "stateRegion"
    }
}

Then, in the hosts module outputs.tf, I specified an output to check assignment:

output "mon_vpc" {
    value = "${data.terraform_remote_state.vpc.id}"
}

When I run (2) above, it exits with:

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

mon_vpc = 2018-06-02 23:14:42.958848954 +0000 UTC

Questions:

  1. I'm going wrong setting up the code so that the hosts environment is configured to correctly acquire the VPC ID from the already-existing VPC (terraform state file) - any advice on what to change here would be appreciated.

  2. It does look like I've managed to acquire the date of when the VPC was created rather than its ID, which given the code is perplexing - anyone know why?

I'm not using community modules - all hand rolled.

EDIT: In response to Brandon Miller, here is a bit more. In my VPC module, I have an outputs.tf containing among other outputs:

output "aws_vpc.mv.id-op" {
    value = "${aws_vpc.mv.id}"
}

and the vpc.tf contains

resource "aws_vpc" "mv" {
    cidr_block = "${var.vpcCidr}"
    enable_dns_support = true
    enable_dns_hostnames = true
    tags = {
        Name = "mv-vpc-${var.aws_region}"
    }
}

As this cfg results in a vpc being created, and as most of the parameters are <computed>, I assumed state would contain sufficient data for other modules to refer to by consulting state (I assumed at first that terraform used the AWS API for this under the bonnet, rather than consulting a different state key).

EDIT 2: Read all of @brendan-miller's answer and following comments first. Use of periods causes a problem as it confuses terraform (see Brendan's answer for the specification format below):

Error: output 'mon_vpc': unknown resource 'data.aws_vpc.mv-ds' referenced in variable data.aws_vpc.mv-ds.vpc.id
1
How are you declaring the output for your vpc in the remote state?Brandon Miller
@brandon-miller I've edited the post to reflect my declarations. Let me know if that answers your question.volvox
thanks, hopefully my helps clear things upBrandon Miller

1 Answers

1
votes

You named your output aws_vpc.mv.id-op but when you retrieve it you are retrieving just id. You could try

data.terraform_remote_state.vpc.aws_vpc.mv.id

but im not sure if Terraform will complain about the additional .. However the format should always be

data.terraform_remote_state.<name of the remote state module>.<name of the output>

You mentioned wanting to be able to get this info with the AWS API. That is also possible by using the aws_vpc data source. Their example uses id, but you can also use any tag you used on your vpc.

Like this:

data "aws_vpc" "default" {
  filter {
    name   = "tag:Name"
    values = ["example-vpc-name"]
  }
}

Then you can use this for the id

${data.aws_vpc.default.id}

In addition this retrieves all tags set, for example:

${data.aws_vpc.default.tags.Name}

And the cidr block

${data.aws_vpc.default.cidr_block}

As well as some other info. This can be very useful for storing and retrieving things about your VPC.