Reputation: 365
There is issue with command line input for any string attribute inside a map/object variable. the below configuration works with below command. But the moment I use any string attribute inside the object variable. it fails
terraform plan -var='storageProfile2={"storage_mb":102400,"backup_retention_days":15,"geo_redundant_backup_enabled":false}'
//main.tf
resource "azurerm_postgresql_server" "dmcdevops_postgress" {
name = "pstgressdb101"
location = azurerm_resource_group.dmc_rg_creation.location
resource_group_name = azurerm_resource_group.dmc_rg_creation.name
sku_name = "GP_Gen5_4"
backup_retention_days = var.storageProfile2.backup_retention_days
storage_mb = var.storageProfile2.storage_mb
geo_redundant_backup_enabled = var.storageProfile2.geo_redundant_backup_enabled
administrator_login = "sdfgsgfsg"
administrator_login_password = "H@Sh1CoR3!"
version = "11"
ssl_enforcement_enabled = true
}
//variables.tf
variable "storageProfile2" {
default = {
storage_mb = 102400
backup_retention_days = 15
geo_redundant_backup_enabled = false
}
type = object(
{
storage_mb = number
backup_retention_days = number
geo_redundant_backup_enabled = bool
}
)
}
Below config doesn't work. I just added administrator_login as string attribute to the object variable. terraform plan and apply works with default values tho.
terraform plan -var='storageProfile2={"storage_mb":102400,"backup_retention_days":15,"geo_redundant_backup_enabled":false,"administrator_login":"pgadmin1223"}'
//main.tf
resource "azurerm_postgresql_server" "dmcdevops_postgress" {
name = "pstgressdb101"
location = azurerm_resource_group.dmc_rg_creation.location
resource_group_name = azurerm_resource_group.dmc_rg_creation.name
sku_name = "GP_Gen5_4"
backup_retention_days = var.storageProfile2.backup_retention_days
storage_mb = var.storageProfile2.storage_mb
geo_redundant_backup_enabled = var.storageProfile2.geo_redundant_backup_enabled
administrator_login = var.storageProfile2.administrator_login
administrator_login_password = "H@Sh1CoR3!"
version = "11"
ssl_enforcement_enabled = true
}
//varibale.tf
variable "storageProfile2" {
default = {
storage_mb = 102400
backup_retention_days = 15
geo_redundant_backup_enabled = false
administrator_login = "pgadmin"
}
type = object(
{
storage_mb = number
backup_retention_days = number
geo_redundant_backup_enabled = bool
administrator_login = string
}
)
}
Error message
Upvotes: 7
Views: 42094
Reputation: 365
As pointed out by Martin . The issue was regarding unix style shell on power shell. After escaping the double quotes, it worked. Correct syntax for power shell is
terraform plan -var='postgress={"storage_mb":102400,"backup_retention_days":15,"geo_redundant_backup_enabled":false,"administrator_login":\"pgadmin1223\"}'
Also, I agree its better to use tfvars instead of input params especially if you have lot of inputs to terraforms
Upvotes: 1
Reputation: 21686
Since the second config works with the defaults for the variable, the config isn't the issue, the terraform apply -var
must be the issue. It's a very tricky thing to get right and has a number of problematic interactions with shell parsing rules that can trip you up.
I find using .tfvars files far more reliable and I no longer try to get -var working for my Terraform work.
terraform.tfvars:
storageProfile2 = {
storage_mb = 102400
backup_retention_days = 15
geo_redundant_backup_enabled = false
administrator_login = "pgadmin1223"
}
Ceate terraform.tfvars as above in the same directory and then run terraform plan
and terraform apply
without -var. It should resolve your issue.
There are several significant changes in the azurerm provider that are intended to be backwards compatible, but are likedly causing the issue here.
geo_redundant_backup is a deprecated attribute as of v2.7.0 or v2.10.0 depending on which database resource you are using. You should use geo_redundant_backup_enabled instead and specify it as boolean (bool type). I suspect the backwards-compatibility isn't completely reliable.
storage_profile blocks are also deprecated and all of their attributes are now top-level on the corresponding.
The examples in the azurerm provider documentation using storage_profile
are incorrect and this:
storage_profile {
storage_mb = var.storageProfile2.storageMb
backup_retention_days = var.storageProfile2.backupRetentionDays
geo_redundant_backup = var.storageProfile2.geoRedundantBackup
}
Should be rewritten as (direct properties on the resource, not inside a block):
storage_mb = var.storageProfile2.storageMb
backup_retention_days = var.storageProfile2.backupRetentionDays
geo_redundant_backup_enabled = var.storageProfile2.geoRedundantBackup
And your storageProfile2 variable declaration should be updated to set the type of geoRedundantBackup to bool:
variable storageProfile2 {
default = {
storageMb = 102400
backupRetentionDays = 15
geoRedundantBackup = false
}
type = object({ storageMb=number, backupRetentionDays=number, geoRedundantBackup=bool })
}
Since azurerm provider v2.7.0 was released on April 23rd, 2020 including these changes:
- azurerm_postgres_server - all properties in the
storage_profile
block have been moved to the top level (#6459)- azurerm_postgres_server - the following properties were renamed and changed to a boolean type:
ssl_enforcement
tossl_enforcement_enabled
,geo_redundant_backup
tobackup_geo_redundant_enabled
, andauto_grow
toauto_grow_enabled
(#6459)
Since azurerm provider v2.10.0 was released on May 12th, 2020 additional storage_profile were flattened:
- azurerm_mariadb_server - all properties in the
storage_profile
block have been moved to the top level (#6865)- azurerm_mysql_server - all properties in the
storage_profile
block have been moved to the top level (#6833)- azurerm_mariadb_server - the following properties were renamed and changed to a boolean type:
ssl_enforcement
tossl_enforcement_enabled
,geo_redundant_backup
togeo_redundant_backup_enabled
, andauto_grow
azurerm_mysql_server
- support for thecreate_mode
property allowing the creation of replicas, point in time restores, and geo restors (#6833)- azurerm_mysql_server - the following properties were renamed and changed to a boolean type:
ssl_enforcement
tossl_enforcement_enabled
,geo_redundant_backup
togeo_redundant_backup_enabled
, andauto_grow
toauto_grow_enabled
(#6833)
Conventional code style in Terraform:
snake_case
instead of camelCase
(not formalized, but every provider follows this as do the examples)variable "storage_profile_2" {
default = {
storage_mb = 102400
backup_retention_days = 15
geo_redundant_backup_enabled = false
}
type = object(
{
storage_mb = number
backup_retention_days = number
geo_redundant_backup_enabled = bool
}
)
}
And assign attributes as follows
storage_mb = var.storage_profile_2.storage_mb
backup_retention_days = var.storage_profile_2.backup_retention_days
geo_redundant_backup_enabled = var.storage_profile_2.geo_redundant_backup_enabled
The more consistent Terraform code is globally, the easier it will be for all of us practitioners should we ever need to work on someone else's code.
Upvotes: 4