It's a bit disconcerting when one of the BIG aspects of the Terraform 0.12 release is some support for preliminary types.
Pulumi just uses Typescript.
I'm not entirely sure why Terraform is going in the direction of reinventing the wheel when it can leverage stuff out there.
Additionally you have to rewrite everything for each cloud provider, so it just expands the work required, all with no real IDE integration. I’d just write against the cloud provider APIs directly or look at Pulumi when they get interactive debugging.
Then, I needed to launch infra in GCP and I messed around with terraform unsuccessfully for a few days before writing about 10 lines of gcloud CLI commands into a makefile.
Now I just check a makefile into my project and just break things up into little shell scripts.
Solved so many problems and headaches.
If there wasn't a chip on my shoulder telling me I had to use what the next person would expect else as a contractor I risk being seen as unprofessional I'd do it in a heartbeat.
I've never used Terraform but CloudFormation just seems to suck, the documentation is poor and relatively few people are sharing their stack files. I've lost count of the number of times I've hit an error only to find Google hasn't heard of it.
Personally I’m excited that loop operations now exist in 0.12
But thanks for the reference to Pulumi, had not heard of this and it looks very interesting.
The lesson here is that if you plan on making a language, even a DSL, you want to be sure you're really up for it since it's a lot of work.
I haven't found a solution for it, but I have lots of resources that are almost identical, except for a few arguments, but right now it seems like my options are to either write my own Ruby script to output .hcl files, or live with two resources that are almost identical, and live with the mistakes that could entail by future modifications.
I haven't had the time to look into HCL2 yet, but maybe it is solved.
I have two use cases in mind: Use case 1: need to have a reproducible way to generate terraform folders for multiple almost-identical deployments (this can be solved via modules) Use case 2: need way to "promote" a deployment from staging to production (load a .tf file, change a few basic params then save again to a different folder --- doesn't really work with templates since I want to load an existing .tf file)
One thing that might work is to use the combination of two tools: - https://github.com/virtuald/pyhcl = reads .tf, can export .tf.json - https://github.com/kvz/json2hcl = convert .tf.json to .tf but feels hacky...
Any other recommendations for .tf parsing and generation? (preferably in python or scriptable via python)
main.tf.json
resource "aws_instance" "nomadclients_tick" {
ami = "${data.aws_ami.nomadclient_tick.image_id}"
instance_type = "t2.micro"
count = 3
iam_instance_profile = "${aws_iam_instance_profile.consul-join.name}"
subnet_id = "${element(aws_subnet.consul.*.id, count.index)}"
vpc_security_group_ids = [
"${aws_security_group.rule01.id}",
"${aws_security_group.rule02.id}",
"${aws_security_group.rule03.id}",
"${aws_security_group.rule04.id}",
]
}
resource "aws_instance" "nomadclients_tock" {
ami = "${data.aws_ami.nomadclient_tock.image_id}"
instance_type = "t2.micro"
count = 3
iam_instance_profile = "${aws_iam_instance_profile.consul-join.name}"
subnet_id = "${element(aws_subnet.consul.*.id, count.index)}"
vpc_security_group_ids = [
"${aws_security_group.rule01.id}",
"${aws_security_group.rule02.id}",
"${aws_security_group.rule03.id}",
"${aws_security_group.rule04.id}",
]
}
The examples I have found feels very difficult.[0] https://www.terraform.io/docs/modules/index.html
[1] https://www.terraform.io/docs/modules/sources.html#local-pat...
[2] https://www.terraform.io/docs/configuration/variables.html
resource "aws_instance" "nomadclients" {
ami = "${count.index > 2 ? data.aws_ami.nomadclient_tick.image_id : data.aws_ami.nomadclient_tock.image_id}"
instance_type = "t2.micro"
count = 6
iam_instance_profile = "${aws_iam_instance_profile.consul-join.name}"
subnet_id = "${element(aws_subnet.consul.*.id, count.index)}"
vpc_security_group_ids = [
"${aws_security_group.rule01.id}",
"${aws_security_group.rule02.id}",
"${aws_security_group.rule03.id}",
"${aws_security_group.rule04.id}",
]
}
The downside to this approach (in TF < 0.12), however, will become apparent when you want to modify the number of instances in one or both pools. This arrises from the way hcl v1 manages the counter index with each resource in the state; That is each resource is linked to a specific index and when that index is altered in someway, terraform will attempt to adjust the resources at each respective index accordingly.Because of these headaches, we decided to abandon hcl for these use cases and ended up writing our own preprocessor that takes a JSON configuration and generates individual JSON-based HCL (ie. .json.tf) that terraform can then use. We can leverage proper templating to generate many variants of a single resource in a higher level language, while still using terraform to manage the infrastructure and it only adds one additional step to the plan + apply process.
locals {
nomad_ami = [
"${data.aws_ami.nomadclient_tick.image_id}",
"${data.aws_ami.nomadclient_tock.image_id}",
]
}
resource "aws_instance" "nomadclients" {
count = 6
ami = "${element(local.nomad_ami, count.index)}"
...
}
Also, I'll go out on a limb and say that I dislike the flexibility of iteration allowed in HCL 2. I know that people overwhelmingly asked for it, but my opinion is that it demonstrates a fundamental misunderstanding of how the v. 11 and earlier system was designed, and just how powerful completely declarative code can be.