Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ website:
.PHONY: build test testacc vet fmt fmtcheck errcheck test-compile website

tfproviderlint:
go tool tfproviderlint -R014=false -AT001.ignored-filename-suffixes=_data_source_test.go ./...
go tool tfproviderlint -R014=false -S013=false -AT001.ignored-filename-suffixes=_data_source_test.go ./...

tfproviderdocs:
go tool tfproviderdocs check -provider-name scaleway -enable-contents-check

tfproviderlintx:
go tool tfproviderlintx -XR001=false -XS002=false ./...
go tool tfproviderlintx -XR001=false -S013=false -XS002=false ./...
68 changes: 68 additions & 0 deletions internal/locality/regional/ids.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package regional

import (
"context"
"errors"
"fmt"
"strings"

"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/scaleway/scaleway-sdk-go/scw"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality"
)
Expand Down Expand Up @@ -81,3 +85,67 @@ func ParseID(regionalID string) (region scw.Region, id string, err error) {

return
}

func ResolveRegionAndID(
ctx context.Context,
d *schema.ResourceData,
fallbackDefaultRegion func(*schema.ResourceData) (scw.Region, error),
) (scw.Region, string, error) {
identity, err := d.Identity()
if err != nil {
tflog.Warn(ctx, fmt.Sprintf("failed to read identity from ResourceData: %v", err))
} else if identity != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you flatten more and resolve early in case :

  • identity is nil,
  • identity does not contain id and resolve with a specific diagnostic
  • identity does not contain region and resolve with a specific diagnostic

if v := identity.Get("id"); v != nil {
id, _ := v.(string)
if id != "" {
if rv := identity.Get("region"); rv != nil {
if rstr, ok := rv.(string); ok && rstr != "" {
return scw.Region(rstr), id, nil
}
}

if sid := d.Id(); sid != "" {
regionFromState, _, err := ParseID(sid)
if err != nil {
tflog.Warn(ctx, fmt.Sprintf("failed to parse region from state ID %q: %v", sid, err))
} else if regionFromState != "" {
return regionFromState, id, nil
}
}

if fallbackDefaultRegion != nil {
region, err := fallbackDefaultRegion(d)
if err != nil {
tflog.Warn(ctx, fmt.Sprintf("fallbackDefaultRegion error for ID %q: %v", id, err))
} else if region != "" {
return region, id, nil
}
}

return "", "", fmt.Errorf("cannot resolve region for identity (id=%q)", id)
}
}
}

sid := d.Id()
if sid == "" {
tflog.Error(ctx, "cannot resolve identity: both identity.id and state ID are empty")

return "", "", errors.New("cannot resolve identity: both identity.id and state ID are empty")
}

region, id, err := ParseID(sid)
if err != nil {
tflog.Error(ctx, fmt.Sprintf("failed to parse region/ID from state ID %q: %v", sid, err))

return "", "", err
}

if id == "" {
tflog.Error(ctx, fmt.Sprintf("empty ID parsed from state ID %q", sid))

return "", "", fmt.Errorf("empty ID parsed from state ID %q", sid)
}

return region, id, nil
}
4,311 changes: 1,787 additions & 2,524 deletions internal/services/baremetal/testdata/server-with-ipam-private-network.cassette.yaml

Large diffs are not rendered by default.

30 changes: 26 additions & 4 deletions internal/services/vpc/acl.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,24 @@ func ResourceACL() *schema.Resource {
UpdateContext: ResourceVPCACLUpdate,
DeleteContext: ResourceVPCACLDelete,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
StateContext: schema.ImportStatePassthroughWithIdentity("id"),
},
Identity: &schema.ResourceIdentity{
Version: 0,
SchemaFunc: func() map[string]*schema.Schema {
return map[string]*schema.Schema{
"id": {
Type: schema.TypeString,
RequiredForImport: true,
Description: "The ACL ID (e.g. `11111111-1111-1111-1111-111111111111`)",
},
"region": {
Type: schema.TypeString,
OptionalForImport: true,
Description: "The region of the VPC. If omitted during import, defaults from provider",
},
}
},
},
SchemaVersion: 0,
Schema: map[string]*schema.Schema{
Expand Down Expand Up @@ -133,11 +150,16 @@ func ResourceVPCACLCreate(ctx context.Context, d *schema.ResourceData, m any) di

d.SetId(regional.NewIDString(region, regional.ExpandID(d.Get("vpc_id").(string)).ID))

if identity, err := d.Identity(); err == nil && identity != nil {
_ = identity.Set("id", regional.ExpandID(d.Get("vpc_id").(string)).ID)
_ = identity.Set("region", region)
}

return ResourceVPCACLRead(ctx, d, m)
}

