Skip to content

Commit 0900ae6

Browse files
authored
private_ips as optional attribute, only set it when no error occurred (#3094)
1 parent e6951d6 commit 0900ae6

28 files changed

+20516
-17842
lines changed

internal/services/baremetal/server.go

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ If this behaviour is wanted, please set 'reinstall_on_ssh_key_changes' argument
273273
"private_ips": {
274274
Type: schema.TypeList,
275275
Computed: true,
276+
Optional: true,
276277
Description: "List of private IPv4 and IPv6 addresses associated with the resource",
277278
Elem: &schema.Resource{
278279
Schema: map[string]*schema.Schema{
@@ -534,6 +535,7 @@ func ResourceServerRead(ctx context.Context, d *schema.ResourceData, m interface
534535
privateNetworkIDs = append(privateNetworkIDs, pn.PrivateNetworkID)
535536
}
536537

538+
// Read private IPs if possible
537539
allPrivateIPs := make([]map[string]interface{}, 0, listPrivateNetworks.TotalCount)
538540
diags := diag.Diagnostics{}
539541

@@ -542,25 +544,29 @@ func ResourceServerRead(ctx context.Context, d *schema.ResourceData, m interface
542544
opts := &ipam.GetResourcePrivateIPsOptions{
543545
ResourceType: &resourceType,
544546
PrivateNetworkID: &privateNetworkID,
547+
ProjectID: &server.ProjectID,
545548
}
546549

547550
privateIPs, err := ipam.GetResourcePrivateIPs(ctx, m, pnRegion, opts)
548-
if err != nil {
549-
if !httperrors.Is403(err) {
550-
return diag.FromErr(err)
551-
}
552551

552+
switch {
553+
case err == nil:
554+
allPrivateIPs = append(allPrivateIPs, privateIPs...)
555+
case httperrors.Is403(err):
556+
return append(diags, diag.Diagnostic{
557+
Severity: diag.Warning,
558+
Summary: "Unauthorized to read server's private IPs, please check your IAM permissions",
559+
Detail: err.Error(),
560+
AttributePath: cty.GetAttrPath("private_ips"),
561+
})
562+
default:
553563
diags = append(diags, diag.Diagnostic{
554564
Severity: diag.Warning,
555-
Summary: err.Error(),
556-
Detail: "Got 403 while reading private IPs from IPAM API, please check your IAM permissions",
565+
Summary: fmt.Sprintf("Unable to get private IPs for server %s (pn_id: %s)", server.ID, privateNetworkID),
566+
Detail: err.Error(),
557567
AttributePath: cty.GetAttrPath("private_ips"),
558568
})
559569
}
560-
561-
if privateIPs != nil {
562-
allPrivateIPs = append(allPrivateIPs, privateIPs...)
563-
}
564570
}
565571

566572
_ = d.Set("private_ips", allPrivateIPs)

internal/services/baremetal/testdata/server-create-server-with-private-network.cassette.yaml

Lines changed: 671 additions & 622 deletions
Large diffs are not rendered by default.

internal/services/instance/helpers_instance.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,3 +536,19 @@ func prepareRootVolume(rootVolumeI map[string]any, serverType *instance.ServerTy
536536
Boot: rootVolumeIsBootVolume,
537537
}
538538
}
539+
540+
func getServerProjectID(ctx context.Context, api *instance.API, zone scw.Zone, serverID string) (string, error) {
541+
server, err := api.GetServer(&instance.GetServerRequest{
542+
Zone: zone,
543+
ServerID: serverID,
544+
}, scw.WithContext(ctx))
545+
if err != nil {
546+
return "", fmt.Errorf("get private NIC's project ID: error getting server %s", serverID)
547+
}
548+
549+
if server.Server.Project == "" {
550+
return "", fmt.Errorf("no project ID found for server %s", serverID)
551+
}
552+
553+
return server.Server.Project, nil
554+
}

internal/services/instance/private_nic.go

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package instance
22

33
import (
44
"context"
5+
"fmt"
56

67
"github.com/hashicorp/go-cty/cty"
78
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
@@ -74,6 +75,7 @@ func ResourcePrivateNIC() *schema.Resource {
7475
"private_ips": {
7576
Type: schema.TypeList,
7677
Computed: true,
78+
Optional: true,
7779
Description: "List of private IPv4 and IPv6 addresses associated with the resource",
7880
Elem: &schema.Resource{
7981
Schema: map[string]*schema.Schema{
@@ -185,35 +187,56 @@ func ResourceInstancePrivateNICRead(ctx context.Context, d *schema.ResourceData,
185187
_ = d.Set("tags", privateNIC.Tags)
186188
}
187189

190+
// Get private NIC's private IPs if possible
191+
diags := diag.Diagnostics{}
192+
188193
region, err := zone.Region()
189194
if err != nil {
190-
return diag.FromErr(err)
195+
return append(diags, diag.Diagnostic{
196+
Severity: diag.Warning,
197+
Summary: "Unable to get private NIC's private IPs",
198+
Detail: err.Error(),
199+
})
200+
}
201+
202+
projectID, err := getServerProjectID(ctx, instanceAPI, zone, privateNIC.ServerID)
203+
if err != nil {
204+
return append(diags, diag.Diagnostic{
205+
Severity: diag.Warning,
206+
Summary: "Unable to get private NIC's private IPs",
207+
Detail: err.Error(),
208+
})
191209
}
192210

193-
diags := diag.Diagnostics{}
194211
resourceType := ipamAPI.ResourceTypeInstancePrivateNic
195212
opts := &ipam.GetResourcePrivateIPsOptions{
196213
ResourceID: &privateNIC.ID,
197214
ResourceType: &resourceType,
198215
PrivateNetworkID: &privateNIC.PrivateNetworkID,
216+
ProjectID: &projectID,
199217
}
200218

201219
privateIPs, err := ipam.GetResourcePrivateIPs(ctx, m, region, opts)
202-
if err != nil {
203-
if !httperrors.Is403(err) {
204-
return diag.FromErr(err)
205-
}
206220

221+
switch {
222+
case err == nil:
223+
_ = d.Set("private_ips", privateIPs)
224+
case httperrors.Is403(err):
207225
diags = append(diags, diag.Diagnostic{
208226
Severity: diag.Warning,
209-
Summary: err.Error(),
210-
Detail: "Got 403 while reading private IPs from IPAM API, please check your IAM permissions",
227+
Summary: "Unauthorized to read private NIC's private IPs, please check your IAM permissions",
228+
Detail: err.Error(),
229+
AttributePath: cty.GetAttrPath("private_ips"),
230+
})
231+
default:
232+
diags = append(diags, diag.Diagnostic{
233+
Severity: diag.Warning,
234+
Summary: fmt.Sprintf("Unable to get private IPs for pnic %s (server_id: %s)", privateNIC.ID, privateNIC.ServerID),
235+
Detail: err.Error(),
211236
AttributePath: cty.GetAttrPath("private_ips"),
212237
})
213238
}
214239

215-
_ = d.Set("private_ips", privateIPs)
216-
217240
return diags
218241
}
219242

internal/services/instance/server.go

Lines changed: 56 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ func ResourceServer() *schema.Resource {
355355
"private_ips": {
356356
Type: schema.TypeList,
357357
Computed: true,
358+
Optional: true,
358359
Description: "List of private IPv4 addresses associated with the resource",
359360
Elem: &schema.Resource{
360361
Schema: map[string]*schema.Schema{
@@ -780,6 +781,41 @@ func ResourceInstanceServerRead(ctx context.Context, d *schema.ResourceData, m i
780781

781782
_ = d.Set("user_data", userData)
782783

784+
////
785+
// Display warning if server will soon reach End of Service
786+
////
787+
diags := diag.Diagnostics{}
788+
789+
if server.EndOfService {
790+
compatibleTypes, err := api.GetServerCompatibleTypes(&instanceSDK.GetServerCompatibleTypesRequest{
791+
Zone: zone,
792+
ServerID: id,
793+
}, scw.WithContext(ctx))
794+
if err != nil {
795+
return diag.FromErr(err)
796+
}
797+
798+
mostRelevantTypes := compatibleTypes.CompatibleTypes[:5]
799+
800+
diags = append(diags, diag.Diagnostic{
801+
Severity: diag.Warning,
802+
Detail: fmt.Sprintf("Instance type %q will soon reach End of Service", server.CommercialType),
803+
Summary: fmt.Sprintf(`Your Instance will soon reach End of Service. You can check the exact date on the Scaleway console. We recommend that you migrate your Instance before that.
804+
Here are the %d best options for %q, ordered by relevance: [%s]
805+
806+
You can check the full list of compatible server types:
807+
- on the Scaleway console
808+
- using the CLI command 'scw instance server get-compatible-types %s zone=%s'`,
809+
len(mostRelevantTypes),
810+
server.CommercialType,
811+
strings.Join(mostRelevantTypes, ", "),
812+
server.ID,
813+
server.Zone,
814+
),
815+
AttributePath: cty.GetAttrPath("type"),
816+
})
817+
}
818+
783819
////
784820
// Read server private networks
785821
////
@@ -799,75 +835,50 @@ func ResourceInstanceServerRead(ctx context.Context, d *schema.ResourceData, m i
799835
privateNICIDs = append(privateNICIDs, nic.ID)
800836
}
801837

838+
// Read server's private IPs if possible
802839
allPrivateIPs := []map[string]interface{}(nil)
803-
diags := diag.Diagnostics{}
804840
resourceType := ipamAPI.ResourceTypeInstancePrivateNic
805841

806842
region, err := zone.Region()
807843
if err != nil {
808-
return diag.FromErr(err)
844+
return append(diags, diag.Diagnostic{
845+
Severity: diag.Warning,
846+
Summary: "Unable to get server's private IPs",
847+
Detail: err.Error(),
848+
})
809849
}
810850

811851
for _, nicID := range privateNICIDs {
812852
opts := &ipam.GetResourcePrivateIPsOptions{
813853
ResourceType: &resourceType,
814854
ResourceID: &nicID,
855+
ProjectID: &server.Project,
815856
}
816857

817858
privateIPs, err := ipam.GetResourcePrivateIPs(ctx, m, region, opts)
818-
if err != nil {
819-
if !httperrors.Is403(err) {
820-
return diag.FromErr(err)
821-
}
822859

860+
switch {
861+
case err == nil:
862+
allPrivateIPs = append(allPrivateIPs, privateIPs...)
863+
case httperrors.Is403(err):
864+
return append(diags, diag.Diagnostic{
865+
Severity: diag.Warning,
866+
Summary: "Unauthorized to read server's private IPs, please check your IAM permissions",
867+
Detail: err.Error(),
868+
AttributePath: cty.GetAttrPath("private_ips"),
869+
})
870+
default:
823871
diags = append(diags, diag.Diagnostic{
824872
Severity: diag.Warning,
825-
Summary: err.Error(),
826-
Detail: "Got 403 while reading private IPs from IPAM API, please check your IAM permissions",
873+
Summary: fmt.Sprintf("Unable to get private IPs for server %s (pnic_id: %s)", server.ID, nicID),
874+
Detail: err.Error(),
827875
AttributePath: cty.GetAttrPath("private_ips"),
828876
})
829877
}
830-
831-
if privateIPs != nil {
832-
allPrivateIPs = append(allPrivateIPs, privateIPs...)
833-
}
834878
}
835879

836880
_ = d.Set("private_ips", allPrivateIPs)
837881

838-
////
839-
// Display warning if server will soon reach End of Service
840-
////
841-
if server.EndOfService {
842-
compatibleTypes, err := api.GetServerCompatibleTypes(&instanceSDK.GetServerCompatibleTypesRequest{
843-
Zone: zone,
844-
ServerID: id,
845-
}, scw.WithContext(ctx))
846-
if err != nil {
847-
return diag.FromErr(err)
848-
}
849-
850-
mostRelevantTypes := compatibleTypes.CompatibleTypes[:5]
851-
852-
diags = append(diags, diag.Diagnostic{
853-
Severity: diag.Warning,
854-
Detail: fmt.Sprintf("Instance type %q will soon reach End of Service", server.CommercialType),
855-
Summary: fmt.Sprintf(`Your Instance will soon reach End of Service. You can check the exact date on the Scaleway console. We recommend that you migrate your Instance before that.
856-
Here are the %d best options for %q, ordered by relevance: [%s]
857-
858-
You can check the full list of compatible server types:
859-
- on the Scaleway console
860-
- using the CLI command 'scw instance server get-compatible-types %s zone=%s'`,
861-
len(mostRelevantTypes),
862-
server.CommercialType,
863-
strings.Join(mostRelevantTypes, ", "),
864-
server.ID,
865-
server.Zone,
866-
),
867-
AttributePath: cty.GetAttrPath("type"),
868-
})
869-
}
870-
871882
return diags
872883
}
873884

internal/services/instance/testdata/data-source-private-nic-basic.cassette.yaml

Lines changed: 1974 additions & 1043 deletions
Large diffs are not rendered by default.

internal/services/instance/testdata/private-nic-basic.cassette.yaml

Lines changed: 469 additions & 420 deletions
Large diffs are not rendered by default.

internal/services/instance/testdata/private-nic-tags.cassette.yaml

Lines changed: 1034 additions & 642 deletions
Large diffs are not rendered by default.

internal/services/instance/testdata/private-nic-with-ipam.cassette.yaml

Lines changed: 707 additions & 560 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)