Let's Play With Terraform External Providers

With Terraform, in order to use an existing resource in a new resource we want to create, we can use a data source. It's powerful and easy to understand and manipulate, but the thing to know is that you can't retrieve every data source type as you want. Indeed, several data source types can't be retrieved with filter, but several another can.

For example, you can retrieve an existing VPC by its tag name:

# VPC
data "aws_vpc" "vpc-dzone" {
  filter {
    name = "tag:Name"
    values = ["myvpc-for-dzone-article"]
 }
}


It's cool, useful, but unfortunately, this filtering is not possible for every resource.

In my case, I needed to retrieve an existing (network) load balancer, in AWS, and then give the information in order to create an AWS Route 53.

So the solution is to:

1. Create a script which retrieves the resource

2. Use the result of the script in a Terraform data source, with an external provider

3. Use this special data in the resource you want to create

1. The Script

my_module/scripts/get_elb.sh :

#!/bin/bash
set -e
kubectl get svc mygateway -n istio-system -o json | jq .status.loadBalancer.ingress[0]


This script returns a JSON object with a Kubernetes (Istio) gateway (which is an AWS Load Balancer):

$ ./my_module/scripts/get_elb.sh 
{
"hostname": "a123456789gsfgfsgfsg12134gsgsg78-123456789dfdsf45545fdsf.elb.eu-central-1.amazonaws.com"
}


2. The Data Source with Terraform External Provider

my_module/data.tf :

data"external""elb"{

     program= ["bash", "${path.module}/scripts/get_elb.sh"]

}


3. The Definition of Wanted Resource

my_module/aws_r53.tf:

resource "aws_route53_record""mymodule_CNAME" {
    zone_id="${data.aws_route53_zone.my_zone.zone_id}"
    name="${var.domain_name}"
    type="CNAME"
    records= ["${data.external.elb.result.hostname}"]
    ttl="${var.route53_ttl}"
}


Finally, apply your Terraform resources definition in order to create your resources.

You can now check providers used by Terraform in your project & modules:

$ terraform providers
.
├── provider.aws ~> 1.24.0
└── module.my_module
├── provider.aws (inherited)
└── provider.external


That's it!

 

 

 

 

Top