Terraform external data source testing repo
Repository dedicated to a small test of the Terraform External Data Source.
The external data source allows an external program to be called from Terraform during state refresh implementing a specific protocol (JSON communication + an error exit in the case of no success)
Simple code to test our external data source :
# External data source example
#
variable "animal" {
# NO DEFAULT value on purpose, for the demo
}
data "external" "animal-getter" {
program = ["python", "${path.module}/cat-extractor.py"]
query = {
# find all animals with the required tag
tag = var.animal
}
}
resource "null_resource" "animal-echo" {
triggers = {
always_run = timestamp()
}
provisioner "local-exec" {
command = "echo ${data.external.animal-getter.result.name}"
}
}
Simple program in Python3 that is using built-in data, but could be extended to read that from some source, not available normally for Terraform.
This expects to read JSON from STDIN
and produce a resulting response as valid JSON map to STDOUT
.
In case of the fail - it should error and produce one-line error
As of now - JSON arrays in response are not supported ( 27/12/2021 )
#!/usr/bin/python3
# Animal extractor
import sys
import json
data = {}
data['animals'] = []
data['animals'].append({
'tag':'cat',
'name':'Tom'
})
data['animals'].append({
'tag':'dog',
'name':'Pluto'
})
data['animals'].append({
'tag':'vermin',
'name':'Jeez'
})
result={}
try:
arguments = json.load(sys.stdin)
except:
sys.exit('Error reading input arguments')
if 'tag' in arguments:
try:
result = json.dumps(next(filter(lambda animal: animal['tag']==arguments['tag'], data['animals'])))
except:
sys.exit('Tax extraction from data failed, perhaps there is no such tag : "'+arguments['tag']+'"')
print(result)
else:
sys.exit('Error, at least some "tag" of animal is expected like - cat, dog, vermin')
Let's get a "dog" from our data :
terraform apply --auto-approve -var="animal=dog"
null_resource.animal-echo: Refreshing state... [id=1442566978067270438]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated
with the following symbols:
-/+ destroy and then create replacement
Terraform will perform the following actions:
# null_resource.animal-echo must be replaced
-/+ resource "null_resource" "animal-echo" {
~ id = "1442566978067270438" -> (known after apply)
+ triggers = (known after apply) # forces replacement
}
Plan: 1 to add, 0 to change, 1 to destroy.
null_resource.animal-echo: Destroying... [id=1442566978067270438]
null_resource.animal-echo: Destruction complete after 0s
null_resource.animal-echo: Creating...
null_resource.animal-echo: Provisioning with 'local-exec'...
null_resource.animal-echo (local-exec): Executing: ["/bin/sh" "-c" "echo Pluto"]
null_resource.animal-echo (local-exec): Pluto
null_resource.animal-echo: Creation complete after 0s [id=7049043146374803735]
Apply complete! Resources: 1 added, 0 changed, 1 destroyed.
Let's now try to get a "cat" from our data :
terraform apply --auto-approve -var="animal=cat"
null_resource.animal-echo: Refreshing state... [id=7049043146374803735]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated
with the following symbols:
-/+ destroy and then create replacement
Terraform will perform the following actions:
# null_resource.animal-echo must be replaced
-/+ resource "null_resource" "animal-echo" {
~ id = "7049043146374803735" -> (known after apply)
~ triggers = {
- "always_run" = "2021-12-27T16:00:12Z"
} -> (known after apply) # forces replacement
}
Plan: 1 to add, 0 to change, 1 to destroy.
null_resource.animal-echo: Destroying... [id=7049043146374803735]
null_resource.animal-echo: Destruction complete after 0s
null_resource.animal-echo: Creating...
null_resource.animal-echo: Provisioning with 'local-exec'...
null_resource.animal-echo (local-exec): Executing: ["/bin/sh" "-c" "echo Tom"]
null_resource.animal-echo (local-exec): Tom
null_resource.animal-echo: Creation complete after 0s [id=2656677041203394027]
Apply complete! Resources: 1 added, 0 changed, 1 destroyed.
Seems to be valid, we got in return cat Tom, rather a traditional name for a feline character
How about if we request some gibberish? What will error look like?
terraform apply --auto-approve -var="animal=sd"
╷
│ Error: failed to execute "python": Tax extraction from data failed, perhaps there is no such tag : "sd"
│
│
│ with data.external.animal-getter,
│ on main.tf line 7, in data "external" "animal-getter":
│ 7: data "external" "animal-getter" {
│
╵
- make basic code
- test it
- update readme