5 ms·
My biggest hope is that this means that some effort can be directed back to fixing bugs. I love what terraform can do, but I hate what I sometimes need to write
by bshacklett 7y ago
My biggest hope is that this means that some effort can be directed back to fixing bugs. I love what terraform can do, but I hate what I sometimes need to write to make it work.
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.
- kawsper 7y agoThe biggest issue we have with Terraform (and other Hashicorp tools in general, really) is their different configuration formats, but mostly it is HCL limitations. 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.
- solatic 7y agoYou can't write a local module for the resource that takes the differences as inputs?
- kawsper 7y agoMaybe I can, but I am failing to grasp how templates or the modules work, we have these resources where only the ami is different (and sometimes the count): 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.
- farzadb82 7y agoOne way I can think of that will solve this problem is to do something like: 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.
- vegardx 7y agoAlternatively you could put the AMIs in an array, and just iterate over that array. 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)}" ... }
- mhotchen 7y agoI personally would solve this issue with a local module (very easy to set up, just a subfolder with a main.tf that defines the resources[0] then it's called as here[1]) with two input variables[2]: a required ami variable, and an optional count variable which has a default of 3. I hope that helps. [0] https://www.terraform.io/docs/modules/index.html https://www.terraform.io/docs/modules/index.html [1] https://www.terraform.io/docs/modules/sources.html#local-paths https://www.terraform.io/docs/modules/sources.html#local-pat... [2] https://www.terraform.io/docs/configuration/variables.html https://www.terraform.io/docs/configuration/variables.html
- kitotik 7y agoHow does a var, template, or even a generic resource that runs a local script not solve this problem?
- ivan_ah 7y ago+1 for the question about a "standard" or recommended way to parse and generate .tf files from a script. 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 https://github.com/virtuald/pyhcl = reads .tf, can export .tf.json - https://github.com/kvz/json2hcl 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)
- robfig 7y agoYour favorite tool that produces json should be able to work. I'd probably use jsonnet, which has a multi-file mode so that one template file can render into many json files.
- crucialfelix 7y agoYou can actually use JSON files in place of HCL: https://www.terraform.io/docs/configuration/syntax-json.html https://www.terraform.io/docs/configuration/syntax-json.html main.tf.json
- kraig 7y agoIMO they should have dumped HCL once they caught a whiff of what Pulumi is up to, much rather go with actual languages that when you learn them, you pick up some valued knowledge. You can also do a whole lot more with Typescript than you can with HCL 2.
- argd678 7y agoAgreed, the data model of Terraform simply doesn’t match the problem domain. You need an algorithm to codify the pattern and then data to fill in the params. Terraform doesn’t allow you to create the patterns you need in a way that’s debugable and doesn’t allow for code reuse. For simple setups it’s not apparent there’s a problem but when they get more complex it’s nearly impossible to use. 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.
- dvtrn 7y agoI wouldn’t say it becomes impossible to use at scale, what happens at scale with terraform, but rather the opinionated nature of HCL makes itself present in ways you probably won’t ever have to deal with if you’re shepherding very small fleets or single serving resources. 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.
- oneplane 7y agoThe Terraform language extension in VSCode is very good.
- org3432 7y agoIt's not good, it doesn't understand the TF types and recommends values that are invalid for the context, there's no inline help (you have to go look it up on the website), refactoring a variable name doesn't fully work, and you can't set breakpoints or trace through the execution to determine what's going on... I mean it's practically in the mid-80s, although most of those things worked even back then. 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.