Background - I have been asked to take 5 Azure SQL servers off the public network and place them onto private endpoints. The SQL Servers are used by an application in a container within Kubernetes.
I am confident the network is in place as intended. The problem is that the application is still connecting to the old FQDNs not the FQDNs of the private endpoints. My understanding is that the hostname used by the application is generated by the Kubernetes secret resource below and this comes from an output in another project via a remote state file.
I am creating the following DNS records in one state file and have set and output like so:
variable "dns_records" {
default = {
"btarget" = "172.16.102.4"
"public-0" = "172.16.102.5"
"public-1" = "172.16.102.6"
"public-2" = "172.16.102.7"
}
}
resource "azurerm_private_dns_a_record" "dns-records" {
for_each = var.dns_records
name = each.key
records = [each.value]
resource_group_name = "${var.application_name}-${var.environment_tag}-rg"
ttl = 3600
zone_name = azurerm_private_dns_zone.dns-zone.name
}
output "sql_admin_fqdns" {
description = "FQDNs of all other SQL Servers"
sensitive = false
value = { for entry in azurerm_private_dns_a_record.dns-records : entry.name => entry.fqdn }
}
I am then calling the FQDN value from another project with a different state file like this:
data "terraform_remote_state" "staged_azure" {
backend = "azurerm"
config = {
subscription_id = var.tf_state_subscription_id
resource_group_name = var.tf_state_rg_name
storage_account_name = var.tf_state_sa_name
container_name = var.tf_state_container_name
key = var.tf_state_staged_azure_key
access_key = var.tf_state_access_key
}
}
resource "kubernetes_secret" "cms_database" {
metadata {
name = join("-", [var.application_name, "database", each.key])
namespace = kubernetes_namespace.magnolia.id
}
data = {
username = each.value
password = data.terraform_remote_state.staged_azure.outputs.sql_admin_passwords[each.key]
hostname = data.terraform_remote_state.staged_azure.outputs.sql_admin_fqdns[each.key].fqdn
schema = data.terraform_remote_state.staged_azure.outputs.sql_admin_schemas[each.key]
port = 1433
resource-group = data.terraform_remote_state.staged_azure.outputs.sql_admin_rg
}
for_each = data.terraform_remote_state.staged_azure.outputs.sql_admin_usernames
}
When running the plan on the second project it is not getting the correct value from the output in the other project:
Error: Unsupported attribute
│
on tomcat.tf line 59, in resource "kubernetes_secret" "bca_cms_database":
59: hostname = data.terraform_remote_***.staged_azure.outputs.sql_admin_fqdns[each.key].fqdn
│ ├────────────────
data.terraform_remote_***.staged_azure.outputs.sql_admin_fqdns is object with 4 attributes
each.key is "public-2"
│
Can't access attributes on a primitive-typed value (string).
I've tried so many different approaches and the data source never pulls through the correct value even though I can see the correct value is being output from the source project
I am expecting the Kubernetes Secret resource to grab the FQDNS of the private DNS records from the output in the remote state project and inject them into the container.
I posted on the Reddit Terraform sub and they said that hashicorp recommends avoiding referencing remote states and that I should access the data from Azure directly using an Azure Data Source. I've not been able to figure out how to do this yet.
The Kubernetes secret resource was working fine when it was pulling the FQDNs from the SQL servers on the public network.
You got an error because you tried to access
.fqdnon a string value, instead of an object with afqdnattribute. This is because your outputsql_admin_fqdnsis a map of FQDNs, and when you access a map element, you get the FQDN string, not an object.The error can be resolved by changing the way you refer to the FQDNs in your
kubernetes_secretresource. You can omit the.fqdnattribute when accessing the values of thesql_admin_fqdnsmap, as they are already strings.Although using remote state references is common, it can lead to tight coupling between Terraform projects. As suggested, using Azure data sources directly in your Terraform configuration to fetch the necessary information about the SQL servers can be a more decoupled approach.
My terraform configuration:
Output: