TerraformPilot

Infrastructure as Code

Terraform Kubernetes Provider v3.4.0: kubernetes_role_v1 Breaking Changes and Plugin Framework Migration

Terraform Kubernetes provider v3.4.0 moves kubernetes_role_v1 to Plugin Framework, rejects name+generate_name, fixes CVEs. Upgrade notes inside.

LLuca Berton3 min read

Introduction

#

HashiCorp released v3.4.0 of the hashicorp/terraform-provider-kubernetes provider on October 16, 2026. This release migrates kubernetes_role_v1 from SDKv2 to the Plugin Framework, introduces two breaking validation changes for that resource, and patches dependencies to resolve three vulnerabilities. Teams managing RBAC Role resources with Terraform should read the upgrade notes carefully before running terraform apply.

What Is New

#

Breaking change: name and generate_name are now mutually exclusive

#

Previously, kubernetes_role_v1 accepted both metadata.name and metadata.generate_name in the same block, even generate_name = "", despite the Kubernetes API ignoring generate_name whenever name is set. As of v3.4.0, setting both is rejected at plan time (GH-2964).

Configurations that previously looked like this will now fail plan:

resource "kubernetes_role_v1" "example" {
  metadata {
    name          = "pod-reader"
    generate_name = ""
    namespace     = "default"
  }
 
  rule {
    api_groups = [""]
    resources  = ["pods"]
    verbs      = ["get", "list", "watch"]
  }
}

To keep the existing Role in place, drop the empty generate_name:

resource "kubernetes_role_v1" "example" {
  metadata {
    name      = "pod-reader"
    namespace = "default"
  }
 
  rule {
    api_groups = [""]
    resources  = ["pods"]
    verbs      = ["get", "list", "watch"]
  }
}

Removing name instead and keeping generate_name will replace the Role, since the resource identity changes.

Breaking change: null no longer allowed in labels/annotations

#

metadata.labels and metadata.annotations on kubernetes_role_v1 no longer accept null values. Earlier versions silently dropped null entries; now the provider rejects them during plan (GH-2964).

resource "kubernetes_role_v1" "example" {
  metadata {
    name      = "pod-reader"
    namespace = "default"
 
    labels = {
      "app.kubernetes.io/managed-by" = "terraform"
      # team = null  # remove any null-valued entries
    }
  }
 
  rule {
    api_groups = [""]
    resources  = ["pods"]
    verbs      = ["get"]
  }
}

Remove any null-valued map entries, or omit the key entirely, before upgrading.

Plugin Framework migration for kubernetes_role_v1

#

kubernetes_role_v1 has been migrated from SDKv2 to the Plugin Framework. Configuration syntax and resource identity are preserved, including upgrades from provider versions that predate identity support. moved blocks from the deprecated kubernetes_role resource continue to work, but require Terraform 1.8 or later.

A few one-time, non-destructive side effects are expected after upgrading (GH-2964):

  • Explicit empty metadata maps may trigger a one-time in-place update.
  • Roles imported with an earlier provider version may show a one-time in-place update that sets empty labels/annotations to null.
  • Running terraform plan -refresh=false immediately after upgrading may show a one-time in-place update adding resource_names = [].
  • Identity imports default an omitted namespace to default.
  • Import IDs now require a non-empty namespace and name.

None of these in-place updates replace the Role. Review the Plugin Framework upgrade guide linked from the release notes if the resource was imported or managed under an older provider version.

Bug fix: CVE remediation

#

The provider bumps google.golang.org/grpc to v1.83.2 and github.com/moby/spdystream to v0.5.1, resolving GO-2026-6348, GO-2026-6443, and CVE-2026-35469 (GH-2986). This is a good reason to upgrade even for teams not touching kubernetes_role_v1 directly.

Upgrade Steps

#
  1. Audit every kubernetes_role_v1 resource for generate_name set alongside name (including empty strings) and for null entries in labels/annotations. Fix configurations as shown above.
  2. Pin the provider version constraint:
terraform {
  required_providers {
    kubernetes = {
      source  = "hashicorp/kubernetes"
      version = "~> 3.4.0"
    }
  }
}
  1. Re-initialize:
terraform init -upgrade
  1. Run a plan without refresh first to spot the expected one-time diffs mentioned above:
terraform plan -refresh=false
  1. Run a full plan and review carefully before applying:
terraform plan

If Terraform is older than 1.8 and moved blocks reference the deprecated kubernetes_role resource, upgrade Terraform first or those blocks will not work as expected.

Verify

#

Confirm the provider version in use and that the plan shows no unexpected replacements:

terraform providers
terraform apply

After apply, check that any kubernetes_role_v1 resources did not get recreated (no -/+ in the plan output) and that labels/annotations in state match the intended configuration, not null.

Conclusion

#

v3.4.0 is a mandatory review for anyone managing kubernetes_role_v1 resources: the name/generate_name validation and the null-rejection in labels/annotations will break plans that previously worked silently. The underlying Plugin Framework migration is otherwise transparent, aside from a few expected one-time diffs. The gRPC and spdystream bumps make this release worth picking up regardless, given the CVE fixes.

#Terraform#Kubernetes Provider#HashiCorp#Plugin Framework#Terraform Upgrade#CVE

Share this article