<p>I am using Terraform with Kubernetes Provider.
Now when creating <em>ConfigMap</em>s, I want their names to have a content suffix. 
Usually it is a hash of the content.</p>

<p>This way, it should enforce a Deployment, where used.</p>

<p>So I would like it to work similar to:</p>

<pre><code>resource "kubernetes_config_map" "prometheus_config" {
  metadata {
    name      = "prometheus-" + computeHash(file("${path.module}/alerts.yml"), file("${path.module}/recordings.yml"), "abcd")
  }

  data = {
    "foo" = file("${path.module}/alerts.yml")
    "bar" = file("${path.module}/recordings.yml")
    "txt" = "abcd"
  }
}
</code></pre>

<p>Is there any way of implementing a custom function like <code>computeHash</code>?
Or to achieve this another way?</p>

abergmeier
<p>The <a href="https://www.terraform.io/docs/providers/kubernetes/r/config_map.html" rel="nofollow noreferrer"><code>kubernetes_config_map</code> resource</a> returns a <a href="https://www.terraform.io/docs/providers/kubernetes/r/config_map.html#resource_version" rel="nofollow noreferrer"><code>resource_version</code> attribute as part of the metadata</a>. As described in the linked docs:</p>

<blockquote>
  <p>An opaque value that represents the internal version of this config map that can be used by clients to determine when config map has changed. For more info see <a href="https://github.com/kubernetes/community/blob/e59e666e3464c7d4851136baa8835a311efdfb8e/contributors/devel/api-conventions.md#concurrency-control-and-consistency" rel="nofollow noreferrer">Kubernetes reference</a></p>
</blockquote>

<p>You can use this to trigger a deploy by interpolating based on this value in your <a href="https://www.terraform.io/docs/providers/kubernetes/r/deployment.html" rel="nofollow noreferrer"><code>kubernetes_deployment</code> resource</a> directly.</p>

<p>I personally put the value into an environment variable in the container spec which then triggers the deployment to redeploy when the config map changes. Tweaking the example given in the <code>kubernetes_deployment</code> docs this gives:</p>

<pre><code>resource "kubernetes_deployment" "example" {
  metadata {
    name = "terraform-example"
    labels = {
      test = "MyExampleApp"
    }
  }

  spec {
    replicas = 3

    selector {
      match_labels = {
        test = "MyExampleApp"
      }
    }

    template {
      metadata {
        labels = {
          test = "MyExampleApp"
        }
      }

      spec {
        container {
          image = "nginx:1.7.8"
          name  = "example"

          env = [
            {
              name  = "configmap"
              value = "${kubernetes_config_map.example.metadata.0.resource_version}"
            },
          ]

          resources {
            limits {
              cpu    = "0.5"
              memory = "512Mi"
            }
            requests {
              cpu    = "250m"
              memory = "50Mi"
            }
          }

          liveness_probe {
            http_get {
              path = "/nginx_status"
              port = 80

              http_header {
                name  = "X-Custom-Header"
                value = "Awesome"
              }
            }

            initial_delay_seconds = 3
            period_seconds        = 3
          }
        }
      }
    }
  }
}
</code></pre>

<p>It is worth noting that this approach currently has the unfortunate behaviour of requiring 2 <code>apply</code>s to trigger the deployment as Terraform only sees a change to the config map in the first <code>apply</code> but then a follow up <code>plan</code> will show that the deployment spec's container <code>env</code> has changed and this triggers a deployment. I've not dug into this enough to see why the Kubernetes provider works this way as Terraform should be able to see that the deployment is dependent on the config map and that is going to change.</p>
