Terraform: Access attribute of an array element

I’ve declared a data source that points to a Kubernetes Pod.

data "kubernetes_pod" "nginx-template" {
  metadata {
    name = "nginx-template"
    namespace = "terraform"
  }
}

Now I want to access the Kubernetes Pod’s spec.containers[0].image property, and use that to populate another Terraform resource dynamically.

resource "kubernetes_deployment_v1" "deploy-nginx" {
  provider = kubernetes.cluster-dev

  metadata {
    name = "nginx"
    labels = {
      dev-owner = "TrevorSullivan"
    }
    namespace = "terraform"
  }

  spec {
    replicas = 2
    selector {
      match_labels = {
        pod_name = "nginx"
      }
    }
    template {
      metadata {
        labels = {
          pod_name = "nginx"
        }
      }
      spec {
        container {
          name = "nginx"
          image = data.kubernetes_pod.nginx-template.spec.container[0].image
        }
      }
    }
  }
}

However, I am getting an error message:

Can’t access attributes on a list of objects. Did you mean to access attribute “container” for a specific element of the list, or across all elements of the list?

:bulb: Question: How do I access the image property for the first container in a Pod?

I also tried this:

          image = one(data.kubernetes_pod.nginx-template.spec.container[*].image)

This seems to work, for some odd reason. The spec attribute should not be an array, because each Pod only has a single spec property. However, it appears that Terraform treats the spec property as an array, and therefore you must index into it. Seems like a bug to me.

image = data.kubernetes_pod.nginx-template.spec[0].container[0].image

Hi @pcgeek86,

The hashicorp/kubernetes provider seems to declare spec as being a list:

Therefore it’s correct that you would need to access specific elements of the list, but I agree it’s odd for this to be defined as a list if there is always exactly one element.

I expect this is a historical holdover from older versions of the provider that were built for earlier versions of Terraform that didn’t support single-instance nested block types yet. You could share this feedback with the provider development team by opening a feature request issue in their GitHub repository, although I think changing this would be a breaking change for existing users and so the provider team probably cannot change it immediately.


Incidentally, I think one can potentially work for this situation, if spec is defined as always having exactly one element, but the one would need to be applied to the spec attribute directly, like this:

  one(data.kubernetes_pod.nginx-template.spec).container[0].image

In this case though it’s shorter to just use [0] as you showed in your second comment, because you know there will always be one element present. one is intended for situations where a list might have either zero or one elements, to avoid an error in the case where there are zero elements.