Let me first start out by saying that I currently have a working terraform configuration, however my IDE (VSCode; using the mauve.terraform extension, v 1.3.12) complains about my syntax when I do something like:
virtual_machine_name = "${azurerm_virtual_machine.sql["${count.index}"].name}"
It complains that it's expecting a '}' but found a '.'.
Should I be writing this out differently, or in a more "correct" manner? I'm fairly new to working with terraform so I'm sure my syntax could use some help.
Thanks in advance!
For reference, here's my full resource block:
resource "azurerm_virtual_machine_extension" "sql" {
name = "OMSExtension"
location = "${data.azurerm_resource_group.generics_sql_dev.location}"
resource_group_name = "${data.azurerm_resource_group.generics_sql_dev.name}"
virtual_machine_name = "${azurerm_virtual_machine.sql["${count.index}"].name}"
publisher = "Microsoft.EnterpriseCloud.Monitoring"
type = "MicrosoftMonitoringAgent"
type_handler_version = "1.0"
auto_upgrade_minor_version = true
count = "${var.sql_node_count}"
settings = <<-BASE_SETTINGS
{
"workspaceId" : "${data.azurerm_log_analytics_workspace.oms.workspace_id}"
}
BASE_SETTINGS
protected_settings = <<-PROTECTED_SETTINGS
{
"workspaceKey" : "${data.azurerm_log_analytics_workspace.oms.primary_shared_key}"
}
PROTECTED_SETTINGS
}
From Terraform 0.12 and later, the "standard" way to write that is:
virtual_machine_name = azurerm_virtual_machine.sql[count.index].name
What you tried would also work in Terraform 0.12, but the string interpolations are redundant in that version. It works in Terraform 0.12 because of a special backward-compatibility rule that if a quoted string sequence consists only of a single interpolation (like "${ ...anything ... }") then Terraform will ignore the quotes and just return the inner expression value directly.
That's only supported for backward-compatibility with configurations written for Terraform 0.11 and so I'd recommend avoiding it if you are using Terraform 0.12 or later; it tends to hurt readability by leaving a reader wondering if it implies conversion to a string.
For Terraform 0.11 and earlier, one level of string interpolation is required and indexing must be against a "splat operator":
virtual_machine_name = "${azurerm_virtual_machine.sql.*.name[count.index]}"
The azurerm_virtual_machine.sql.*.name part here produces a list of name values, and then [count.index] selects one of them. This approach is required in Terraform 0.11 and earlier because in those versions the index operator [...] must always come at the end of a sequence of traversal steps.
Related
I am trying to define a resource but Terraform complains
resource "aws_cloudwatch_event_target" "my-functions-order-machine-completion-target" {
target_id = "some target id"
rule = aws_cloudwatch_event_rule.my-functions-order-machine-completion-rule.name
arn = module.lambda["myLambda"].function_arn
}
error:
Quoted strings may not be split over multiple lines. To produce a multi-line
string, either use the \n escape to represent a newline character or use the
"heredoc" multi-line template syntax.
I saw Heredoc Strings but not sure how to use this after "resource"
Although not a great answer, shortening the name of the resource sorted out the issue for me.
I also tried interpolation syntax like so which did not work:
resource "resource" "${var.name}"
I'm trying to parse and configure a Terraform HCL configuration, using a script.
So far I've been using a tool named "hclq" (Link to github page).
Unfortunately, while this tool is great. When I have a conditional statement, such as:
resource "vault_identity_group" "group_a" {
count = terraform.workspace != "prod" ? 1 : 0
...
}
As documented by HashiCorp: Conditional Expressions
I tried encasing the condition as a literal:
count = ${terraform.workspace != "prod" ? 1 : 0}
But it seems that is no longer supported by Terraform.
Does anyone have any idea how can I get over this issue?
Thank you!
UPDATE: I've found an error in my literal, it should be encased in quotation marks:
count = "${terraform.workspace != var.prod ? 1 : 0}"
This way, the hclq tool can parse it as a string, I also had to switch the "prod" string with a variable, as the TF configuration does not support character escaping.
I Got a syntax problem with terraform:
Let me write some pseudo code to descript the problem as the line is a bit complicated:
I would like to have display_name equal to force_name when defined.
And if not defined I would like to have name_prefix**-01**
Now the -XX suffix is always added in both case, and I can't enclose it correctly to add it in the else clause.
What I tried:
I've tried many enclosing {} "" () in differents places.
resource "exoscale_compute" "generic" {
count = "${var.replicas}"
affinity_groups = "${var.affinity_group}"
disk_size = "${var.disk_size}"
display_name = "${var.force_name != "" ? var.force_name : var.name_prefix}-${format("%02d", count.index + var.replicas_index_start) }
The issue:
The output is always forcedname**-01** or nameprefix**-01**
What I'd like would be:
forcedname or nameprefix-01
Could you help ?
Thanks
You can nest the interpolation, so the 2nd option for the ?: operator becomes another string with more interpolation:
display_name = "${var.force_name != "" ? var.force_name : "${var.name_prefix}-${format("%02d", count.index + var.replicas_index_start)}" }
Terraform provides excellent documentation for displaying outputs including AWS.
output "ip" {
value = "${aws_eip.ip.public_ip}"
}
That would in term provide something like
ip = 50.17.232.209
what I would like to get if possible is something like:
public_ip = x.x.x.x and private_ip = y.y.y.y
in one line as opposed to separate items. I have tried something like this:
output "public ip and private ip" {
value = "${aws_eip.ip.public_ip}"
value = "${aws_eip.ip.private_ip}"
}
Currently, It's working if I split them up like this:
output "public_ip" {
value = "${aws_eip.ip.public_ip}"
}
output "private_ip" {
value = "${aws_eip.ip.private_ip}"
}
Thanks
The following should work, although splitting them up probably makes most sense:
output "public ip and private ip" {
value = "public_ip = ${aws_eip.ip.public_ip} and private_ip = ${aws_eip.ip.private_ip}"
}
Maybe you have to tune it a bit to have the formatting as you prefer, but I hope that my answer at least shows that there is nothing special compared to string interpolation somewhere else..
Terraform v0.12.13
+ provider.aws v2.43.0
+ provider.null v2.1.2
Your version of Terraform is out of date! The latest version
is 0.12.18. You can update by downloading from www.terraform.io/downloads.html
Error: Invalid output name
on outputs.tf line 1, in output "public and private":
1: output "public and private" {
A name must start with a letter and may contain only letters, digits,
underscores, and dashes.
I am having trouble in variable interpolation in terraform. Here is what my terraform configuration looks like. i.e variable inside builtin function
variable "key" {}
ssh_keys {
path = "/home/${var.provider["user"]}/.ssh/authorized_keys"
key_data = "${file(${var.key})}"
}
Command: terraform apply -var 'key=~/.ssh/id_rsa.pub'
It's not reading the value of "key" from command line argument or from env variable. However when i hardcore the value in .tf file, it works. Like below.
key_data = "${file("~/.ssh/id_rsa.pub")}"
The ${ ... } syntax is only used when embedding an expression into a quoted string. In this case, where your var.key variable is just being passed as an argument to a function already within a ${ ... } sequence, you can just reference the variable name directly like this:
key_data = "${file(var.key)}"
Nested ${ ... } sequences are sometimes used to pass an interpolated string to a function. In that case there would first be a nested set of quotes to return to string context. For example:
key_data = "${file("${path.module}/${var.key_filename}")}"
In this more complicated case, the innermost string expression is first evaluated to join together the two variables with a /, then that whole string is passed to the file function, with the result finally returned as the value of key_data.
It doesn't work because you were using the wrong flag for the scenario you described above.
If you want to specify a path to a file use the "-var-file" flag as follow:
terraform apply -var-file=~/.ssh/id_rsa.pub
If you must use the "-var" flag then you must specify the content of the file as follow:
terraform apply -var 'key=contenctOFPublicKey'
ssh_keys - (Optional) Specifies a collection of path and key_data to be placed on the virtual machine.
Note: Please note that the only allowed path is /home/<username>/.ssh/authorized_keys due to a limitation of Azure.
refer: AZURERM_VIRTUAL_MACHINE