Reputation: 2752
I am trying to create few storage account and some containers in each account. I need to create this as a module so that I can reuse it. The way that I am thinking to do this is by creating a variable such as
storageaccounts = [
{
name = "testbackupstorage11"
containers = ["logs", "web", "backups"]
},
{
name = "testbackupstorage12"
containers = ["logs-1", "web-1"]
}
]
I've created the following code. However, I think this line
count = length(var.storageaccounts.*.containers)
is giving me error. I want to loop through the storageaccount array, get the containers and assign the 'length' of the containers key to the 'count' inside the 'azurerm_storage_container' so that this block creates multiple storage account.
However, this doesn't work as expected, most likely because of * I also tested with
count = length(var.storageaccounts[count.index].containers)
when I do this, I get the error
on ..\modules\storage\main.tf line 21, in resource "azurerm_storage_container" "this":
21: count = length(var.storageaccounts[count.index].containers)
The "count" object can be used only in "resource" and "data" blocks, and only
when the "count" argument is set.
How can I accomplish this? Or is there any better way?
Here is the full code.
resource "random_id" "this" {
count = length(var.storageaccounts)
keepers = {
storagename = 1
}
byte_length = 6
prefix = var.storageaccounts[count.index].name
}
resource "azurerm_storage_account" "this" {
count = length(var.storageaccounts)
name = substr(lower(random_id.this[count.index].hex), 0, 24)
resource_group_name = var.resourcegroup
location = var.location
account_tier = "Standard"
account_replication_type = "LRS"
}
resource "azurerm_storage_container" "this" {
count = length(var.storageaccounts.*.containers)
name = var.storageaccounts[count.index].containers[count.index]
storage_account_name = azurerm_storage_account.this[count.index].name
container_access_type = "private"
}
provider "random" {
version = "2.2"
}
locals {
storageaccounts = [
{
name = "testbackupstorage11"
containers = ["logs", "web", "backups"]
},
{
name = "testbackupstorage12"
containers = ["logs-1", "web-1"]
}
]
}
module "storage" {
source = "../modules/storage"
resourcegroup = "my-test"
location = "eastus"
storageaccounts = local.storageaccounts
}
provider "azurerm" {
version = "=2.0.0"
features {}
}
//variable "prefix" {}
variable "location" {}
variable "resourcegroup" {}
variable "storageaccounts" {
default = []
type = list(object({
name = string
containers = list(string)
}))
}
Upvotes: 0
Views: 18753
Reputation: 83
length(var.storageaccounts.*.containers)
Your count doesn't make sense, you asking for a list of storageaccounts with the attribute containers. So it would be looking for
[
{
name = "testbackupstorage11"
containers = ["logs", "web", "backups"]
},
{
name = "testbackupstorage12"
containers = ["logs-1", "web-1"]
}
].containers
Try using a locals to merge all into one list:
locals{
storageaccounts = [for x in var.storageaccounts: x.containers]
} // Returns list of lists
Then
count = length(flatten(local.storageaccounts)) //all one big list
https://www.terraform.io/docs/configuration/functions/flatten.html
Sorry, not had a chance to test the code, but I hope this helps.
Upvotes: 0
Reputation: 195
count = length(var.storageaccounts.*.containers)
will return the length of var.storageaccounts
which is 2.
count = length(var.storageaccounts[count.index].containers)
would fail because you can't reference something that hasn't been declared.
What you can do is flatten the lists.
For example:
variables.tf
variable "storageaccounts" {
default = []
type = list(object({
name = string
containers = list(string)
}))
}
main.tf
resource "null_resource" "cluster" {
count = length(flatten(var.storageaccounts.*.containers))
provisioner "local-exec" {
command = "echo ${flatten(var.storageaccounts.*.containers)[count.index]}"
}
}
variables.tfvars
storageaccounts = [
{
name = "testbackupstorage11"
containers = ["logs", "web", "backups"]
},
{
name = "testbackupstorage12"
containers = ["logs-1", "web-1"]
}
]
The plan
terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.
------------------------------------------------------------------------
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# null_resource.cluster[0] will be created
+ resource "null_resource" "cluster" {
+ id = (known after apply)
}
# null_resource.cluster[1] will be created
+ resource "null_resource" "cluster" {
+ id = (known after apply)
}
# null_resource.cluster[2] will be created
+ resource "null_resource" "cluster" {
+ id = (known after apply)
}
# null_resource.cluster[3] will be created
+ resource "null_resource" "cluster" {
+ id = (known after apply)
}
# null_resource.cluster[4] will be created
+ resource "null_resource" "cluster" {
+ id = (known after apply)
}
Plan: 5 to add, 0 to change, 0 to destroy.
------------------------------------------------------------------------
This plan was saved to: /path/plan
To perform exactly these actions, run the following command to apply:
terraform apply "/path/plan"
The application
terraform apply
/outputs/basics/plan
null_resource.cluster[1]: Creating...
null_resource.cluster[4]: Creating...
null_resource.cluster[3]: Creating...
null_resource.cluster[0]: Creating...
null_resource.cluster[2]: Creating...
null_resource.cluster[3]: Provisioning with 'local-exec'...
null_resource.cluster[1]: Provisioning with 'local-exec'...
null_resource.cluster[4]: Provisioning with 'local-exec'...
null_resource.cluster[0]: Provisioning with 'local-exec'...
null_resource.cluster[2]: Provisioning with 'local-exec'...
null_resource.cluster[3] (local-exec): Executing: ["/bin/sh" "-c" "echo logs-1"]
null_resource.cluster[2] (local-exec): Executing: ["/bin/sh" "-c" "echo backups"]
null_resource.cluster[4] (local-exec): Executing: ["/bin/sh" "-c" "echo web-1"]
null_resource.cluster[1] (local-exec): Executing: ["/bin/sh" "-c" "echo web"]
null_resource.cluster[0] (local-exec): Executing: ["/bin/sh" "-c" "echo logs"]
null_resource.cluster[2] (local-exec): backups
null_resource.cluster[2]: Creation complete after 0s [id=3936346761857660500]
null_resource.cluster[4] (local-exec): web-1
null_resource.cluster[3] (local-exec): logs-1
null_resource.cluster[0] (local-exec): logs
null_resource.cluster[1] (local-exec): web
null_resource.cluster[4]: Creation complete after 0s [id=3473332636300628727]
null_resource.cluster[3]: Creation complete after 0s [id=8036538301397331156]
null_resource.cluster[1]: Creation complete after 0s [id=8566902439147392295]
null_resource.cluster[0]: Creation complete after 0s [id=6115664408585418236]
Apply complete! Resources: 5 added, 0 changed, 0 destroyed.
The state of your infrastructure has been saved to the path
below. This state is required to modify and destroy your
infrastructure, so keep it safe. To inspect the complete state
use the `terraform show` command.
State path: terraform.tfstate
Upvotes: 0