Skip to content

Commit 7e1bf2c

Browse files
authored
fix(ssh-key): data inconsistency with empty label objects (#922)
When we implemented the Label helper we added some extra logic that handled the difference between the `label` attribute default (null) and the Hetzner Cloud API default (`{}`). This worked well in our test cases, but breaks if you pass an empty object to the attribute: ``` When applying changes to hcloud_ssh_key.this, provider "provider[\"registry.terraform.io/hetznercloud/hcloud\"]" produced an unexpected new value: .labels: was cty.MapValEmpty(cty.String), but now null. ``` We have now fixed this by setting the default of the labels field to an empty object to match the return value of the API. With this, we no longer need the workaround to handle null labels in Terraform config. Fixes #921
1 parent 932c47b commit 7e1bf2c

File tree

4 files changed

+10
-9
lines changed

4 files changed

+10
-9
lines changed

internal/loadbalancer/resource_target_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010

1111
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
1212
"github.com/hashicorp/terraform-plugin-testing/terraform"
13+
1314
"github.com/hetznercloud/hcloud-go/hcloud"
1415
"github.com/hetznercloud/terraform-provider-hcloud/internal/loadbalancer"
1516
"github.com/hetznercloud/terraform-provider-hcloud/internal/network"

internal/sshkey/resource_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/hetznercloud/terraform-provider-hcloud/internal/teste2e"
99

1010
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
11+
1112
"github.com/hetznercloud/hcloud-go/hcloud"
1213
"github.com/hetznercloud/terraform-provider-hcloud/internal/testsupport"
1314
"github.com/hetznercloud/terraform-provider-hcloud/internal/testtemplate"

internal/util/resourceutil/labels.go

+7-8
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ package resourceutil
33
import (
44
"context"
55

6+
"github.com/hashicorp/terraform-plugin-framework/attr"
67
"github.com/hashicorp/terraform-plugin-framework/diag"
78
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
9+
"github.com/hashicorp/terraform-plugin-framework/resource/schema/mapdefault"
810
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
911
"github.com/hashicorp/terraform-plugin-framework/types"
1012

@@ -42,21 +44,18 @@ func LabelsSchema() schema.MapAttribute {
4244
return schema.MapAttribute{
4345
MarkdownDescription: "User-defined [labels](https://docs.hetzner.cloud/#labels) (key-value pairs) for the resource.",
4446
Optional: true,
47+
Computed: true, // Required to use Default
4548
ElementType: types.StringType,
49+
// In the resource schemas, labels can be null, but the API always returns an empty object for labels.
50+
// To avoid a data consistency issue, we set the default value to the empty object.
51+
Default: mapdefault.StaticValue(types.MapValueMust(types.StringType, map[string]attr.Value{})),
4652
Validators: []validator.Map{
4753
labelsValidator{},
4854
},
4955
}
5056
}
5157

5258
// LabelsMapValueFrom prepare the labels from the API to be assigned into the resource model.
53-
//
54-
// In the resource schemas, labels can be null, but the API always returns an empty object for labels.
55-
// This causes a conflict in the Terraform Data Consistency check. This method handles empty label
56-
// objects by instead returning a null map.
5759
func LabelsMapValueFrom(ctx context.Context, in map[string]string) (types.Map, diag.Diagnostics) {
58-
if len(in) > 0 {
59-
return types.MapValueFrom(ctx, types.StringType, in)
60-
}
61-
return types.MapNull(types.StringType), nil
60+
return types.MapValueFrom(ctx, types.StringType, in)
6261
}

internal/util/resourceutil/labels_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ func TestLabelsMapValueFrom(t *testing.T) {
9797
{
9898
name: "Empty Map",
9999
in: map[string]string{},
100-
want: types.MapNull(types.StringType),
100+
want: types.MapValueMust(types.StringType, map[string]attr.Value{}),
101101
diags: nil,
102102
},
103103
}

0 commit comments

Comments
 (0)