How to display public ip of ec2_instance after terraform creation - terraform

I would like to display the public_ip of aws_instance created by terraform after terraform execution.
However, only the global IP of the first server appears.
My source code is as follows.
resource "aws_instance" "main" {
count = "3"
...
}
output "ec2_global_ips" {
value = "${aws_instance.main.*.public_ip}"
}
Is something wrong grammar?
Let me know if you have to know how to display array values as output in terraform.

I believe this will work:
output "ec2_global_ips" {
value = ["${aws_instance.main.*.public_ip}"]
}

Related

How to select the value of a specific resource in tuple based on a property value?

Hello im struggling a little to solve this challenge and hope someone can provide insights. I need to pick a specific resource out of a tuple of those resources based on a property on that resource. How would one go about achieving something like that?
Code looks something like:
resource "aws_network_interface" "network_interface" {
for_each = var.counter_of_2
// stuff
}
resource "aws_network_interface_attachment" "currently_used_eni" {
instance_id = var.instance_id
network_interface_id = <the aws_network_interface with tag.Name = "thisone">
device_index = 0
}
Because tag is not ID of resource something like that would be impossible. Imagine if you have two network interfaces with same tag. Which one should it take?
But your case might be not lost. (yet it might... depends on case)
I assume that if you want to find specific aws_network_interface then tags are unique. And if they are unique then every network interface have different tag. So you can simply use something like that:
aws_network_interface.network_interface["value_from_for_each"]
For simplicity (and assuming that one network interface = one tag) I'll make this for_each collection to be set of tag names.
variable "interface_tags" {
type = set(string)
default = ["tag1", "tag2", "thisone"]
}
resource "aws_network_interface" "network_interface" {
for_each = var.interface_tags
// stuff
}
resource "aws_network_interface_attachment" "currently_used_eni" {
instance_id = var.instance_id
network_interface_id = aws_network_interface.network_interface["thisone"].id
device_index = 0
}
And this should work (and I hope it can be used in your case)

Cannot assign variable from data.tf to variables.tf file

New to terraform, and have been building out the infrastructure recently.
I am trying to pull secrets from azure key vault and assign the keys to the variables.tf file depending on the environment(dev.tfvars, test.tfvars, etc). However when I execute the plan with the tfvar file as the parameter, I get an error with the following message:
Error: Variables not allowed
Here are the files and the relevant contents of it.
variables.tf:
variable "user_name" {
type = string
sensitive = true
}
data.tf (referencing the azure key vault):
data "azurerm_key_vault" "test" {
name = var.key_vault_name
resource_group_name = var.resource_group
}
data "azurerm_key_vault_secret" "test" {
name = "my-key-vault-key-name"
key_vault_id = data.azurerm_key_vault.test.id
}
test.tfvars:
user_name = "${data.azurerm_key_vault_secret.test.value}" # Where the error occurrs
Can anyone point out what I'm doing wrong here? And if so is there another way to achieve such a thing?
In Terraform a variable can be used for user input only. You can not assign to them anything dynamically computed from your code. They are like read-only arguments, for more info see Input Variables from the doc.
If you want to assign a value to something for later use, you must use locals. For example:
locals {
user_name = data.azurerm_key_vault_secret.test.value
}
Local values can be changed dynamically during execution. For more info, see Local Values.
You can't create dynamic variables. All variables must have known values before execution of your code. The only thing you could do is to use local, instead of variabile:
locals {
user_name = data.azurerm_key_vault_secret.test.value
}
and then refer to it as local.user_name.

Terraform resource property dependent on creation of resource

Often, I've found myself in the scenario where I want to create a resource with Terraform and want to set, for example, an environment variable on this resource which is only known at a later stage, when the resource is created.
Let's say I want to create a google_cloud_run_service and want to set an environment variable in the container, that represents the url from which the app can be approached:
resource "google_cloud_run_service" "test_app" {
name = "test-app"
location = var.region
template {
spec {
containers {
image = "gcr.io/myimage:latest"
env {
name = "CURRENT_HOST"
value = google_cloud_run_service.test_app.status[0].url
}
}
}
}
}
This however is not allowed, as the service is not yet created. Is there a way to accomplish this?

Iterate over map with lists in terraform 0.12

I am using terraform 0.12.8 and I am trying to write a resource which would iterate over the following variable structure:
variable "applications" {
type = map(string)
default = {
"app1" = "test,dev,prod"
"app2" = "dev,prod"
}
}
My resource:
resource "aws_iam_user" "custom" {
for_each = var.applications
name = "circleci-${var.tags["ServiceType"]}-user-${var.tags["Environment"]}-${each.key}"
path = "/"
}
So, I can iterate over my map. However, I can't figure out how to verify that var.tags["Environment"] is enabled for specific app e.g. app1.
Basically, I want to ensure that the resource is created for each application as long as the Environment variable is in the list referencing app name in the applications map.
Could someone help me out here?
Please note that I am happy to go with a different variable structure if you have something to propose that would accomplish my goal.

Attempting to use list of stacks output as module output

I have a module that creates a variable number of CloudFormation Stacks. This works just fine but I am having problems attempting to use the Stack output as output in the module. The stack creates a subnet and I specify the created subnet id as an output of the stack. Then I want to return a list of all subnet ids as part of module output. This is what I think my output should look like:
output "subnets" {
value = ["${aws_cloudformation_stack.subnets.*.outputs["Subnet"]}"]
}
I get an integer parse error when I do that. Terraform seems to be treating outputs as a list instead of a map. Any way to get this to work?
Edit: Here is where I declare the stacks:
resource "aws_cloudformation_stack" "subnets" {
count = "${local.num_zones}"
name = "Subnet-${element(local.availability_zones, count.index)}"
on_failure = "DELETE"
template_body = "${file("${path.module}/templates/subnet.yaml")}"
parameters {
CIDR = "${cidrsubnet(var.cidr,ceil(log(local.num_zones * 2, 2)), count.index)}"
AZ = "${element(local.availability_zones, count.index)}"
VPC = "${aws_cloudformation_stack.vpc.outputs["VPCId"]}"
}
}
Then there is a Stack output in subnet.yaml that is has key Subnet and is the id of the subnet that was created.
The stacks are all created successfully but I can't seem to get exporting all the created subnet ids from my terraform module. Not sure why terraform is treating *.outputs as list vs keeping *.outputs["Subnet"] as the list. I'm guessing *.outputs is getting converted to a list of maps but I need a list of a specific key (Subnet) in the map.
I've got a non list example working for stack and using output from stack as terraform module output:
resource "aws_cloudformation_stack" "vpc" {
name = "${var.name_prefix}-VPC"
on_failure = "DELETE"
template_body = "${file("${path.module}/templates/vpc.yaml")}"
parameters {
CIDR = "${var.cidr}"
}
}
output "vpc" {
value = "${aws_cloudformation_stack.vpc.outputs["VPCId"]}"
}
I was able to work around the issue by declaring data to lookup the subnets after creation. It's not ideal but gets me passed being stuck. Let me know if anyone knows how to do what I was originally trying to do. Here is what I came up with:
data "aws_subnet_ids" "subnets" {
depends_on = ["aws_cloudformation_stack.subnets"]
vpc_id = "${aws_cloudformation_stack.vpc.outputs["VPCId"]}"
}
output "subnets" {
value = "${data.aws_subnet_ids.subnets.ids}"
}

Resources