python-terrascript
python-terrascript copied to clipboard
Accessing attributes inside a Terrascript configuration
Nitish Kumar Yadav on LinkedIn Hi Markus, Needed one help, I have a terraform and need to convert that to terrascript, but facing problems as the resources are having nested variables
provider "aws" {
access_key = "AWS_ACCESS_KEY"
secret_key = "AWS_SECRET_KEY"
region = "ap-south-1"
}
resource "aws_key_pair" "test_keypair" {
key_name="id_rsa.pub"
public_key = "${file("/home/cloud_user/.ssh/id_rsa.pub")}"
}
resource "aws_instance" "test_instance" {
ami = "ami-2ed19c41"
instance_type = "t2.micro"
key_name= "id_rsa.pub"
connection {
user = "ec2-user"
private_key = "${file("/home/cloud_user/.ssh/id_rsa")}"
}
provisioner "remote-exec" {
inline = [
"touch ~/provisioned",
"sudo yum install -y httpd"
]
}
tags {
Name = "Terraform provisioner test instance"
}
}
output "public_ip" {
value = "${aws_instance.test_instance.public_ip}"
}
import terrascript as ts
import terrascript.aws.r as r
ts.provider("aws", access_key="ACCESS_KEY", secret_key="SECRET_KEY", region="ap-south-1")
keypair = r.key_pair("test_keypair", key_name="id_rsa.pub",
public_key=ts.function.file("/home/cloud_user/.ssh/id_rsa.pub"))
conn = ts.connection(user="ec2_user",
private_key=ts.function.file("/home/cloud_user/.ssh/id_rsa"))
prov = ts.provisioner("remote-exec", inline=["touch ~/provisioned",
"sudo yum install -y httpd"])
inst = r.instance("test_instance", ami="ami-2ed19c41", instance_type="t2.micro",
key_name="id_rsa.pub",
connection=conn, provisioner=prov,
tags={"Name": "Terraform provisioner test instance"})
ts.output("public_ip", value=inst.public_ip)
print(ts.dump())
Hi @mjuenema,
I believe this is a good place to ask this. I am trying to avoid assigning to local variables. Something like:
ts = Terrascript()
ts += d.vsphere_datacenter('dc1')
ts += d.vsphere_distributed_virtual_switch('dvs',
name="",
datacenter_id=ts.config.__getitem__('dc1'))
Ideally I would be able to reference data sources/resources already inside a Terrascript instance. I was looking into _Config__getitem__(key)
, but it isn't very straightforward to retrieve items.
Do you know of a way to achieve this currently, or should we always use local variables for this?
Thanks in advance!
Hi @austin-millan. I'd recommend to use Python variables to keep references to resources.
For the details of your question: the logic for referencing resources is implemented in the __repr__()
method (calling the interpolated
property) of the _base
class in terrascript/__init__.py
. But you should ignore all this and follow my advice below.
In release 0.5.1 I added the Terrascript.add()
method so one can do this.
ts = Terrascript()
dc1 = ts.add(d.vsphere_datacenter('dc1'))
ts.addd.vsphere_distributed_virtual_switch('dvs',
name="",
datacenter_id=dc1)
The .add()
method works like +
but also returns its original argument, i.e. dc1
will be a "vSphere datacenter". It also looks nicer than +
/+=
, especially since I just learned that +=
is not supported by all Python implementations.
Unfortunately documentation is quite behind as I have very limited time at the moment to work on this project. It's very nice to see though that other people find python-terrascript useful, proven by the bug reports and questions I get :-)
I changed the title to better reflect the content of this issue.
Dot-notation as implemented in https://pypi.org/project/python-box/ may be a nice approach here. I'd probably have to re-implement this myself as I am already "abusing" the attribute access methods.
I just realised that at least for read-only access, dot-notation already works. See the test_datasource_attributes()
method in https://github.com/mjuenema/python-terrascript/blob/develop/tests/test_data.py for an example.
Existing attributes are returned and accessing not (yet) existing ones creates a reference.
d = terrascript.data.aws_eip('external_ip', public_ip="1.2.3.4")
assert d.public_ip == "1.2.3.4"
assert d.unknown == 'data.aws_eip.external_ip.unknown'
Changing an existing attribute through dot-notation is not implemented but I am going to look into it.
TODO: Create a test case for Nitish's example.