From 820d07cf0343283c87768cf2d62cb0b21e2e0b26 Mon Sep 17 00:00:00 2001 From: jo Date: Thu, 9 Jan 2025 19:27:15 +0000 Subject: [PATCH] wip --- internal/firewall/attachment_resource.go | 22 +-- .../attachment_resource_internal_test.go | 34 ++--- .../loadbalancer/resource_service_test.go | 24 ++-- internal/loadbalancer/resource_target_test.go | 6 +- internal/loadbalancer/resource_test.go | 6 +- internal/network/data_source.go | 6 +- internal/network/resource.go | 14 +- internal/network/resource_route.go | 6 +- internal/network/resource_subnet.go | 10 +- internal/placementgroup/resource.go | 18 +-- internal/primaryip/resource.go | 4 +- internal/server/resource.go | 129 ++++++++---------- internal/server/resource_network.go | 10 +- internal/server/resource_test.go | 51 +++++-- internal/teste2e/testing.go | 4 +- internal/testsupport/check.go | 4 +- 16 files changed, 171 insertions(+), 177 deletions(-) diff --git a/internal/firewall/attachment_resource.go b/internal/firewall/attachment_resource.go index 54ebc9d13..1d13cd755 100644 --- a/internal/firewall/attachment_resource.go +++ b/internal/firewall/attachment_resource.go @@ -5,12 +5,12 @@ import ( "fmt" "log" "sort" - "strconv" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hetznercloud/hcloud-go/v2/hcloud" + "github.com/hetznercloud/terraform-provider-hcloud/internal/util" "github.com/hetznercloud/terraform-provider-hcloud/internal/util/hcloudutil" ) @@ -170,8 +170,8 @@ func deleteAttachment(ctx context.Context, d *schema.ResourceData, m interface{} } type attachment struct { - FirewallID int - ServerIDs []int + FirewallID int64 + ServerIDs []int64 LabelSelectors []string } @@ -179,12 +179,12 @@ type attachment struct { func (a *attachment) FromResourceData(d *schema.ResourceData) error { // The terraform schema definition above ensures this is always set and // of the correct type. Thus there is no need to check such things. - a.FirewallID = d.Get("firewall_id").(int) + a.FirewallID = util.CastInt64(d.Get("firewall_id")) srvIDs, ok := d.GetOk("server_ids") if ok { for _, v := range srvIDs.(*schema.Set).List() { - a.ServerIDs = append(a.ServerIDs, v.(int)) + a.ServerIDs = append(a.ServerIDs, util.CastInt64(v)) } sort.Slice(a.ServerIDs, func(i, j int) bool { return a.ServerIDs[i] < a.ServerIDs[j] @@ -216,7 +216,7 @@ func (a *attachment) ToResourceData(d *schema.ResourceData) { if len(a.ServerIDs) > 0 { vals := make([]interface{}, len(a.ServerIDs)) for i, id := range a.ServerIDs { - vals[i] = id + vals[i] = int(id) } f := d.Get("server_ids").(*schema.Set).F // Returns a default value if server_ids is not present in HCL. srvIDs = schema.NewSet(f, vals) @@ -233,8 +233,8 @@ func (a *attachment) ToResourceData(d *schema.ResourceData) { } d.Set("label_selectors", lSels) - d.Set("firewall_id", a.FirewallID) - d.SetId(strconv.Itoa(a.FirewallID)) + d.Set("firewall_id", int(a.FirewallID)) + d.SetId(util.FormatID(a.FirewallID)) } // FromFirewall reads the attachment data from fw into a. @@ -285,7 +285,7 @@ func (a *attachment) AllResources() []hcloud.FirewallResource { func (a *attachment) DiffResources(o attachment) ([]hcloud.FirewallResource, []hcloud.FirewallResource) { var more, less []hcloud.FirewallResource // nolint: prealloc - aSrvs := make(map[int]bool, len(a.ServerIDs)) + aSrvs := make(map[int64]bool, len(a.ServerIDs)) for _, id := range a.ServerIDs { aSrvs[id] = true } @@ -307,7 +307,7 @@ func (a *attachment) DiffResources(o attachment) ([]hcloud.FirewallResource, []h less = append(less, labelSelectorResource(ls)) } - oSrvs := make(map[int]bool, len(o.ServerIDs)) + oSrvs := make(map[int64]bool, len(o.ServerIDs)) for _, id := range o.ServerIDs { oSrvs[id] = true } @@ -332,7 +332,7 @@ func (a *attachment) DiffResources(o attachment) ([]hcloud.FirewallResource, []h return less, more } -func serverResource(id int) hcloud.FirewallResource { +func serverResource(id int64) hcloud.FirewallResource { return hcloud.FirewallResource{ Type: hcloud.FirewallResourceTypeServer, Server: &hcloud.FirewallResourceServer{ID: id}, diff --git a/internal/firewall/attachment_resource_internal_test.go b/internal/firewall/attachment_resource_internal_test.go index 8205333dc..ac68bff12 100644 --- a/internal/firewall/attachment_resource_internal_test.go +++ b/internal/firewall/attachment_resource_internal_test.go @@ -1,7 +1,6 @@ package firewall import ( - "strconv" "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -9,6 +8,7 @@ import ( "github.com/stretchr/testify/require" "github.com/hetznercloud/hcloud-go/v2/hcloud" + "github.com/hetznercloud/terraform-provider-hcloud/internal/util" ) func TestAttachment_FromResourceData(t *testing.T) { @@ -27,7 +27,7 @@ func TestAttachment_FromResourceData(t *testing.T) { }, att: attachment{ FirewallID: 4711, - ServerIDs: []int{1, 2, 3}, + ServerIDs: []int64{1, 2, 3}, LabelSelectors: []string{"key1=value1", "key2=value2"}, }, }, @@ -39,7 +39,7 @@ func TestAttachment_FromResourceData(t *testing.T) { }, att: attachment{ FirewallID: 4712, - ServerIDs: []int{4, 5, 6}, + ServerIDs: []int64{4, 5, 6}, }, }, { @@ -94,7 +94,7 @@ func TestAttachment_ToResourceData(t *testing.T) { name: "server_ids and label_selectors present", att: attachment{ FirewallID: 4711, - ServerIDs: []int{1, 2, 3}, + ServerIDs: []int64{1, 2, 3}, LabelSelectors: []string{"key1=value1", "key2=value2"}, }, }, @@ -102,7 +102,7 @@ func TestAttachment_ToResourceData(t *testing.T) { name: "only server_ids present", att: attachment{ FirewallID: 4712, - ServerIDs: []int{4, 5, 6}, + ServerIDs: []int64{4, 5, 6}, }, }, { @@ -131,7 +131,7 @@ func TestAttachment_ToResourceData(t *testing.T) { }, att: attachment{ FirewallID: 4714, - ServerIDs: []int{1, 2, 3}, + ServerIDs: []int64{1, 2, 3}, }, }, } @@ -143,8 +143,8 @@ func TestAttachment_ToResourceData(t *testing.T) { tt.att.ToResourceData(data) - assert.Equal(t, data.Id(), strconv.Itoa(tt.att.FirewallID)) - assert.Equal(t, data.Get("firewall_id"), tt.att.FirewallID) + assert.Equal(t, data.Id(), util.FormatID(tt.att.FirewallID)) + assert.Equal(t, data.Get("firewall_id"), int(tt.att.FirewallID)) srvIDdata, ok := data.GetOk("server_ids") if len(tt.att.ServerIDs) > 0 { @@ -152,7 +152,7 @@ func TestAttachment_ToResourceData(t *testing.T) { // Need to iterate as the types of the slices don't match: []int vs []interface{} for _, id := range tt.att.ServerIDs { - assert.Contains(t, srvIDdata.(*schema.Set).List(), id) + assert.Contains(t, srvIDdata.(*schema.Set).List(), int(id)) } } else { assert.False(t, ok, "expected no server_ids in data") @@ -195,7 +195,7 @@ func TestAttachment_FromFirewall(t *testing.T) { }, att: attachment{ FirewallID: 4712, - ServerIDs: []int{1, 2}, + ServerIDs: []int64{1, 2}, }, }, { @@ -257,7 +257,7 @@ func TestAttachment_AllResources(t *testing.T) { name: "servers and label selectors attached", att: attachment{ FirewallID: 4712, - ServerIDs: []int{1, 2}, + ServerIDs: []int64{1, 2}, LabelSelectors: []string{"key1=value1", "key2=value2"}, }, res: []hcloud.FirewallResource{ @@ -290,12 +290,12 @@ func TestAttachment_DiffResources(t *testing.T) { name: "nothing changed", att: attachment{ FirewallID: 4711, - ServerIDs: []int{1, 2, 3}, + ServerIDs: []int64{1, 2, 3}, LabelSelectors: []string{"key1=value1", "key2=value2"}, }, other: attachment{ FirewallID: 4711, - ServerIDs: []int{1, 2, 3}, + ServerIDs: []int64{1, 2, 3}, LabelSelectors: []string{"key1=value1", "key2=value2"}, }, }, @@ -303,12 +303,12 @@ func TestAttachment_DiffResources(t *testing.T) { name: "resources in att but not in other", att: attachment{ FirewallID: 4711, - ServerIDs: []int{1, 2, 3}, + ServerIDs: []int64{1, 2, 3}, LabelSelectors: []string{"key1=value1", "key2=value2"}, }, other: attachment{ FirewallID: 4711, - ServerIDs: []int{1, 2}, + ServerIDs: []int64{1, 2}, LabelSelectors: []string{"key1=value1"}, }, more: []hcloud.FirewallResource{ @@ -320,12 +320,12 @@ func TestAttachment_DiffResources(t *testing.T) { name: "resources in other but not in att", att: attachment{ FirewallID: 4711, - ServerIDs: []int{1, 2}, + ServerIDs: []int64{1, 2}, LabelSelectors: []string{"key1=value1"}, }, other: attachment{ FirewallID: 4711, - ServerIDs: []int{1, 2, 3}, + ServerIDs: []int64{1, 2, 3}, LabelSelectors: []string{"key1=value1", "key2=value2"}, }, less: []hcloud.FirewallResource{ diff --git a/internal/loadbalancer/resource_service_test.go b/internal/loadbalancer/resource_service_test.go index 8b0cded36..5793af852 100644 --- a/internal/loadbalancer/resource_service_test.go +++ b/internal/loadbalancer/resource_service_test.go @@ -2,7 +2,6 @@ package loadbalancer_test import ( "fmt" - "strconv" "testing" "github.com/hashicorp/terraform-plugin-testing/helper/resource" @@ -14,6 +13,7 @@ import ( "github.com/hetznercloud/terraform-provider-hcloud/internal/teste2e" "github.com/hetznercloud/terraform-provider-hcloud/internal/testsupport" "github.com/hetznercloud/terraform-provider-hcloud/internal/testtemplate" + "github.com/hetznercloud/terraform-provider-hcloud/internal/util" ) func TestAccLoadBalancerServiceResource_TCP(t *testing.T) { @@ -47,7 +47,7 @@ func TestAccLoadBalancerServiceResource_TCP(t *testing.T) { testsupport.CheckResourceExists(lbResName, loadbalancer.ByID(t, &lb)), testsupport.LiftTCF(hasService(&lb, 70)), testsupport.CheckResourceAttrFunc(svcResName, "load_balancer_id", func() string { - return strconv.Itoa(lb.ID) + return util.FormatID(lb.ID) }), resource.TestCheckResourceAttr(svcResName, "protocol", "tcp"), resource.TestCheckResourceAttr(svcResName, "listen_port", "70"), @@ -80,7 +80,7 @@ func TestAccLoadBalancerServiceResource_TCP(t *testing.T) { testsupport.CheckResourceExists(lbResName, loadbalancer.ByID(t, &lb)), testsupport.LiftTCF(hasService(&lb, 70)), testsupport.CheckResourceAttrFunc(svcResName, "load_balancer_id", func() string { - return strconv.Itoa(lb.ID) + return util.FormatID(lb.ID) }), resource.TestCheckResourceAttr(svcResName, "protocol", "tcp"), resource.TestCheckResourceAttr(svcResName, "listen_port", "70"), @@ -121,7 +121,7 @@ func TestAccLoadBalancerServiceResource_HTTP(t *testing.T) { testsupport.CheckResourceExists(lbResName, loadbalancer.ByID(t, &lb)), testsupport.LiftTCF(hasService(&lb, 80)), testsupport.CheckResourceAttrFunc(svcResName, "load_balancer_id", func() string { - return strconv.Itoa(lb.ID) + return util.FormatID(lb.ID) }), resource.TestCheckResourceAttr(svcResName, "protocol", "http"), resource.TestCheckResourceAttr(svcResName, "listen_port", "80"), @@ -149,7 +149,7 @@ func TestAccLoadBalancerServiceResource_HTTP(t *testing.T) { testsupport.CheckResourceExists(lbResName, loadbalancer.ByID(t, &lb)), testsupport.LiftTCF(hasService(&lb, 81)), testsupport.CheckResourceAttrFunc(svcResName, "load_balancer_id", func() string { - return strconv.Itoa(lb.ID) + return util.FormatID(lb.ID) }), resource.TestCheckResourceAttr(svcResName, "protocol", "http"), resource.TestCheckResourceAttr(svcResName, "listen_port", "81"), @@ -187,7 +187,7 @@ func TestAccLoadBalancerServiceResource_HTTP(t *testing.T) { testsupport.CheckResourceExists(lbResName, loadbalancer.ByID(t, &lb)), testsupport.LiftTCF(hasService(&lb, 81)), testsupport.CheckResourceAttrFunc(svcResName, "load_balancer_id", func() string { - return strconv.Itoa(lb.ID) + return util.FormatID(lb.ID) }), resource.TestCheckResourceAttr(svcResName, "protocol", "http"), resource.TestCheckResourceAttr(svcResName, "listen_port", "81"), @@ -242,7 +242,7 @@ func TestAccLoadBalancerServiceResource_HTTP_StickySessions(t *testing.T) { testsupport.CheckResourceExists(lbResName, loadbalancer.ByID(t, &lb)), testsupport.LiftTCF(hasService(&lb, 80)), testsupport.CheckResourceAttrFunc(svcResName, "load_balancer_id", func() string { - return strconv.Itoa(lb.ID) + return util.FormatID(lb.ID) }), resource.TestCheckResourceAttr(svcResName, "protocol", "http"), resource.TestCheckResourceAttr(svcResName, "http.0.cookie_lifetime", "1800"), @@ -293,7 +293,7 @@ func TestAccLoadBalancerServiceResource_HTTPS(t *testing.T) { testsupport.CheckResourceExists(certData.TFID(), certificate.ByID(t, &cert)), testsupport.LiftTCF(hasService(&lb, 443)), testsupport.CheckResourceAttrFunc(svcResName, "http.0.certificates.0", func() string { - return strconv.Itoa(cert.ID) + return util.FormatID(cert.ID) }), resource.TestCheckResourceAttr(svcResName, "protocol", "https"), resource.TestCheckResourceAttr(svcResName, "listen_port", "443"), @@ -435,7 +435,7 @@ func TestAccLoadBalancerServiceResource_ChangeListenPort(t *testing.T) { testsupport.CheckResourceExists(lbResName, loadbalancer.ByID(t, &lb)), testsupport.LiftTCF(hasService(&lb, 70)), testsupport.CheckResourceAttrFunc(svcResName, "load_balancer_id", func() string { - return strconv.Itoa(lb.ID) + return util.FormatID(lb.ID) }), resource.TestCheckResourceAttr(svcResName, "protocol", "tcp"), resource.TestCheckResourceAttr(svcResName, "listen_port", "70"), @@ -443,7 +443,7 @@ func TestAccLoadBalancerServiceResource_ChangeListenPort(t *testing.T) { testsupport.LiftTCF(hasService(&lb, 443)), testsupport.CheckResourceAttrFunc(svcResName2, "load_balancer_id", func() string { - return strconv.Itoa(lb.ID) + return util.FormatID(lb.ID) }), resource.TestCheckResourceAttr(svcResName2, "protocol", "tcp"), resource.TestCheckResourceAttr(svcResName2, "listen_port", "443"), @@ -473,7 +473,7 @@ func TestAccLoadBalancerServiceResource_ChangeListenPort(t *testing.T) { testsupport.CheckResourceExists(lbResName, loadbalancer.ByID(t, &lb)), testsupport.LiftTCF(hasService(&lb, 71)), testsupport.CheckResourceAttrFunc(svcResName, "load_balancer_id", func() string { - return strconv.Itoa(lb.ID) + return util.FormatID(lb.ID) }), resource.TestCheckResourceAttr(svcResName, "protocol", "tcp"), resource.TestCheckResourceAttr(svcResName, "listen_port", "71"), @@ -481,7 +481,7 @@ func TestAccLoadBalancerServiceResource_ChangeListenPort(t *testing.T) { testsupport.LiftTCF(hasService(&lb, 443)), testsupport.CheckResourceAttrFunc(svcResName2, "load_balancer_id", func() string { - return strconv.Itoa(lb.ID) + return util.FormatID(lb.ID) }), resource.TestCheckResourceAttr(svcResName2, "protocol", "tcp"), resource.TestCheckResourceAttr(svcResName2, "listen_port", "443"), diff --git a/internal/loadbalancer/resource_target_test.go b/internal/loadbalancer/resource_target_test.go index e2b10efbf..4854ea3c0 100644 --- a/internal/loadbalancer/resource_target_test.go +++ b/internal/loadbalancer/resource_target_test.go @@ -2,7 +2,6 @@ package loadbalancer_test import ( "fmt" - "strconv" "testing" "github.com/hashicorp/terraform-plugin-testing/helper/resource" @@ -16,6 +15,7 @@ import ( "github.com/hetznercloud/terraform-provider-hcloud/internal/teste2e" "github.com/hetznercloud/terraform-provider-hcloud/internal/testsupport" "github.com/hetznercloud/terraform-provider-hcloud/internal/testtemplate" + "github.com/hetznercloud/terraform-provider-hcloud/internal/util" ) func TestAccLoadBalancerTargetResource_ServerTarget(t *testing.T) { @@ -63,11 +63,11 @@ func TestAccLoadBalancerTargetResource_ServerTarget(t *testing.T) { loadbalancer.TargetResourceType+".lb-test-target", "type", "server"), testsupport.CheckResourceAttrFunc( loadbalancer.TargetResourceType+".lb-test-target", "load_balancer_id", func() string { - return strconv.Itoa(lb.ID) + return util.FormatID(lb.ID) }), testsupport.CheckResourceAttrFunc( loadbalancer.TargetResourceType+".lb-test-target", "server_id", func() string { - return strconv.Itoa(srv.ID) + return util.FormatID(srv.ID) }), testsupport.LiftTCF(hasServerTarget(&lb, &srv)), ), diff --git a/internal/loadbalancer/resource_test.go b/internal/loadbalancer/resource_test.go index b3c07e271..a424f890c 100644 --- a/internal/loadbalancer/resource_test.go +++ b/internal/loadbalancer/resource_test.go @@ -2,7 +2,6 @@ package loadbalancer_test import ( "fmt" - "strconv" "testing" "github.com/hashicorp/terraform-plugin-testing/helper/acctest" @@ -14,6 +13,7 @@ import ( "github.com/hetznercloud/terraform-provider-hcloud/internal/teste2e" "github.com/hetznercloud/terraform-provider-hcloud/internal/testsupport" "github.com/hetznercloud/terraform-provider-hcloud/internal/testtemplate" + "github.com/hetznercloud/terraform-provider-hcloud/internal/util" ) func TestAccLoadBalancerResource(t *testing.T) { @@ -180,10 +180,10 @@ func TestAccLoadBalancerResource_InlineTarget(t *testing.T) { testsupport.CheckResourceExists(resServer1.TFID(), server.ByID(t, &srv0)), testsupport.CheckResourceExists(resServer2.TFID(), server.ByID(t, &srv1)), testsupport.CheckResourceAttrFunc(res.TFID(), "target.0.server_id", func() []string { - return []string{strconv.Itoa(srv0.ID), strconv.Itoa(srv1.ID)} + return []string{util.FormatID(srv0.ID), util.FormatID(srv1.ID)} }), testsupport.CheckResourceAttrFunc(res.TFID(), "target.1.server_id", func() []string { - return []string{strconv.Itoa(srv0.ID), strconv.Itoa(srv1.ID)} + return []string{util.FormatID(srv0.ID), util.FormatID(srv1.ID)} }), ), }, diff --git a/internal/network/data_source.go b/internal/network/data_source.go index 8e5a9790a..649c26ddf 100644 --- a/internal/network/data_source.go +++ b/internal/network/data_source.go @@ -2,12 +2,12 @@ package network import ( "context" - "strconv" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hetznercloud/hcloud-go/v2/hcloud" + "github.com/hetznercloud/terraform-provider-hcloud/internal/util" "github.com/hetznercloud/terraform-provider-hcloud/internal/util/datasourceutil" "github.com/hetznercloud/terraform-provider-hcloud/internal/util/hcloudutil" "github.com/hetznercloud/terraform-provider-hcloud/internal/util/merge" @@ -100,7 +100,7 @@ func dataSourceHcloudNetworkRead(ctx context.Context, d *schema.ResourceData, m client := m.(*hcloud.Client) if id, ok := d.GetOk("id"); ok { - n, _, err := client.Network.GetByID(ctx, id.(int)) + n, _, err := client.Network.GetByID(ctx, util.CastInt64(id)) if err != nil { return hcloudutil.ErrorToDiag(err) } @@ -165,7 +165,7 @@ func dataSourceHcloudNetworkListRead(ctx context.Context, d *schema.ResourceData ids := make([]string, len(allNetworks)) tsNetworks := make([]map[string]interface{}, len(allNetworks)) for i, firewall := range allNetworks { - ids[i] = strconv.Itoa(firewall.ID) + ids[i] = util.FormatID(firewall.ID) tsNetworks[i] = getNetworkAttributes(firewall) } d.Set("networks", tsNetworks) diff --git a/internal/network/resource.go b/internal/network/resource.go index 7c9427267..750aee9e8 100644 --- a/internal/network/resource.go +++ b/internal/network/resource.go @@ -4,7 +4,6 @@ import ( "context" "log" "net" - "strconv" "github.com/hashicorp/go-cty/cty" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -12,6 +11,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hetznercloud/hcloud-go/v2/hcloud" + "github.com/hetznercloud/terraform-provider-hcloud/internal/util" "github.com/hetznercloud/terraform-provider-hcloud/internal/util/hcloudutil" ) @@ -91,7 +91,7 @@ func resourceNetworkCreate(ctx context.Context, d *schema.ResourceData, m interf return hcloudutil.ErrorToDiag(err) } - d.SetId(strconv.Itoa(network.ID)) + d.SetId(util.FormatID(network.ID)) deleteProtection := d.Get("delete_protection").(bool) if deleteProtection { @@ -190,7 +190,7 @@ func resourceNetworkUpdate(ctx context.Context, d *schema.ResourceData, m interf func resourceNetworkDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { client := m.(*hcloud.Client) - networkID, err := strconv.Atoi(d.Id()) + networkID, err := util.ParseID(d.Id()) if err != nil { log.Printf("[WARN] invalid network id (%s), removing from state: %v", d.Id(), err) @@ -218,13 +218,7 @@ func resourceNetworkIsNotFound(err error, d *schema.ResourceData) bool { } func setNetworkSchema(d *schema.ResourceData, n *hcloud.Network) { - for key, val := range getNetworkAttributes(n) { - if key == "id" { - d.SetId(strconv.Itoa(val.(int))) - } else { - d.Set(key, val) - } - } + util.SetSchemaFromAttributes(d, getNetworkAttributes(n)) } func getNetworkAttributes(n *hcloud.Network) map[string]interface{} { diff --git a/internal/network/resource_route.go b/internal/network/resource_route.go index 6f5c000bb..eccf20b2f 100644 --- a/internal/network/resource_route.go +++ b/internal/network/resource_route.go @@ -6,13 +6,13 @@ import ( "fmt" "log" "net" - "strconv" "strings" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hetznercloud/hcloud-go/v2/hcloud" + "github.com/hetznercloud/terraform-provider-hcloud/internal/util" "github.com/hetznercloud/terraform-provider-hcloud/internal/util/control" "github.com/hetznercloud/terraform-provider-hcloud/internal/util/hcloudutil" ) @@ -67,7 +67,7 @@ func resourceNetworkRouteCreate(ctx context.Context, d *schema.ResourceData, m i return nil } networkID := d.Get("network_id") - network := &hcloud.Network{ID: networkID.(int)} + network := &hcloud.Network{ID: util.CastInt64(networkID)} opts := hcloud.NetworkAddRouteOpts{ Route: hcloud.NetworkRoute{ Destination: destination, @@ -182,7 +182,7 @@ func lookupNetworkRouteID(ctx context.Context, terraformID string, client *hclou return } - networkID, err := strconv.Atoi(parts[0]) + networkID, err := util.ParseID(parts[0]) if err != nil { err = errInvalidNetworkRouteID return diff --git a/internal/network/resource_subnet.go b/internal/network/resource_subnet.go index 512dcc720..81cc2ddfa 100644 --- a/internal/network/resource_subnet.go +++ b/internal/network/resource_subnet.go @@ -6,7 +6,6 @@ import ( "fmt" "log" "net" - "strconv" "strings" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -14,6 +13,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hetznercloud/hcloud-go/v2/hcloud" + "github.com/hetznercloud/terraform-provider-hcloud/internal/util" "github.com/hetznercloud/terraform-provider-hcloud/internal/util/control" "github.com/hetznercloud/terraform-provider-hcloud/internal/util/hcloudutil" ) @@ -80,7 +80,7 @@ func resourceNetworkSubnetCreate(ctx context.Context, d *schema.ResourceData, m return hcloudutil.ErrorToDiag(err) } networkID := d.Get("network_id") - network := &hcloud.Network{ID: networkID.(int)} + network := &hcloud.Network{ID: util.CastInt64(networkID)} subnetType := hcloud.NetworkSubnetType(d.Get("type").(string)) opts := hcloud.NetworkAddSubnetOpts{ @@ -93,7 +93,7 @@ func resourceNetworkSubnetCreate(ctx context.Context, d *schema.ResourceData, m if subnetType == hcloud.NetworkSubnetTypeVSwitch { vSwitchID := d.Get("vswitch_id") - opts.Subnet.VSwitchID = vSwitchID.(int) + opts.Subnet.VSwitchID = util.CastInt64(vSwitchID) } err = control.Retry(control.DefaultRetries, func() error { @@ -213,7 +213,7 @@ func generateNetworkSubnetID(network *hcloud.Network, ipRange string) string { // The faux subnet ID is created by the hcloud_network_subnet resource // during creation. Using this method it can be read from the state and // used in the implementation of other resources. -func ParseSubnetID(s string) (int, *net.IPNet, error) { +func ParseSubnetID(s string) (int64, *net.IPNet, error) { if s == "" { return 0, nil, errInvalidNetworkSubnetID } @@ -222,7 +222,7 @@ func ParseSubnetID(s string) (int, *net.IPNet, error) { return 0, nil, errInvalidNetworkSubnetID } - networkID, err := strconv.Atoi(parts[0]) + networkID, err := util.ParseID(parts[0]) if err != nil { return 0, nil, errInvalidNetworkSubnetID } diff --git a/internal/placementgroup/resource.go b/internal/placementgroup/resource.go index b9c9c81cf..4ac3a8f21 100644 --- a/internal/placementgroup/resource.go +++ b/internal/placementgroup/resource.go @@ -3,13 +3,13 @@ package placementgroup import ( "context" "log" - "strconv" "github.com/hashicorp/go-cty/cty" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hetznercloud/hcloud-go/v2/hcloud" + "github.com/hetznercloud/terraform-provider-hcloud/internal/util" "github.com/hetznercloud/terraform-provider-hcloud/internal/util/hcloudutil" ) @@ -83,7 +83,7 @@ func resourcePlacementGroupCreate(ctx context.Context, d *schema.ResourceData, m if err != nil { return hcloudutil.ErrorToDiag(err) } - d.SetId(strconv.Itoa(res.PlacementGroup.ID)) + d.SetId(util.FormatID(res.PlacementGroup.ID)) if res.Action != nil { if err := hcloudutil.WaitForAction(ctx, &client.Action, res.Action); err != nil { @@ -97,7 +97,7 @@ func resourcePlacementGroupCreate(ctx context.Context, d *schema.ResourceData, m func resourcePlacementGroupRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { client := m.(*hcloud.Client) - id, err := strconv.Atoi(d.Id()) + id, err := util.ParseID(d.Id()) if err != nil { log.Printf("[WARN] invalid placement group id (%s), removing from state: %v", d.Id(), err) d.SetId("") @@ -121,7 +121,7 @@ func resourcePlacementGroupRead(ctx context.Context, d *schema.ResourceData, m i func resourcePlacementGroupUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { client := m.(*hcloud.Client) - id, err := strconv.Atoi(d.Id()) + id, err := util.ParseID(d.Id()) if err != nil { log.Printf("[WARN] invalid placement group id (%s), removing from state: %v", d.Id(), err) d.SetId("") @@ -175,7 +175,7 @@ func resourcePlacementGroupUpdate(ctx context.Context, d *schema.ResourceData, m func resourcePlacementGroupDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { client := m.(*hcloud.Client) - id, err := strconv.Atoi(d.Id()) + id, err := util.ParseID(d.Id()) if err != nil { log.Printf("[WARN] invalid placement group id (%s), removing from state: %v", d.Id(), err) d.SetId("") @@ -198,13 +198,7 @@ func handleNotFound(err error, d *schema.ResourceData) bool { } func setSchema(d *schema.ResourceData, pg *hcloud.PlacementGroup) { - for key, val := range getAttributes(pg) { - if key == "id" { - d.SetId(strconv.Itoa(val.(int))) - } else { - d.Set(key, val) - } - } + util.SetSchemaFromAttributes(d, getAttributes(pg)) } func getAttributes(pg *hcloud.PlacementGroup) map[string]interface{} { diff --git a/internal/primaryip/resource.go b/internal/primaryip/resource.go index 37d8c1a69..e2cc0dcb3 100644 --- a/internal/primaryip/resource.go +++ b/internal/primaryip/resource.go @@ -317,9 +317,9 @@ func setPrimaryIPSchema(d *schema.ResourceData, f *hcloud.PrimaryIP) { func getPrimaryIPAttributes(f *hcloud.PrimaryIP) map[string]interface{} { res := map[string]interface{}{ - "id": util.FormatID(f.ID), + "id": f.ID, "ip_address": f.IP.String(), - "assignee_id": int(f.AssigneeID), + "assignee_id": f.AssigneeID, "assignee_type": f.AssigneeType, "name": f.Name, "type": f.Type, diff --git a/internal/server/resource.go b/internal/server/resource.go index e0dd095d1..d196f5221 100644 --- a/internal/server/resource.go +++ b/internal/server/resource.go @@ -8,7 +8,6 @@ import ( "fmt" "log" "net" - "strconv" "strings" "time" @@ -19,6 +18,7 @@ import ( "github.com/hetznercloud/hcloud-go/v2/hcloud" "github.com/hetznercloud/terraform-provider-hcloud/internal/primaryip" + "github.com/hetznercloud/terraform-provider-hcloud/internal/util" "github.com/hetznercloud/terraform-provider-hcloud/internal/util/control" "github.com/hetznercloud/terraform-provider-hcloud/internal/util/hcloudutil" ) @@ -352,12 +352,12 @@ func resourceServerCreate(ctx context.Context, d *schema.ResourceData, m interfa if firewallIDs, ok := d.GetOk("firewall_ids"); ok { for _, firewallID := range firewallIDs.(*schema.Set).List() { - opts.Firewalls = append(opts.Firewalls, &hcloud.ServerCreateFirewall{Firewall: hcloud.Firewall{ID: firewallID.(int)}}) + opts.Firewalls = append(opts.Firewalls, &hcloud.ServerCreateFirewall{Firewall: hcloud.Firewall{ID: util.CastInt64(firewallID)}}) } } if placementGroupID, ok := d.GetOk("placement_group_id"); ok { - placementGroup, err := getPlacementGroup(ctx, c, placementGroupID.(int)) + placementGroup, err := getPlacementGroup(ctx, c, util.CastInt64(placementGroupID)) if err != nil { return hcloudutil.ErrorToDiag(err) } @@ -369,19 +369,19 @@ func resourceServerCreate(ctx context.Context, d *schema.ResourceData, m interfa createPublicNet := hcloud.ServerCreatePublicNet{} for _, publicNetBlock := range publicNet.(*schema.Set).List() { publicNetEntry := publicNetBlock.(map[string]interface{}) - if enableIPv4, err := toServerPublicNet[bool](publicNetEntry, "ipv4_enabled"); err == nil { + if enableIPv4, err := ToPublicNetField[bool](publicNetEntry, "ipv4_enabled"); err == nil { createPublicNet.EnableIPv4 = enableIPv4 } - if enableIPv6, err := toServerPublicNet[bool](publicNetEntry, "ipv6_enabled"); err == nil { + if enableIPv6, err := ToPublicNetField[bool](publicNetEntry, "ipv6_enabled"); err == nil { createPublicNet.EnableIPv6 = enableIPv6 } - if ipv4, err := toServerPublicNet[int](publicNetEntry, "ipv4"); err == nil && ipv4 != 0 { + if ipv4, err := ToPublicNetField[int](publicNetEntry, "ipv4"); err == nil && ipv4 != 0 { createPublicNet.EnableIPv4 = true - createPublicNet.IPv4 = &hcloud.PrimaryIP{ID: ipv4} + createPublicNet.IPv4 = &hcloud.PrimaryIP{ID: util.CastInt64(ipv4)} } - if ipv6, err := toServerPublicNet[int](publicNetEntry, "ipv6"); err == nil && ipv6 != 0 { + if ipv6, err := ToPublicNetField[int](publicNetEntry, "ipv6"); err == nil && ipv6 != 0 { createPublicNet.EnableIPv6 = true - createPublicNet.IPv6 = &hcloud.PrimaryIP{ID: ipv6} + createPublicNet.IPv6 = &hcloud.PrimaryIP{ID: util.CastInt64(ipv6)} } } opts.PublicNet = &createPublicNet @@ -397,7 +397,7 @@ func resourceServerCreate(ctx context.Context, d *schema.ResourceData, m interfa if err != nil { return hcloudutil.ErrorToDiag(err) } - d.SetId(strconv.Itoa(res.Server.ID)) + d.SetId(util.FormatID(res.Server.ID)) if err := hcloudutil.WaitForAction(ctx, &c.Action, res.Action); err != nil { return hcloudutil.ErrorToDiag(err) @@ -580,7 +580,7 @@ func resourceServerUpdate(ctx context.Context, d *schema.ResourceData, m interfa for _, f := range server.PublicNet.Firewalls { found := false for _, i := range firewallIDs { - fID := i.(int) + fID := util.CastInt64(i) if f.Firewall.ID == fID { found = true @@ -609,7 +609,7 @@ func resourceServerUpdate(ctx context.Context, d *schema.ResourceData, m interfa } for _, i := range firewallIDs { - fID := i.(int) + fID := util.CastInt64(i) found := false for _, f := range server.PublicNet.Firewalls { if f.Firewall.ID == fID { @@ -648,7 +648,7 @@ func resourceServerUpdate(ctx context.Context, d *schema.ResourceData, m interfa } if d.HasChange("placement_group_id") { - placementGroupID := d.Get("placement_group_id").(int) + placementGroupID := util.CastInt64(d.Get("placement_group_id")) if err := setPlacementGroup(ctx, c, server, placementGroupID); err != nil { return hcloudutil.ErrorToDiag(err) } @@ -670,18 +670,18 @@ func updatePublicNet(ctx context.Context, o interface{}, n interface{}, c *hclou diffToRemove := o.(*schema.Set).Difference(n.(*schema.Set)) diffToAdd := n.(*schema.Set).Difference(o.(*schema.Set)) - ipv4IDToRemove := 0 - ipv6IDToRemove := 0 + var ipv4IDToRemove int64 + var ipv6IDToRemove int64 ipv4EnabledInRemoveDiff := true ipv6EnabledInRemoveDiff := true // collect ip IDs which got removed for _, d := range diffToRemove.List() { fields := d.(map[string]interface{}) ipv4IDToRemove, ipv6IDToRemove = collectPrimaryIPIDs(fields) - if ipv4Enabled, err := toPublicNetPrimaryIPField[bool](fields, "ipv4_enabled"); err == nil { + if ipv4Enabled, err := ToPublicNetField[bool](fields, "ipv4_enabled"); err == nil { ipv4EnabledInRemoveDiff = ipv4Enabled } - if ipv6Enabled, err := toPublicNetPrimaryIPField[bool](fields, "ipv6_enabled"); err == nil { + if ipv6Enabled, err := ToPublicNetField[bool](fields, "ipv6_enabled"); err == nil { ipv6EnabledInRemoveDiff = ipv6Enabled } } @@ -720,7 +720,7 @@ func updatePublicNet(ctx context.Context, o interface{}, n interface{}, c *hclou fields := d.(map[string]interface{}) ipv4IDToAdd, ipv6IDToAdd := collectPrimaryIPIDs(fields) - if ipv4Enabled, err := toPublicNetPrimaryIPField[bool](fields, "ipv4_enabled"); err == nil { + if ipv4Enabled, err := ToPublicNetField[bool](fields, "ipv4_enabled"); err == nil { if err := publicNetUpdateDecision(ctx, c, ipv4Enabled, @@ -733,7 +733,7 @@ func updatePublicNet(ctx context.Context, o interface{}, n interface{}, c *hclou return err } } - if ipv6Enabled, err := toPublicNetPrimaryIPField[bool](fields, "ipv6_enabled"); err == nil { + if ipv6Enabled, err := ToPublicNetField[bool](fields, "ipv6_enabled"); err == nil { if err := publicNetUpdateDecision(ctx, c, ipv6Enabled, ipv6EnabledInRemoveDiff, @@ -758,10 +758,10 @@ func publicNetUpdateDecision(ctx context.Context, c *hcloud.Client, ipEnabled bool, ipEnabledInRemoveDiff bool, - ipID int, - ipIDInRemoveDiff int, + ipID int64, + ipIDInRemoveDiff int64, server *hcloud.Server, - serverIPID int, + serverIPID int64, ipType hcloud.PrimaryIPType) diag.Diagnostics { switch { // if ip set true + ip id, remove all previous assigned ipv4 + assign new @@ -840,7 +840,7 @@ func publicNetUpdateDecision(ctx context.Context, func resourceServerDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { client := m.(*hcloud.Client) - serverID, err := strconv.Atoi(d.Id()) + serverID, err := util.ParseID(d.Id()) if err != nil { log.Printf("[WARN] invalid server id (%s), removing from state: %v", d.Id(), err) d.SetId("") @@ -1044,7 +1044,7 @@ func getSSHkeys(ctx context.Context, client *hcloud.Client, d *schema.ResourceDa func inlineAttachServerToNetwork(ctx context.Context, c *hcloud.Client, s *hcloud.Server, nwData map[string]interface{}) error { const op = "hcloud/inlineAttachServerToNetwork" - nw := &hcloud.Network{ID: nwData["network_id"].(int)} + nw := &hcloud.Network{ID: util.CastInt64(nwData["network_id"])} ip := net.ParseIP(nwData["ip"].(string)) aliasIPs := make([]net.IP, 0, nwData["alias_ips"].(*schema.Set).Len()) @@ -1064,10 +1064,10 @@ func updateServerInlineNetworkAttachments(ctx context.Context, c *hcloud.Client, log.Printf("[INFO] Updating inline network attachments for server %d", s.ID) - cfgNetworks := make(map[int]map[string]interface{}, data.Len()) + cfgNetworks := make(map[int64]map[string]interface{}, data.Len()) for _, v := range data.List() { nwData := v.(map[string]interface{}) - nwID := nwData["network_id"].(int) + nwID := util.CastInt64(nwData["network_id"]) cfgNetworks[nwID] = nwData } @@ -1127,23 +1127,13 @@ func newIPSet(f schema.SchemaSetFunc, ips []net.IP) *schema.Set { } func setServerSchema(d *schema.ResourceData, s *hcloud.Server) { - for key, val := range getServerAttributes(d, s) { - switch key { - case "id": - d.SetId(strconv.Itoa(val.(int))) - default: - err := d.Set(key, val) - if err != nil { - log.Fatal(err) - } - } - } + util.SetSchemaFromAttributes(d, getServerAttributes(d, s)) } func getServerAttributes(d *schema.ResourceData, s *hcloud.Server) map[string]interface{} { firewallIDs := make([]int, len(s.PublicNet.Firewalls)) for i, firewall := range s.PublicNet.Firewalls { - firewallIDs[i] = firewall.Firewall.ID + firewallIDs[i] = int(firewall.Firewall.ID) } res := map[string]interface{}{ @@ -1177,7 +1167,7 @@ func getServerAttributes(d *schema.ResourceData, s *hcloud.Server) map[string]in } if s.Image != nil { - if s.Image.Name != "" && strconv.Itoa(s.Image.ID) != d.Get("image") { + if s.Image.Name != "" && util.FormatID(s.Image.ID) != d.Get("image") { // Only use the image name if the image is official (Name != "") // AND the user did not explicitly specify the image id res["image"] = s.Image.Name @@ -1199,7 +1189,7 @@ func getServerAttributes(d *schema.ResourceData, s *hcloud.Server) map[string]in } if s.PlacementGroup != nil { - res["placement_group_id"] = s.PlacementGroup.ID + res["placement_group_id"] = int(s.PlacementGroup.ID) } else { res["placement_group_id"] = nil } @@ -1224,7 +1214,7 @@ func networkToTerraformNetworks(privateNetworks []hcloud.ServerPrivateNet) []map return tfPrivateNetworks } -func getPlacementGroup(ctx context.Context, c *hcloud.Client, id int) (*hcloud.PlacementGroup, error) { +func getPlacementGroup(ctx context.Context, c *hcloud.Client, id int64) (*hcloud.PlacementGroup, error) { placementGroup, _, err := c.PlacementGroup.GetByID(ctx, id) if err != nil { return nil, err @@ -1237,7 +1227,7 @@ func getPlacementGroup(ctx context.Context, c *hcloud.Client, id int) (*hcloud.P return placementGroup, nil } -func setPlacementGroup(ctx context.Context, c *hcloud.Client, server *hcloud.Server, id int) error { +func setPlacementGroup(ctx context.Context, c *hcloud.Client, server *hcloud.Server, id int64) error { if server.PlacementGroup != nil { if server.Status != hcloud.ServerStatusOff { // Removing PG requires the server to be shut down before, this is an invasive operation. We do not currently @@ -1288,34 +1278,27 @@ func setProtection(ctx context.Context, c *hcloud.Client, server *hcloud.Server, return hcloudutil.WaitForAction(ctx, &c.Action, action) } -func toServerPublicNet[V int | bool](field map[string]interface{}, key string) (V, error) { - var op = "toServerPublicNet" - var valType V - if valType, ok := field[key].(V); ok { - return valType, nil - } - return valType, fmt.Errorf("%s: unable to apply value to public_net values", op) -} - -func collectPrimaryIPIDs(primaryIPList map[string]interface{}) (int, int) { - var IPv4ID = 0 - var IPv6ID = 0 - if id, err := toPublicNetPrimaryIPField[int](primaryIPList, "ipv4"); id != 0 && err == nil { - IPv4ID = id +func collectPrimaryIPIDs(primaryIPList map[string]interface{}) (int64, int64) { + var IPv4ID int64 + var IPv6ID int64 + if id, err := ToPublicNetField[int](primaryIPList, "ipv4"); id != 0 && err == nil { + IPv4ID = util.CastInt64(id) } - if id, err := toPublicNetPrimaryIPField[int](primaryIPList, "ipv6"); id != 0 && err == nil { - IPv6ID = id + if id, err := ToPublicNetField[int](primaryIPList, "ipv6"); id != 0 && err == nil { + IPv6ID = util.CastInt64(id) } return IPv4ID, IPv6ID } -func toPublicNetPrimaryIPField[V int | bool](field map[string]interface{}, key string) (V, error) { - var op = "toPublicNetPrimaryIPField" - var fieldValue V - if fieldValue, ok := field[key].(V); ok { - return fieldValue, nil +func ToPublicNetField[V int | bool](field map[string]interface{}, key string) (V, error) { + var op = "ToPublicNetField" + + if value, ok := field[key]; ok { + return value.(V), nil } - return fieldValue, fmt.Errorf("%s: field does not contain ID", op) + + var zero V + return zero, fmt.Errorf("%s: field does not contain key: %s", op, key) } func onServerCreateWithoutPublicNet(opts *hcloud.ServerCreateOpts, d *schema.ResourceData, fn func(opts *hcloud.ServerCreateOpts) error) diag.Diagnostics { @@ -1348,8 +1331,8 @@ func powerOnServer(ctx context.Context, c *hcloud.Client, server *hcloud.Server) func publicNetRemovedDecision(ctx context.Context, c *hcloud.Client, server *hcloud.Server, - serverIPID int, - ipIDToRemove int, + serverIPID int64, + ipIDToRemove int64, ipType hcloud.PrimaryIPType) diag.Diagnostics { if server.PublicNet.IPv4.ID != 0 && ipIDToRemove != 0 { if err := primaryip.UnassignPrimaryIP(ctx, c, serverIPID); err != nil { @@ -1374,7 +1357,7 @@ func validateUniqueNetworkIDs(d *schema.ResourceDiff) error { return fmt.Errorf("network has unexpected type: %T", n) } - uniqueNetworkIDs := map[int]bool{} + uniqueNetworkIDs := map[int64]bool{} for _, networkI := range networks.List() { network, ok := networkI.(map[string]interface{}) @@ -1382,11 +1365,11 @@ func validateUniqueNetworkIDs(d *schema.ResourceDiff) error { return fmt.Errorf("network item has unexpected type: %T", networkI) } - networkID, ok := network["network_id"] + networkIDI, ok := network["network_id"] if !ok { continue } - if networkID == 0 { + if util.CastInt64(networkIDI) == 0 { // ID is 0 if Network will be created in same apply, we are unable to reliably detect if the // "to-be-created" networks are the same. // See https://github.com/hetznercloud/terraform-provider-hcloud/issues/899 @@ -1397,13 +1380,9 @@ func validateUniqueNetworkIDs(d *schema.ResourceDiff) error { continue } - id, ok := networkID.(int) - if !ok { - return fmt.Errorf("network id has unexpected type: %T", networkID) - } - + id := util.CastInt64(networkIDI) if uniqueNetworkIDs[id] { - return fmt.Errorf("server is only allowed to be attached to each network once: %d", networkID) + return fmt.Errorf("server is only allowed to be attached to each network once: %d", networkIDI) } uniqueNetworkIDs[id] = true diff --git a/internal/server/resource_network.go b/internal/server/resource_network.go index 1c2804a9c..b052296d8 100644 --- a/internal/server/resource_network.go +++ b/internal/server/resource_network.go @@ -6,7 +6,6 @@ import ( "fmt" "log" "net" - "strconv" "strings" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -14,6 +13,7 @@ import ( "github.com/hetznercloud/hcloud-go/v2/hcloud" "github.com/hetznercloud/terraform-provider-hcloud/internal/network" + "github.com/hetznercloud/terraform-provider-hcloud/internal/util" "github.com/hetznercloud/terraform-provider-hcloud/internal/util/control" "github.com/hetznercloud/terraform-provider-hcloud/internal/util/hcloudutil" "github.com/hetznercloud/terraform-provider-hcloud/internal/util/merge" @@ -87,8 +87,8 @@ func resourceServerNetworkCreate(ctx context.Context, d *schema.ResourceData, m networkID = nwID } - server := &hcloud.Server{ID: d.Get("server_id").(int)} - n := &hcloud.Network{ID: networkID.(int)} + server := &hcloud.Server{ID: util.CastInt64(d.Get("server_id"))} + n := &hcloud.Network{ID: util.CastInt64(networkID)} aliasIPs := make([]net.IP, 0, d.Get("alias_ips").(*schema.Set).Len()) for _, aliasIP := range d.Get("alias_ips").(*schema.Set).List() { ip := net.ParseIP(aliasIP.(string)) @@ -268,7 +268,7 @@ func lookupServerNetworkID(ctx context.Context, terraformID string, client *hclo return } - serverID, err := strconv.Atoi(parts[0]) + serverID, err := util.ParseID(parts[0]) if err != nil { err = errInvalidServerNetworkID return @@ -284,7 +284,7 @@ func lookupServerNetworkID(ctx context.Context, terraformID string, client *hclo return } - networkID, err := strconv.Atoi(parts[1]) + networkID, err := util.ParseID(parts[1]) if err != nil { err = errInvalidServerNetworkID return diff --git a/internal/server/resource_test.go b/internal/server/resource_test.go index ab1e56f86..e4ae705d2 100644 --- a/internal/server/resource_test.go +++ b/internal/server/resource_test.go @@ -6,11 +6,11 @@ import ( "encoding/base64" "fmt" "regexp" - "strconv" "testing" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/hetznercloud/hcloud-go/v2/hcloud" "github.com/hetznercloud/terraform-provider-hcloud/internal/firewall" @@ -23,6 +23,7 @@ import ( "github.com/hetznercloud/terraform-provider-hcloud/internal/teste2e" "github.com/hetznercloud/terraform-provider-hcloud/internal/testsupport" "github.com/hetznercloud/terraform-provider-hcloud/internal/testtemplate" + "github.com/hetznercloud/terraform-provider-hcloud/internal/util" "github.com/hetznercloud/terraform-provider-hcloud/internal/util/hcloudutil" ) @@ -679,8 +680,8 @@ func TestAccServerResource_PrimaryIPNetworkTests(t *testing.T) { resource.TestCheckResourceAttr(sResWithNetAndPublicNet.TFID(), "network.0.ip", "10.0.1.5"), resource.TestCheckResourceAttr(sResWithNetAndPublicNet.TFID(), "network.0.alias_ips.#", "2"), testsupport.LiftTCF(func() error { - assert.NotEqual(t, 0, s.PublicNet.IPv4.ID) - assert.NotEqual(t, 0, s.PublicNet.IPv6.ID) + assert.NotEqual(t, int64(0), s.PublicNet.IPv4.ID) + assert.NotEqual(t, int64(0), s.PublicNet.IPv6.ID) return nil }), ), @@ -722,7 +723,7 @@ func TestAccServerResource_PrimaryIPNetworkTests(t *testing.T) { testsupport.LiftTCF(func() error { assert.Equal(t, p.AssigneeID, s.ID) assert.Equal(t, p.ID, s.PublicNet.IPv4.ID) - assert.Equal(t, 0, s.PublicNet.IPv6.ID) + assert.Equal(t, int64(0), s.PublicNet.IPv6.ID) return nil }), ), @@ -743,7 +744,7 @@ func TestAccServerResource_PrimaryIPNetworkTests(t *testing.T) { testsupport.LiftTCF(func() error { assert.Equal(t, p.AssigneeID, s.ID) assert.Equal(t, s.PublicNet.IPv4.ID, p.ID) - assert.NotEqual(t, 0, s.PublicNet.IPv6.ID) + assert.NotEqual(t, int64(0), s.PublicNet.IPv6.ID) return nil }), ), @@ -762,8 +763,8 @@ func TestAccServerResource_PrimaryIPNetworkTests(t *testing.T) { testsupport.CheckResourceExists(sResWithPrimaryIP.TFID(), server.ByID(t, &s)), testsupport.LiftTCF(func() error { assert.NotEqual(t, p.ID, s.PublicNet.IPv4.ID) - assert.NotEqual(t, 0, s.PublicNet.IPv4.ID) - assert.NotEqual(t, 0, s.PublicNet.IPv6.ID) + assert.NotEqual(t, int64(0), s.PublicNet.IPv4.ID) + assert.NotEqual(t, int64(0), s.PublicNet.IPv6.ID) return nil }), ), @@ -782,7 +783,7 @@ func TestAccServerResource_PrimaryIPNetworkTests(t *testing.T) { testsupport.CheckResourceExists(sResWithOnlyIPv6.TFID(), server.ByID(t, &s)), testsupport.LiftTCF(func() error { assert.Equal(t, p.ID, s.PublicNet.IPv6.ID) - assert.Equal(t, 0, s.PublicNet.IPv4.ID) + assert.Equal(t, int64(0), s.PublicNet.IPv4.ID) return nil }), ), @@ -801,8 +802,8 @@ func TestAccServerResource_PrimaryIPNetworkTests(t *testing.T) { testsupport.CheckResourceExists(sResWithOnlyIPv6AutoGenerated.TFID(), server.ByID(t, &s)), testsupport.LiftTCF(func() error { assert.NotEqual(t, p.ID, s.PublicNet.IPv4.ID) - assert.Equal(t, 0, s.PublicNet.IPv4.ID) - assert.NotEqual(t, 0, s.PublicNet.IPv6.ID) + assert.Equal(t, int64(0), s.PublicNet.IPv4.ID) + assert.NotEqual(t, int64(0), s.PublicNet.IPv6.ID) return nil }), ), @@ -1039,7 +1040,7 @@ func TestAccServerResource_PlacementGroup(t *testing.T) { resource.TestCheckResourceAttr(srvRes.TFID(), "server_type", srvRes.Type), resource.TestCheckResourceAttr(srvRes.TFID(), "image", srvRes.Image), testsupport.CheckResourceAttrFunc(srvRes.TFID(), "placement_group_id", func() string { - return strconv.Itoa(pg.ID) + return util.FormatID(pg.ID) }), ), }, @@ -1090,7 +1091,7 @@ func TestAccServerResource_PlacementGroup(t *testing.T) { Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr(srvResNoPG.TFID(), "status", "running"), testsupport.CheckResourceAttrFunc(srvRes.TFID(), "placement_group_id", func() string { - return strconv.Itoa(pg.ID) + return util.FormatID(pg.ID) }), ), }, @@ -1199,3 +1200,29 @@ func userDataHashSum(userData string) string { sum := sha1.Sum([]byte(userData)) // nolint: gosec return base64.StdEncoding.EncodeToString(sum[:]) } + +func TestToPublicNetField(t *testing.T) { + t.Run("int", func(t *testing.T) { + got, err := server.ToPublicNetField[int](map[string]any{"key": int(1)}, "key") + require.NoError(t, err) + require.Equal(t, int(1), got) + }) + + t.Run("bool", func(t *testing.T) { + got, err := server.ToPublicNetField[bool](map[string]any{"key": true}, "key") + require.NoError(t, err) + require.Equal(t, true, got) + }) + + t.Run("int not found", func(t *testing.T) { + got, err := server.ToPublicNetField[int](map[string]any{}, "key") + require.EqualError(t, err, "ToPublicNetField: field does not contain key: key") + require.Equal(t, int(0), got) + }) + + t.Run("bool not found", func(t *testing.T) { + got, err := server.ToPublicNetField[bool](map[string]any{}, "key") + require.EqualError(t, err, "ToPublicNetField: field does not contain key: key") + require.Equal(t, false, got) + }) +} diff --git a/internal/teste2e/testing.go b/internal/teste2e/testing.go index 7475b6d72..491dabdda 100644 --- a/internal/teste2e/testing.go +++ b/internal/teste2e/testing.go @@ -35,10 +35,10 @@ var ( TestLoadBalancerType = "lb11" // TestDataCenter is the default datacenter where we execute our tests. - TestDataCenter = getEnv("TEST_DATACENTER", "nbg1-dc3") + TestDataCenter = getEnv("TEST_DATACENTER", "hel1-dc2") // TestLocationName is the default location where we execute our tests. - TestLocationName = getEnv("TEST_LOCATION", "nbg1") + TestLocationName = getEnv("TEST_LOCATION", "hel1") ) func ProtoV6ProviderFactories() map[string]func() (tfprotov6.ProviderServer, error) { diff --git a/internal/testsupport/check.go b/internal/testsupport/check.go index afc58f695..0f1feb24e 100644 --- a/internal/testsupport/check.go +++ b/internal/testsupport/check.go @@ -3,13 +3,13 @@ package testsupport import ( "errors" "fmt" - "strconv" "github.com/hashicorp/go-multierror" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" "github.com/hetznercloud/hcloud-go/v2/hcloud" + "github.com/hetznercloud/terraform-provider-hcloud/internal/util" ) // KeyFunc allows to retrieve a resource from the Hetzner Cloud backend using @@ -64,7 +64,7 @@ func backendResourceByKey(s *terraform.State, name string, k KeyFunc) error { if rs.Primary.ID == "" { return fmt.Errorf("%s: resource %s: no primary id", op, name) } - id, err := strconv.Atoi(rs.Primary.ID) + id, err := util.ParseID(rs.Primary.ID) if err != nil { return fmt.Errorf("%s: resource %s: primary id: %w", op, name, err) }