python-terrascript
python-terrascript copied to clipboard
Variable string concatenation
I'm trying to perform string concatenation with variables, but are having some trouble to get it to work.
Actual Terraform:
variable "env_prefix" {
type = string
description = "my env prefix"
}
resource "azurerm_resource_group" "rg_demo" {
name = "${var.env_prefix}-infra-demo"
location = "North Europe"
}
Expected Terrascript:
import terrascript
script = terrascript.Terrascript()
env_prefix = script.add(terrascript.Variable("env_prefix", type="string", description="my env prefix"))
# Sorry for the convulated resource syntax, what is the proper way to do it?
script += type("azurerm_resource_group", (terrascript.Resource,), {})(
"rg_demo",
name=f"${{{env_prefix}}}-infra-demo",
location="North Europe",
)
print(script)
Expected result:
{
"variable": {
"env_prefix": {
"type": "string",
"description": "my env prefix"
}
},
"resource": {
"azurerm_resource_group": {
"rg_demo": {
"name": "${var.env_prefix}-infra-demo",
"location": "North Europe"
}
}
}
}
Actual result:
{
"variable": {
"env_prefix": {
"type": "string",
"description": "my env prefix"
}
},
"resource": {
"azurerm_resource_group": {
"rg_demo": {
"name": "${{'type': 'string', 'description': 'my env prefix'}}-infra-demo",
"location": "North Europe"
}
}
}
}
Without string interpolation during the assignmen (name=env_prefix,
, it gets almost right:
{
"variable": {
"env_prefix": {
"type": "string",
"description": "my env prefix"
}
},
"resource": {
"azurerm_resource_group": {
"rg_demo": {
"name": "var.env_prefix",
"location": "North Europe"
}
}
}
}
But should in fact be:
{
"resource": {
"azurerm_resource_group": {
"rg_demo": {
"name": "${var.env_prefix}",
"location": "North Europe"
}
}
}
}
Am I doing something wrong here, or is this simply a case which is not (yet) covered?
Using this class instead as Variable works:
import json
import terrascript
class Variable(terrascript.Variable):
def __repr__(self):
return f'var.{self._name}'
script = terrascript.Terrascript()
env_prefix = script.add(Variable("env_prefix", type="string", description="my env prefix"))
# Sorry for the convulated resource syntax, what is the proper way to do it?
script += type("azurerm_resource_group", (terrascript.Resource,), {})(
"rg_demo",
name=f"${{{env_prefix}}}-infra-demo",
location="North Europe",
)
print(env_prefix)
print(json.dumps(env_prefix, indent=2))
print(script)
Actual output:
var.env_prefix
{
"type": "string",
"description": "my env prefix"
}
{
"variable": {
"env_prefix": {
"type": "string",
"description": "my env prefix"
}
},
"resource": {
"azurerm_resource_group": {
"rg_demo": {
"name": "${var.env_prefix}-infra-demo",
"location": "North Europe"
}
}
}
}
Is this change something that would be desirable that I make tests and a PR for in Terrascript?
Also related to this, should Variable be represented by var._name
or ${var._name}
?
The later is what works when actually running the Terraform template, while the former requires you to manually surround it with ${}
: name=f'${{{my_var}}}'
.
Should be fixed in develop now.
Actually, this is not fixed.
I think that variables should ALWAYS be inserted as ${var.name}
instead of var.name
in the json.
I had the same problem, testing terrascript - 0.9.0
with terraform - 0.13.6
.
Here my case.
import terrascript
import terrascript.resource
from terrascript import Output
def ref(r):
return '${' + r + '}'
tf = terrascript.Terrascript()
tf += terrascript.terraform(
required_providers={
'tls': '~> 3.1.0'
}
)
tls_private_key = terrascript.resource.tls_private_key('linkerd_trust_anchor_key', **{
'algorithm': 'ECDSA',
'ecdsa_curve': 'P256'
})
tf += tls_private_key
tf += Output('private_key_pem_without_brackets', value=tls_private_key.private_key_pem)
tf += Output('private_key_pem_with_brackets', value=ref(tls_private_key.private_key_pem))
In the output, the reference to a atribute of a resource or data, also must have a ${ }
, not just variables.
The output private_key_pem_without_brackets
prints it's literal value and private_key_pem_with_brackets
prints the private_key.
I think that at the moment, the terrascript version 0.9.0 isn't usable without some tricks.
{
"terraform": {
"required_providers": {
"tls": "~> 3.1.0"
}
},
"resource": {
"tls_private_key": {
"linkerd_trust_anchor_key": {
"algorithm": "ECDSA",
"ecdsa_curve": "P256"
}
}
},
"output": {
"private_key_pem_without_brackets": {
"value": "tls_private_key.linkerd_trust_anchor_key.private_key_pem"
},
"private_key_pem_with_brackets": {
"value": "${tls_private_key.linkerd_trust_anchor_key.private_key_pem}"
}
}
}