hashicorp / terraform-provider-kubernetes

Terraform Kubernetes provider
https://www.terraform.io/docs/providers/kubernetes/
Mozilla Public License 2.0
1.59k stars 974 forks source link

`kubernetes_manifest` always shows changes in `creationTimestamp` #1652

Closed torbendury closed 2 months ago

torbendury commented 2 years ago

Terraform Version, Provider Version and Kubernetes Version

Terraform version: v1.1.7
Kubernetes provider version: 2.8.0
Kubernetes version: v1.22.1 (okd)

Affected Resource(s)

Terraform Configuration Files

locals {
  crd_version = "v1.15.1"
  crds = [
    "https://raw.githubusercontent.com/fission/fission/${local.crd_version}/crds/v1/fission.io_canaryconfigs.yaml",
    "https://raw.githubusercontent.com/fission/fission/${local.crd_version}/crds/v1/fission.io_environments.yaml",
    "https://raw.githubusercontent.com/fission/fission/${local.crd_version}/crds/v1/fission.io_functions.yaml",
    "https://raw.githubusercontent.com/fission/fission/${local.crd_version}/crds/v1/fission.io_httptriggers.yaml",
    "https://raw.githubusercontent.com/fission/fission/${local.crd_version}/crds/v1/fission.io_kuberneteswatchtriggers.yaml",
    "https://raw.githubusercontent.com/fission/fission/${local.crd_version}/crds/v1/fission.io_messagequeuetriggers.yaml",
    "https://raw.githubusercontent.com/fission/fission/${local.crd_version}/crds/v1/fission.io_packages.yaml",
    "https://raw.githubusercontent.com/fission/fission/${local.crd_version}/crds/v1/fission.io_timetriggers.yaml",
  ]
}

data "http" "fission-crd" {
  for_each = toset(local.crds)
  url      = each.key
}

resource "kubernetes_manifest" "fission-crd" {
  for_each = { for http in data.http.fission-crd : http.url => http }
  manifest = { for k, v in yamldecode(each.value.body) : k => v if !(length(regexall("status", k)) > 0) }
}

Debug Output

none so far, unsure if needed

Panic Output

none so far

Steps to Reproduce

  1. insert above block and create the resources
  2. run a terraform plan afterwards

Expected Behavior

Since nothing has changed in the YAML manifests, I expect the terraform plan to exit without showing changes

Actual Behavior

Terraform always wants to modify the resource:

  # kubernetes_manifest.fission-crd["https://raw.githubusercontent.com/fission/fission/v1.15.1/crds/v1/fission.io_messagequeuetriggers.yaml"] will be updated in-place
  ~ resource "kubernetes_manifest" "fission-crd" {
      ~ object   = {
          ~ metadata   = {
              ~ creationTimestamp          = null -> (known after apply)
                # (15 unchanged elements hidden)
            }
            # (3 unchanged elements hidden)
        }
        # (1 unchanged attribute hidden)
    }

  # kubernetes_manifest.fission-crd["https://raw.githubusercontent.com/fission/fission/v1.15.1/crds/v1/fission.io_packages.yaml"] will be updated in-place
  ~ resource "kubernetes_manifest" "fission-crd" {
      ~ object   = {
          ~ metadata   = {
              ~ creationTimestamp          = null -> (known after apply)
                # (15 unchanged elements hidden)
            }
            # (3 unchanged elements hidden)
        }
        # (1 unchanged attribute hidden)
    }

  # kubernetes_manifest.fission-crd["https://raw.githubusercontent.com/fission/fission/v1.15.1/crds/v1/fission.io_timetriggers.yaml"] will be updated in-place
  ~ resource "kubernetes_manifest" "fission-crd" {
      ~ object   = {
          ~ metadata   = {
              ~ creationTimestamp          = null -> (known after apply)
                # (15 unchanged elements hidden)
            }
            # (3 unchanged elements hidden)
        }
        # (1 unchanged attribute hidden)
    }

Important Factoids

I'm running OKD 4.9, I did not have time yet to try and reproduce it e.g. on a GKE, AKS or something.

References

Community Note

alexsomesan commented 2 years ago

Hi! The problem here is that the provider strips creationTimestamp from all manifests because it's an attribute that produces unexpected diffs and it's not user actionable. You can try to resolve this issue by removing the creationTimestamp attribute from the object that you get out of yamldecode.

However, we recommend all our users to convert the yaml manifests to HCL offline, using the tfk8s tool. This is the preferred workflow for kubernetes_manifest as it allows full use of Terraform's HCL language to customize the resources before they are applied.

vladimirtiukhtin commented 2 years ago

@alexsomesan this does not apply to CRDs, doesn't it? What is an advice for CRD users?

jeffbeal-scale commented 2 years ago

I had a CRD written with an HCL map and was having this issue. The previous author had written creationTimestamp = null in the map; removing that fixed the issue:

resource "kubernetes_manifest" "originissuers_crd" {
  manifest = {
    apiVersion = "apiextensions.k8s.io/v1"
    kind       = "CustomResourceDefinition"
    metadata = {
      creationStamp = null #Removing this line and applying resolved the diff
      name = "originissuers.cert-manager.k8s.cloudflare.com"
    }
kierdavis commented 2 years ago

Can confirm that tfk8s emitted creationTimestamp = null lines when fed with some CRDs in YAML form, and that removing these lines and running a terraform apply made the spurious changes go away.

vlad-ivanov-name commented 1 year ago

For those using kustomization provider, you can hack your way around without manually editing the generated data structures with the following expression

  manifest = merge(
    { for k, v in each.value : k => v if k != "status" && k != "metadata" },
    contains(keys(each.value), "metadata") ?
      { metadata : { for m_k, m_v in each.value["metadata"] : m_k => m_v if m_k != "creationTimestamp" } } :
      {}
  )
TOTom commented 1 year ago

Hi, I encounter this question too. all my "CRD" need modification every time because of field "object.metadata.creationTimestamp". i also add " metadata.creationTimestamp" in the computed_field , but no help. hope this bug can be fixed soon.

~ resource "kubernetes_manifest" "prometheus_operator_crds" {

  ~ object          = {
      ~ metadata   = {
          + creationTimestamp          = (known after apply)
            name                       = "alertmanagerconfigs.monitoring.coreos.com"
            # (14 unchanged attributes hidden)
        }
        # (3 unchanged attributes hidden)
    }
    # (1 unchanged attribute hidden)
}
vladimirtiukhtin commented 1 year ago

As suggested by @alexsomesan, I converted yamls offline removing all occurrences of creationTimestamp and it worked. I guess having resources offline is the way forward and is in fact more robust

github-actions[bot] commented 3 months ago

Marking this issue as stale due to inactivity. If this issue receives no comments in the next 30 days it will automatically be closed. If this issue was automatically closed and you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. This helps our maintainers find and focus on the active issues. Maintainers may also remove the stale label at their discretion. Thank you!