Skip to content

Commit dbcbc4f

Browse files
Mia-Crossyfodil
andauthored
feat(baremetal): read private ips (#3071)
Co-authored-by: Yacine Fodil <[email protected]>
1 parent e04ed3c commit dbcbc4f

8 files changed

+7894
-5462
lines changed

docs/resources/baremetal_server.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,9 @@ In addition to all arguments above, the following attributes are exported:
321321
- `status` - The private network status.
322322
- `created_at` - The date and time of the creation of the private network.
323323
- `updated_at` - The date and time of the last update of the private network.
324+
- `private_ips` - The list of private IPv4 and IPv6 addresses associated with the resource.
325+
- `id` - The ID of the IP address resource.
326+
- `address` - The private IP address.
324327
- `ips` - (List of) The IPs of the server.
325328
- `id` - The ID of the IP.
326329
- `address` - The address of the IP.

internal/services/baremetal/server.go

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
1313
"github.com/scaleway/scaleway-sdk-go/api/baremetal/v1"
1414
baremetalV3 "github.com/scaleway/scaleway-sdk-go/api/baremetal/v3"
15+
ipamAPI "github.com/scaleway/scaleway-sdk-go/api/ipam/v1"
1516
"github.com/scaleway/scaleway-sdk-go/scw"
1617
sdkValidation "github.com/scaleway/scaleway-sdk-go/validation"
1718
"github.com/scaleway/terraform-provider-scaleway/v2/internal/cdf"
@@ -21,6 +22,7 @@ import (
2122
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality/regional"
2223
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality/zonal"
2324
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/account"
25+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/ipam"
2426
"github.com/scaleway/terraform-provider-scaleway/v2/internal/types"
2527
"github.com/scaleway/terraform-provider-scaleway/v2/internal/verify"
2628
)
@@ -268,6 +270,25 @@ If this behaviour is wanted, please set 'reinstall_on_ssh_key_changes' argument
268270
Optional: true,
269271
Description: "The partitioning schema in json format",
270272
},
273+
"private_ips": {
274+
Type: schema.TypeList,
275+
Computed: true,
276+
Description: "List of private IPv4 and IPv6 addresses associated with the resource",
277+
Elem: &schema.Resource{
278+
Schema: map[string]*schema.Schema{
279+
"id": {
280+
Type: schema.TypeString,
281+
Computed: true,
282+
Description: "The ID of the IP address resource",
283+
},
284+
"address": {
285+
Type: schema.TypeString,
286+
Computed: true,
287+
Description: "The private IP address",
288+
},
289+
},
290+
},
291+
},
271292
},
272293
CustomizeDiff: customdiff.Sequence(
273294
customDiffOffer(),
@@ -508,7 +529,43 @@ func ResourceServerRead(ctx context.Context, d *schema.ResourceData, m interface
508529

509530
_ = d.Set("private_network", flattenPrivateNetworks(pnRegion, listPrivateNetworks.ServerPrivateNetworks))
510531

511-
return nil
532+
privateNetworkIDs := make([]string, 0, listPrivateNetworks.TotalCount)
533+
for _, pn := range listPrivateNetworks.ServerPrivateNetworks {
534+
privateNetworkIDs = append(privateNetworkIDs, pn.PrivateNetworkID)
535+
}
536+
537+
allPrivateIPs := make([]map[string]interface{}, 0, listPrivateNetworks.TotalCount)
538+
diags := diag.Diagnostics{}
539+
540+
for _, privateNetworkID := range privateNetworkIDs {
541+
resourceType := ipamAPI.ResourceTypeBaremetalPrivateNic
542+
opts := &ipam.GetResourcePrivateIPsOptions{
543+
ResourceType: &resourceType,
544+
PrivateNetworkID: &privateNetworkID,
545+
}
546+
547+
privateIPs, err := ipam.GetResourcePrivateIPs(ctx, m, pnRegion, opts)
548+
if err != nil {
549+
if !httperrors.Is403(err) {
550+
return diag.FromErr(err)
551+
}
552+
553+
diags = append(diags, diag.Diagnostic{
554+
Severity: diag.Warning,
555+
Summary: err.Error(),
556+
Detail: "Got 403 while reading private IPs from IPAM API, please check your IAM permissions",
557+
AttributePath: cty.GetAttrPath("private_ips"),
558+
})
559+
}
560+
561+
if privateIPs != nil {
562+
allPrivateIPs = append(allPrivateIPs, privateIPs...)
563+
}
564+
}
565+
566+
_ = d.Set("private_ips", allPrivateIPs)
567+
568+
return diags
512569
}
513570

514571
//gocyclo:ignore

internal/services/baremetal/server_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,8 @@ func TestAccServer_CreateServerWithPrivateNetwork(t *testing.T) {
613613
testAccCheckBaremetalServerExists(tt, "scaleway_baremetal_server.base"),
614614
testAccCheckBaremetalServerHasPrivateNetwork(tt, "scaleway_baremetal_server.base"),
615615
resource.TestCheckResourceAttrPair("scaleway_baremetal_server.base", "private_network.0.id", "scaleway_vpc_private_network.pn", "id"),
616+
resource.TestCheckResourceAttrSet("scaleway_baremetal_server.base", "private_ips.0.id"),
617+
resource.TestCheckResourceAttrSet("scaleway_baremetal_server.base", "private_ips.0.address"),
616618
),
617619
},
618620
},