func ResourceVPCACLRead(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
vpcAPI, region, ID, err := NewAPIWithRegionAndID(m, d.Id())
vpcAPI, region, ID, err := NewAPIWithRegionAndIDFromState(ctx, m, d)
if err != nil {
return diag.FromErr(err)
}
Expand All @@ -164,7 +186,7 @@ func ResourceVPCACLRead(ctx context.Context, d *schema.ResourceData, m any) diag
}

func ResourceVPCACLUpdate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
vpcAPI, region, ID, err := NewAPIWithRegionAndID(m, d.Id())
vpcAPI, region, ID, err := NewAPIWithRegionAndIDFromState(ctx, m, d)
if err != nil {
return diag.FromErr(err)
}
Expand Down Expand Up @@ -194,7 +216,7 @@ func ResourceVPCACLUpdate(ctx context.Context, d *schema.ResourceData, m any) di
}

func ResourceVPCACLDelete(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
vpcAPI, region, ID, err := NewAPIWithRegionAndID(m, d.Id())
vpcAPI, region, ID, err := NewAPIWithRegionAndIDFromState(ctx, m, d)
if err != nil {
return diag.FromErr(err)
}
Expand Down
20 changes: 20 additions & 0 deletions internal/services/vpc/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,26 @@ func NewAPIWithRegionAndID(m any, id string) (*vpc.API, scw.Region, string, erro
return vpcAPI, region, ID, err
}

func NewAPIWithRegionAndIDFromState(ctx context.Context, m any, d *schema.ResourceData) (
*vpc.API,
scw.Region,
string,
error,
) {
vpcAPI := vpc.NewAPI(meta.ExtractScwClient(m))

region, ID, err := regional.ResolveRegionAndID(ctx, d, func(d *schema.ResourceData) (scw.Region, error) {
_, provRegion, err := vpcAPIWithRegion(d, m)

return provRegion, err
})
if err != nil {
return nil, "", "", err
}

return vpcAPI, region, ID, nil
}

func NewAPI(m any) (*vpc.API, error) {
return vpc.NewAPI(meta.ExtractScwClient(m)), nil
}
Expand Down
43 changes: 39 additions & 4 deletions internal/services/vpc/private_network.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,24 @@ func ResourcePrivateNetwork() *schema.Resource {
UpdateContext: ResourceVPCPrivateNetworkUpdate,
DeleteContext: ResourceVPCPrivateNetworkDelete,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
StateContext: schema.ImportStatePassthroughWithIdentity("id"),
},
Identity: &schema.ResourceIdentity{
Version: 0,
SchemaFunc: func() map[string]*schema.Schema {
return map[string]*schema.Schema{
"id": {
Type: schema.TypeString,
RequiredForImport: true,
Description: "The Private Network ID (e.g. `11111111-1111-1111-1111-111111111111`)",
},
"region": {
Type: schema.TypeString,
OptionalForImport: true,
Description: "The region of the VPC. If omitted during import, defaults from provider",
},
}
},
},
SchemaVersion: 1,
StateUpgraders: []schema.StateUpgrader{
Expand Down Expand Up @@ -230,11 +247,24 @@ func ResourceVPCPrivateNetworkCreate(ctx context.Context, d *schema.ResourceData

d.SetId(regional.NewIDString(region, pn.ID))

identity, err := d.Identity()
if err != nil {
return diag.FromErr(err)
}

if err = identity.Set("id", pn.ID); err != nil {
return diag.FromErr(err)
}

if err = identity.Set("region", region); err != nil {
return diag.FromErr(err)
}

return ResourceVPCPrivateNetworkRead(ctx, d, m)
}

func ResourceVPCPrivateNetworkRead(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
vpcAPI, region, ID, err := NewAPIWithRegionAndID(m, d.Id())
vpcAPI, region, ID, err := NewAPIWithRegionAndIDFromState(ctx, m, d)
if err != nil {
return diag.FromErr(err)
}
Expand Down Expand Up @@ -274,11 +304,16 @@ func ResourceVPCPrivateNetworkRead(ctx context.Context, d *schema.ResourceData,
_ = d.Set("ipv4_subnet", ipv4Subnet)
_ = d.Set("ipv6_subnets", ipv6Subnets)

if identity, err := d.Identity(); err == nil && identity != nil {
_ = identity.Set("id", pn.ID)
_ = identity.Set("region", region)
}

return nil
}

func ResourceVPCPrivateNetworkUpdate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
vpcAPI, region, ID, err := NewAPIWithRegionAndID(m, d.Id())
vpcAPI, region, ID, err := NewAPIWithRegionAndIDFromState(ctx, m, d)
if err != nil {
return diag.FromErr(err)
}
Expand All @@ -298,7 +333,7 @@ func ResourceVPCPrivateNetworkUpdate(ctx context.Context, d *schema.ResourceData
}

func ResourceVPCPrivateNetworkDelete(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
vpcAPI, region, ID, err := NewAPIWithRegionAndID(m, d.Id())
vpcAPI, region, ID, err := NewAPIWithRegionAndIDFromState(ctx, m, d)
if err != nil {
return diag.FromErr(err)
}
Expand Down
43 changes: 39 additions & 4 deletions internal/services/vpc/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,24 @@ func ResourceRoute() *schema.Resource {
UpdateContext: ResourceRouteUpdate,
DeleteContext: ResourceRouteDelete,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
StateContext: schema.ImportStatePassthroughWithIdentity("id"),
},
Identity: &schema.ResourceIdentity{
Version: 0,
SchemaFunc: func() map[string]*schema.Schema {
return map[string]*schema.Schema{
"id": {
Type: schema.TypeString,
RequiredForImport: true,
Description: "The Route ID (e.g. `11111111-1111-1111-1111-111111111111`)",
},
"region": {
Type: schema.TypeString,
OptionalForImport: true,
Description: "The region of the VPC. If omitted during import, defaults from provider",
},
}
},
},
SchemaVersion: 0,
Schema: map[string]*schema.Schema{
Expand Down Expand Up @@ -111,11 +128,24 @@ func ResourceRouteCreate(ctx context.Context, d *schema.ResourceData, m any) dia

d.SetId(regional.NewIDString(region, res.ID))

identity, err := d.Identity()
if err != nil {
return diag.FromErr(err)
}

if err = identity.Set("id", res.ID); err != nil {
return diag.FromErr(err)
}

if err = identity.Set("region", region); err != nil {
return diag.FromErr(err)
}

return ResourceRouteRead(ctx, d, m)
}

func ResourceRouteRead(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
vpcAPI, region, ID, err := NewAPIWithRegionAndID(m, d.Id())
vpcAPI, region, ID, err := NewAPIWithRegionAndIDFromState(ctx, m, d)
if err != nil {
return diag.FromErr(err)
}
Expand Down Expand Up @@ -153,11 +183,16 @@ func ResourceRouteRead(ctx context.Context, d *schema.ResourceData, m any) diag.
_ = d.Set("tags", res.Tags)
}

if identity, err := d.Identity(); err == nil && identity != nil {
_ = identity.Set("id", res.ID)
_ = identity.Set("region", region)
}

return nil
}

func ResourceRouteUpdate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
vpcAPI, region, ID, err := NewAPIWithRegionAndID(m, d.Id())
vpcAPI, region, ID, err := NewAPIWithRegionAndIDFromState(ctx, m, d)
if err != nil {
return diag.FromErr(err)
}
Expand Down Expand Up @@ -215,7 +250,7 @@ func ResourceRouteUpdate(ctx context.Context, d *schema.ResourceData, m any) dia
}

func ResourceRouteDelete(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
vpcAPI, region, ID, err := NewAPIWithRegionAndID(m, d.Id())
vpcAPI, region, ID, err := NewAPIWithRegionAndIDFromState(ctx, m, d)
if err != nil {
return diag.FromErr(err)
}
Expand Down
Loading
Loading