Problem getting value from helm_release output

Terraform version:

Terraform v0.12.6
+ provider.external v1.2.0
+ provider.helm v0.10.4
+ provider.rancher2 v1.6.0

I have this resource in my rancher module:

resource "helm_release" "rancher" {
  name       = "rancher"
  namespace  = "cattle-system"
  repository = data.helm_repository.rancher_repo.metadata[0].name
  chart      = "${data.helm_repository.rancher_repo.metadata[0].name}/rancher"
  version    = var.rancher_chart_version
  set {
    name  = "letsEncrypt.environment"
    value = var.letsencrypt_env
  }
  set {
    name  = "hostname"
    value = var.rancher_dns
  }
  set {
    name  = "ingress.tls.source"
    value = var.rancher_ssl
  }
  set {
    name  = "letsEncrypt.email"
    value = var.notification_email
  }
}

I want to create an output to use the var.rancher_dns.
Creating an output like this

output "rancher_url" {
  value = helm_release.rancher
}

will give me an output like this:

rancher_url = {
  "chart" = "rancher-stable/rancher"
  "disable_webhooks" = false
  "force_update" = false
  "id" = "rancher"
  "metadata" = [
    {
      "chart" = "rancher"
      "name" = "rancher"
      "namespace" = "cattle-system"
      "revision" = 1
      "values" = "hostname: RANCHER_URL\ningress:\n  tls:\n    source: letsEncrypt\nletsEncrypt:\n  email: MY_MAIL\n  environment: staging\n"
      "version" = "2.3.2"
    },
  ]
  "name" = "rancher"
  "namespace" = "cattle-system"
  "recreate_pods" = false
  "repository" = "rancher-stable"
  "reuse" = false
  "reuse_values" = false
  "set" = [
    {
      "name" = "hostname"
      "value" = "RANCHER_URL"
    },
    {
      "name" = "ingress.tls.source"
      "value" = "letsEncrypt"
    },
    {
      "name" = "letsEncrypt.email"
      "value" = "MY_MAIL"
    },
    {
      "name" = "letsEncrypt.environment"
      "value" = "staging"
    },
  ]
  "set_sensitive" = []
  "set_string" = []
  "status" = "DEPLOYED"
  "timeout" = 300
  "verify" = false
  "version" = "2.3.2"
  "wait" = true
}

Okay, but how do I get the actual url?

I tried this:

output "rancher_url" {
  value = lookup(helm_release.rancher,"set")
}

which will give me this output:

rancher_url = [
  {
    "name" = "hostname"
    "value" = "MY_URL"
  },
  {
    "name" = "ingress.tls.source"
    "value" = "letsEncrypt"
  },
  {
    "name" = "letsEncrypt.email"
    "value" = "MY_MAIL"
  },
  {
    "name" = "letsEncrypt.environment"
    "value" = "staging"
  },
]

From here on I have no idea how to proceed.

I tried different functions like element, index but I think I do not understand the structure yet.

Thanks for answering in advance.

Hi @ajfriesen!

I’m not personally familiar with Helm so I’m focusing only on the Terraform language parts of your question here and hoping that it will give you want you need to solve your broader problem.

It looks like what you are trying to do here is find the value attribute from the element of set that has name = "hostname". The way the schema for this resource type is defined makes that a little awkward, but not impossible. I think I’d approach it by first creating a local value that has the contents of that set collection projected into a map instead of a list, which should work as long as we can rely on the name values being unique across that collection:

locals {
  rancher_release_settings = {
    for obj in helm_release.rancher.set : obj.name => obj.value
  }
}

This local value will then be a map something like this:

{
  "hostname" = "RANCHER_URL"
  "ingress.tls.source": "letsEncrypt",
  # etc, etc ...
}

From your output value expression you an then access that individual hostname element:

output "rancher_url" {
  value = local.rancher_release_settings["hostname"]
}

Thanks for the reply.

I did found another way to get that information for the next module before I did read your answer.

But nonetheless I tried this as well but could not figure out how to use that.

I could create a map for the locals like this

locals {
  rancher_release_settings= {
    letsEncrypt.email = var.notification_email
    ingress.tls.source = var.rancher_ssl
    hostname = var.rancher_dns
    letsEncrypt.environment = var.letsencrypt_env
  }
}

But I do not know how to use that for loop in the helm command.