Terraform module output variable as input for another module using variables

Advertisements

I am trying to pass output of StorageAccount and App Service Plan output values to Function App module. However I am not able to figure it out how to manage the variable.tf for root and child module

Here is my code in detailed to understand better

terraform.tfvars

#Resource Group
resourcegroupname = "eus-dev-test-rg"
asp-resourcegroupname = "eus-dev-shared-asp-rg"
location          = "eastus"

#Storage Account
storageaccountname = "euspftestsa001"

#App Servicen Plan
serviceplanname = "eus-dev-shared-asp-01"
ostype = "Windows"
sku = "Y1"

#Function App
functionappname = "eus-dev-test-fnapp-02"
stack_version = { node = "~14" }

main.tf

module "ResourceGroup" {
  source            = "../../modules/ResourceGroup"
  resourcegroupname = var.resourcegroupname
  location          = var.location
}

module "ASP-ResourceGroup" {
  source            = "../../modules/ResourceGroup"
  resourcegroupname = var.asp-resourcegroupname
  location          = var.location
}

module "ApplicationServicePlan" {
  source            = "../../modules/ApplicationServicePlan"
  resourcegroupname = module.ASP-ResourceGroup.rg_name_out
  serviceplanname   = var.serviceplanname
  location          = var.location
  ostype            = var.ostype
  sku               = var.sku
}

module "NODE_WA_StorageAccount" {
  source             = "../../modules/StorageAccount"
  storageaccountname = var.storageaccountname
  resourcegroupname  = module.ResourceGroup.rg_name_out
  location           = var.location
}

module "FunctionApp" {
  depends_on                 = [module.ResourceGroup, module.NODE_WA_StorageAccount, module.ApplicationServicePlan]
  source                     = "../../modules/FunctionApp/mrf"
  resourcegroupname          = module.ResourceGroup.rg_name_out
  location                   = var.location
  service_plan_id            = module.ApplicationServicePlan.app_sp_out
  storageaccountname         = module.NODE_WA_StorageAccount.sa_name_out
  storage_account_access_key = module.NODE_WA_StorageAccount.sa_primary_access_key_out
  functionappname            = var.functionappname
  stack_version              = var.stack_version
}

variables.tf

variable "resourcegroupname" {
  type        = string
}

variable "asp-resourcegroupname" {
  type        = string
}

variable "location" {
  type        = string
}

variable "storageaccountname" {
    type = string
}

variable "serviceplanname" {
  type = string
}

variable "ostype" {
  type = string
}

variable "sku" {
  type = string
}


variable "stack_version" {
  type = map
}

variable "functionappname" {
 type = string 
}

Modules code

Resource Group module

main.tf

resource "azurerm_resource_group" "rg" {
  name     = var.resourcegroupname
  location = var.location
}

variable.tf

variable "resourcegroupname" {
  type        = string
}

    variable "location" {
      type        = string
    }
    
    variable "tags" {
      type        = map(string)
    }

output.tf

output "rg_name_out" {
  value = azurerm_resource_group.rg.name
}

Storage Account module

main.tf

resource "azurerm_storage_account" "storageaccount" {
      name                     = var.storageaccountname
      resource_group_name      = var.resourcegroupname
      location                 = var.location
      account_tier             = "Standard"
      account_replication_type = "LRS"
    }

variable.tf

variable "resourcegroupname" {
  type        = string
  description = "The name of the resource group"
}

variable "location" {
  type        = string
  description = "resources should deploy only on 'eastus' as per the policy"
}

variable "storageaccountname" {
    type = string
    description = "The name of the Storage Account name"  
}

output.tf

output "sa_primary_access_key_out"{
    value = azurerm_storage_account.storageaccount.primary_access_key
}
output "sa_name_out"{
    value = azurerm_storage_account.storageaccount.name
}

Azure Function App Module

main.tf

resource "azurerm_windows_function_app" "win-fn" {
  name                = var.functionappname
  resource_group_name = var.resourcegroupname
  location            = var.location

  storage_account_name       = var.storageaccountname
  storage_account_access_key = primaryaccesskey
  service_plan_id            = serviceplanid

  site_config {
    ftps_state = "FtpsOnly"
    application_stack {
      node_version = lookup(var.stack_version, "node", null)
      java_version = lookup(var.stack_version, "java", null)
    }
  }
}

variable.tf

variable "resourcegroupname" {
  type        = string
  description = "The name of the resource group"
}

variable "location" {
  type        = string
  description = "resources should deploy only on 'eastus' as per the policy"
}

variable "functionappname" {
  type = string
  description = "location for the  iwallet resources"

}

variable "storageaccountname"{
  type = string 
  description = "The name of the WebApp SKU"
}

variable "stack_version" {
  type = map
}

ERROR while executing the terraform plan

╷
│ Error: Unsupported argument
│
│   on main.tf line 55, in module "FunctionApp":
│   55:   service_plan_id = module.ApplicationServicePlan.app_sp_out
│
│ An argument named "service_plan_id" is not expected here.
╵
╷
│ Error: Unsupported argument
│
│   on main.tf line 59, in module "FunctionApp":
│   59:   storage_account_access_key = module.NODE_WA_StorageAccount.sa_primary_access_key_out
│
│ An argument named "storage_account_access_key" is not expected here.

>Solution :

You have to define additional two variables in the FunctionApp module. The root module does not automatically map the values of the variables to the arguments in the child module. In other words, arguments storage_account_access_key and service_plan_id are unknown to the root module. To fix this, you just need to define the two variables in the FunctionApp variables.tf:

variable "service_plan_id" {
  type        = string
  description = "Service Plan ID."
}

variable "storage_account_access_key" {
  type        = string
  description = "Storage account access key."
}           

Then, in the child module FunctionApp, change this:

resource "azurerm_windows_function_app" "win-fn" {
  name                = var.functionappname
  resource_group_name = var.resourcegroupname
  location            = var.location

  storage_account_name       = var.storageaccountname
  storage_account_access_key = var.storage_account_access_key # <--- reference to the new variable
  service_plan_id            = var.service_plan_id # <--- reference to the new variable

  site_config {
    ftps_state = "FtpsOnly"
    application_stack {
      node_version = lookup(var.stack_version, "node", null)
      java_version = lookup(var.stack_version, "java", null)
    }
  }
}

Think of module variables as inputs to functions in programming languages. If you try to pass the value to an undefined variable that will not work. The same logic applies here. Any input you want to provide to a module you have to define. Then, that input must have a value. You can either set it to a default one when defining the variable or leave it undefined and provide it when calling the module.

Leave a ReplyCancel reply