terraform-provider-hcloud icon indicating copy to clipboard operation
terraform-provider-hcloud copied to clipboard

[Bug]: Placement group data source fails for newly created placement groups

Open fnkr opened this issue 2 years ago • 3 comments

What happened?

➜ terraform apply -auto-approve
hcloud_placement_group.test: Creating...
hcloud_placement_group.test: Creation complete after 0s [id=1251]
data.hcloud_placement_group.test: Reading...
data.hcloud_placement_group.test: Read complete after 0s [name=test]

Error: Provider produced inconsistent final plan

When expanding the plan for hcloud_server.test_2 to include new values learned
so far during apply, provider "registry.terraform.io/hetznercloud/hcloud"
produced an invalid new value for .placement_group_id: was null, but now
cty.NumberIntVal(1251).

This is a bug in the provider, which should be reported in the provider's own
issue tracker.


Error: Provider produced inconsistent final plan

When expanding the plan for hcloud_server.test_1 to include new values learned
so far during apply, provider "registry.terraform.io/hetznercloud/hcloud"
produced an invalid new value for .placement_group_id: was null, but now
cty.NumberIntVal(1251).

This is a bug in the provider, which should be reported in the provider's own
issue tracker.

What did you expect to happen?

Terraform should create the placement group and servers.

Please provide a minimal working example

terraform {
  required_providers {
    hcloud = {
      source = "hetznercloud/hcloud"
    }
  }
  required_version = ">= 0.13"
}

provider "hcloud" {
  token = ""
}

data "hcloud_placement_group" "test" {
  name = "test"

  depends_on = [
    hcloud_placement_group.test,
  ]
}

resource "hcloud_placement_group" "test" {
  name = "test"
  type = "spread"
}

resource "hcloud_server" "test_1" {
  name               = "test-1"
  server_type        = "cx11"
  image              = "ubuntu-20.04"
  placement_group_id = data.hcloud_placement_group.test.id
}

resource "hcloud_server" "test_2" {
  name               = "test-2"
  server_type        = "cx11"
  image              = "ubuntu-20.04"
  placement_group_id = data.hcloud_placement_group.test.id
}

A more real-life scenario would look like this: Terraform would use an existing placement group if one is specified or create it's own otherwise. Other resources would refer to the data source (not the resource) in any case.

variable "existing_placement_group_name" {
  type    = string
  default = ""
}

data "hcloud_placement_group" "test" {
  name = var.existing_placement_group_name == "" ? hcloud_placement_group.test.0.name : var.existing_placement_group_name
}

resource "hcloud_placement_group" "test" {
  count = var.existing_placement_group_name == "" ? 1 : 0
  name  = "test"
  type  = "spread"
}

resource "hcloud_server" "test" {
  name               = "test"
  server_type        = "cx11"
  image              = "ubuntu-20.04"
  placement_group_id = data.hcloud_placement_group.test.id
}

This works well for other resource types such as networks.

fnkr avatar Aug 31 '21 18:08 fnkr

Hey @fnkr,

thank you for your report. Just out of curiosity why do you use a datasource when you have the data of the placement group already fully in the resource? so using hcloud_placement_group.test.id in you case would be better IMO. I will try to reproduce it.

LKaemmerling avatar Sep 06 '21 05:09 LKaemmerling

Mmh this can not work, even for the other resources it should not work.

Terraform tries to create those servers with placement group id = null (because the datasource does not find something yet). You could solve it with a few more depends_on, but this isn't as nice as using the resource.

So from our side I wouldn't say this is a bug. It works like intended from terraform side.

LKaemmerling avatar Sep 06 '21 05:09 LKaemmerling

Other resources always reference the data object and the data object either references the resource or an existing placement group in the cloud. This way I don't have to put a ternary in every single server resource. The pattern works well for networks (e.g. here, here), where the data object is referenced by server / load balancer network attachments, network subnets and network routes. Never got any error here, so it should work for placement groups too, right?

terraform {
  required_providers {
    hcloud = {
      source = "hetznercloud/hcloud"
    }
  }
  required_version = ">= 0.13"
}

provider "hcloud" {
  token = ""
}

variable "existing_placement_group_name" {
  type    = string
  default = ""
}

data "hcloud_placement_group" "test" {
  name = var.existing_placement_group_name == "" ? hcloud_placement_group.test.0.name : var.existing_placement_group_name
}

resource "hcloud_placement_group" "test" {
  count = var.existing_placement_group_name == "" ? 1 : 0
  name  = "test"
  type  = "spread"
}

resource "hcloud_server" "test" {
  name               = "test"
  server_type        = "cx11"
  image              = "ubuntu-20.04"
  placement_group_id = data.hcloud_placement_group.test.id
}

You could solve it with a few more depends_on, but this isn't as nice as using the resource.

Where should I add these?

fnkr avatar Sep 06 '21 07:09 fnkr

This issue has been marked as stale because it has not had recent activity. The bot will close the issue if no further action occurs.

github-actions[bot] avatar Oct 12 '23 12:10 github-actions[bot]

Hey, sorry for letting this go stale (and not fixing it for so long). This is indeed a bug IMO. Some fields were not marked as computed, causing Terraform to evaluate the plan incorrectly.

This should be fixed with #806.

apricote avatar Dec 04 '23 09:12 apricote

Thanks for fixing!

fnkr avatar Dec 04 '23 09:12 fnkr