hashicorp / terraform

Terraform enables you to safely and predictably create, change, and improve infrastructure. It is a source-available tool that codifies APIs into declarative configuration files that can be shared amongst team members, treated as code, edited, reviewed, and versioned.
https://www.terraform.io
Other
42.76k stars 9.56k forks source link

Error: Provider produced invalid plan - planned value `cty.ListValEmpty(cty.String)` does not match config value `cty.UnknownVal(cty.List(cty.String))` #35689

Closed oscarhermoso closed 2 months ago

oscarhermoso commented 2 months ago

Terraform Version

Terraform v1.9.5
on linux_amd64

Terraform Configuration Files

resource "binarylane_server" "server" {
  count = 1

  name              = "${local.cluster_id}-server-${count.index + 1}"
  region            = "per"
  image             = "ubuntu-24.04"
  size              = "std-min"
  password          = random_password.binarylane.result
  ssh_keys          = [binarylane_ssh_key.example.id]
  vpc_id            = binarylane_vpc.example.id
  public_ipv4_count = 1
  user_data         = sensitive(data.cloudinit_config.server.rendered)
  wait_for_create   = 60 # Must wait for the server to be ready before creating firewall rules
}

resource "binarylane_server_firewall_rules" "example" {
  for_each = { for server in concat(binarylane_server.server, binarylane_server.agent) : server.name => server }

  server_id = each.value.id

  firewall_rules = [
    {
      description           = "K3s supervisor and Kubernetes API Server"
      protocol              = "tcp"
      source_addresses      = ["0.0.0.0/0"]
      destination_addresses = local.server_ips # <-- blows up here
      destination_ports     = ["6443"]
      action                = "accept"
    },
    # ...
  ]
}

Debug Output

https://gist.github.com/oscarhermoso/53849e90d66a97258ca2cb72906fe848

Expected Behavior

Terraform should plan succeed, with binarylane_server_firewall_rules.example["tf-example-k8s-agent-2"].firewall_rules[0].destination_addresses and similar planned as unknown values

Actual Behavior

│ Error: Provider produced invalid plan │ │ Provider "registry.terraform.io/oscarhermoso/binarylane" planned an invalid value for │ binarylane_server_firewall_rules.example["tf-example-k8s-agent-2"].firewall_rules[0].destination_addresses: │ planned value cty.ListValEmpty(cty.String) does not match config value │ cty.UnknownVal(cty.List(cty.String)). │ │ This is a bug in the provider, which should be reported in the provider's own issue tracker.

Steps to Reproduce

  1. Clone https://github.com/oscarhermoso/terraform-provider-binarylane
  2. cd examples/k3s
  3. terraform init
  4. Uncomment block in binarylane_server_firewall_rules.example:
    # TODO: Due to a bug, this only works if you uncomment AFTER creating servers
    # {
    #   description           = "K3s supervisor and Kubernetes API Server"
    #   protocol              = "tcp"
    #   source_addresses      = ["0.0.0.0/0"]
    #   destination_addresses = local.server_ips
    #   destination_ports     = ["6443"]
    #   action                = "accept"
    # },
  5. BINARYLANE_API_TOKEN=anything TF_ACC=1 tf apply

Additional Context

Failing in https://github.com/oscarhermoso/terraform-provider-binarylane/blob/main/internal/provider/server_firewall_rules_resource.go

After adding logging in a ModifyPlan method, I can see that the raw Config has type "destination_addresses":tftypes.List[tftypes.String]<unknown>, whereas the raw Plan has type "destination_addresses":tftypes.List[tftypes.String].

Logging ``` │ Warning: req.config │ │ with binarylane_server_firewall_rules.example["tf-example-k8s-agent-1"], │ on main.tf line 131, in resource "binarylane_server_firewall_rules" "example": │ 131: resource "binarylane_server_firewall_rules" "example" { │ │ tftypes.Object["firewall_rules":tftypes.List[tftypes.Object["action":tftypes.String, "description":tftypes.String, │ "destination_addresses":tftypes.List[tftypes.String], "destination_ports":tftypes.List[tftypes.String], │ "protocol":tftypes.String, "source_addresses":tftypes.List[tftypes.String]]], │ "server_id":tftypes.Number]<"firewall_rules":tftypes.List[tftypes.Object["action":tftypes.String, │ "description":tftypes.String, "destination_addresses":tftypes.List[tftypes.String], │ "destination_ports":tftypes.List[tftypes.String], "protocol":tftypes.String, │ "source_addresses":tftypes.List[tftypes.String]]], │ "description":tftypes.String<"K3s supervisor and Kubernetes API Server">, │ "destination_addresses":tftypes.List[tftypes.String], │ "destination_ports":tftypes.List[tftypes.String]>, "protocol":tftypes.String<"tcp">, │ "source_addresses":tftypes.List[tftypes.String]>>>, "server_id":tftypes.Number> │ │ (and 2 more similar warnings elsewhere) ╵ ╷ │ Warning: req.plan │ │ with binarylane_server_firewall_rules.example["tf-example-k8s-agent-1"], │ on main.tf line 131, in resource "binarylane_server_firewall_rules" "example": │ 131: resource "binarylane_server_firewall_rules" "example" { │ │ tftypes.Object["firewall_rules":tftypes.List[tftypes.Object["action":tftypes.String, "description":tftypes.String, │ "destination_addresses":tftypes.List[tftypes.String], "destination_ports":tftypes.List[tftypes.String], │ "protocol":tftypes.String, "source_addresses":tftypes.List[tftypes.String]]], │ "server_id":tftypes.Number]<"firewall_rules":tftypes.List[tftypes.Object["action":tftypes.String, │ "description":tftypes.String, "destination_addresses":tftypes.List[tftypes.String], │ "destination_ports":tftypes.List[tftypes.String], "protocol":tftypes.String, │ "source_addresses":tftypes.List[tftypes.String]]], │ "description":tftypes.String<"K3s supervisor and Kubernetes API Server">, │ "destination_addresses":tftypes.List[tftypes.String]<>, │ "destination_ports":tftypes.List[tftypes.String]>, "protocol":tftypes.String<"tcp">, │ "source_addresses":tftypes.List[tftypes.String]>>>, "server_id":tftypes.Number> ```

Considering the terraform-provider-binarylane priovider does not contain any code convert req.Raw.Config to req.Raw.Plan - my understanding is that either this is a bug with Terraform, or I need to add some code in a ModifyPlan method or similar to handle unknown values.

Either way, would appreciate any assistance with investigating the issue. Thanks in advance.

References

https://github.com/oscarhermoso/terraform-provider-binarylane/issues/15

liamcervante commented 2 months ago

Hi @oscarhermoso, thanks for filing this!

The error from Terraform indicates that Terraform Core is sending an unknown value for this attribute in the request and receiving an empty list back in the plan. Since, this attribute is not computed it is not valid for the provider to change the value during the plan. There is nothing that Terraform Core could be doing to produce the planned value you are seeing, it is likely that this value is being produced by the plugin framework between Terraform and your code in the provider. Unfortunately, there is unlikely to be anyone in this repository who can help you with provider development in this way - this issue is probably caused by the implementation of the terraform-plugin-framework within your provider.

I'd recommend either positing within our forums to see if anyone else has had the same issues and been able to resolve it, alternatively you can refile this as a bug directly within terraform-plugin-framework where the developers of the framework itself will have more context around the expected behaviour.

Thanks!

github-actions[bot] commented 1 month ago

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.