internal/services/baremetal/testdata/server-add-another-private-network.cassette.yaml

Lines changed: 2110 additions & 1473 deletions
Large diffs are not rendered by default.

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

Lines changed: 1963 additions & 1277 deletions
Large diffs are not rendered by default.

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

Lines changed: 1588 additions & 1000 deletions
Large diffs are not rendered by default.

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

Lines changed: 2103 additions & 1711 deletions
Large diffs are not rendered by default.

internal/services/ipam/helpers.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
package ipam
22

33
import (
4+
"context"
5+
"fmt"
46
"net"
57
"time"
68

79
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
810
ipam "github.com/scaleway/scaleway-sdk-go/api/ipam/v1"
911
"github.com/scaleway/scaleway-sdk-go/scw"
12+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/httperrors"
1013
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality/regional"
1114
"github.com/scaleway/terraform-provider-scaleway/v2/internal/meta"
1215
)
@@ -65,3 +68,67 @@ func diffSuppressFuncStandaloneIPandCIDR(_, oldValue, newValue string, _ *schema
6568

6669
return false
6770
}
71+
72+
type GetResourcePrivateIPsOptions struct {
73+
ResourceType *ipam.ResourceType
74+
ResourceID *string
75+
ResourceName *string
76+
PrivateNetworkID *string
77+
}
78+
79+
// GetResourcePrivateIPs fetches the private IP addresses of a resource in a private network.
80+
func GetResourcePrivateIPs(ctx context.Context, m interface{}, region scw.Region, opts *GetResourcePrivateIPsOptions) ([]map[string]interface{}, error) {
81+
ipamAPI := ipam.NewAPI(meta.ExtractScwClient(m))
82+
83+
req := &ipam.ListIPsRequest{
84+
Region: region,
85+
}
86+
87+
if opts != nil {
88+
if opts.PrivateNetworkID != nil {
89+
req.PrivateNetworkID = opts.PrivateNetworkID
90+
}
91+
92+
if opts.ResourceID != nil {
93+
req.ResourceID = opts.ResourceID
94+
}
95+
96+
if opts.ResourceName != nil {
97+
req.ResourceName = opts.ResourceName
98+
}
99+
100+
if opts.ResourceType != nil {
101+
req.ResourceType = *opts.ResourceType
102+
}
103+
}
104+
105+
resp, err := ipamAPI.ListIPs(req, scw.WithContext(ctx))
106+
if err != nil {
107+
if httperrors.Is403(err) {
108+
return nil, err
109+
}
110+
111+
return nil, fmt.Errorf("error fetching IPs from IPAM: %w", err)
112+
}
113+
114+
if len(resp.IPs) == 0 {
115+
return nil, nil
116+
}
117+
118+
ipList := make([]map[string]interface{}, 0, len(resp.IPs))
119+
120+
for _, ip := range resp.IPs {
121+
ipNet := ip.Address
122+
if ipNet.IP == nil {
123+
continue
124+
}
125+
126+
ipMap := map[string]interface{}{
127+
"id": regional.NewIDString(region, ip.ID),
128+
"address": ipNet.IP.String(),
129+
}
130+
ipList = append(ipList, ipMap)
131+
}
132+
133+
return ipList, nil
134+
}

0 commit comments

Comments
 (0)