Skip to content

Commit 6fc289e

Browse files
Mia-Crossyfodil
andcommitted
feat(rdb): read instance's private IPs
Co-authored-by: Yacine FODIL <[email protected]>
1 parent 8801985 commit 6fc289e

File tree

9 files changed

+3448
-2209
lines changed

9 files changed

+3448
-2209
lines changed

docs/resources/rdb_instance.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,9 @@ are of the form `{region}/{id}`, e.g. `fr-par/11111111-1111-1111-1111-1111111111
238238
- `port` - Port in the Private Network.
239239
- `name` - Name of the endpoint.
240240
- `hostname` - Hostname of the endpoint.
241+
- `private_ip` - The list of private IPv4 addresses associated with the resource.
242+
- `id` - The ID of the IPv4 address resource.
243+
- `address` - The private IPv4 address.
241244
- `certificate` - Certificate of the Database Instance.
242245
- `organization_id` - The organization ID the Database Instance is associated with.
243246

internal/services/ipam/helpers.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package ipam
22

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

@@ -65,3 +67,63 @@ func diffSuppressFuncStandaloneIPandCIDR(_, oldValue, newValue string, _ *schema
6567

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

internal/services/ipam/ip_data_source_test.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,6 @@ func TestAccDataSourceIPAMIP_RDB(t *testing.T) {
151151
user_name = "my_initial_user"
152152
password = "thiZ_is_v&ry_s3cret"
153153
tags = [ "terraform-test", "scaleway_rdb_instance", "volume", "rdb_pn" ]
154-
volume_type = "bssd"
155-
volume_size_in_gb = 10
156154
private_network {
157155
pn_id = "${scaleway_vpc_private_network.main.id}"
158156
enable_ipam = true

internal/services/ipam/testdata/data-source-ipamiprdb.cassette.yaml

Lines changed: 344 additions & 246 deletions
Large diffs are not rendered by default.

internal/services/rdb/instance.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
1111
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
1212
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
13+
ipamAPI "github.com/scaleway/scaleway-sdk-go/api/ipam/v1"
1314
"github.com/scaleway/scaleway-sdk-go/api/rdb/v1"
1415
"github.com/scaleway/scaleway-sdk-go/scw"
1516
"github.com/scaleway/terraform-provider-scaleway/v2/internal/cdf"
@@ -18,6 +19,7 @@ import (
1819
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality/regional"
1920
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality/zonal"
2021
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/account"
22+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/ipam"
2123
"github.com/scaleway/terraform-provider-scaleway/v2/internal/types"
2224
"github.com/scaleway/terraform-provider-scaleway/v2/internal/verify"
2325
)
@@ -322,6 +324,25 @@ func ResourceInstance() *schema.Resource {
322324
Optional: true,
323325
Description: "Enable or disable encryption at rest for the database instance",
324326
},
327+
"private_ips": {
328+
Type: schema.TypeList,
329+
Computed: true,
330+
Description: "List of private IPv4 addresses associated with the resource",
331+
Elem: &schema.Resource{
332+
Schema: map[string]*schema.Schema{
333+
"id": {
334+
Type: schema.TypeString,
335+
Computed: true,
336+
Description: "The ID of the IPv4 address resource",
337+
},
338+
"address": {
339+
Type: schema.TypeString,
340+
Computed: true,
341+
Description: "The private IPv4 address",
342+
},
343+
},
344+
},
345+
},
325346
// Common
326347
"region": regional.Schema(),
327348
"organization_id": account.OrganizationIDSchema(),
@@ -640,10 +661,36 @@ func ResourceRdbInstanceRead(ctx context.Context, d *schema.ResourceData, m inte
640661
_ = d.Set("logs_policy", flattenInstanceLogsPolicy(res.LogsPolicy))
641662

642663
// set endpoints
664+
var privateIPs []map[string]interface{}
665+
643666
if pnI, pnExist := flattenPrivateNetwork(res.Endpoints); pnExist {
644667
_ = d.Set("private_network", pnI)
668+
669+
for _, endpoint := range res.Endpoints {
670+
if endpoint.PrivateNetwork == nil {
671+
continue
672+
}
673+
674+
if endpoint.PrivateNetwork.ProvisioningMode == rdb.EndpointPrivateNetworkDetailsProvisioningModeIpam {
675+
resourceType := ipamAPI.ResourceTypeRdbInstance
676+
opts := &ipam.GetResourcePrivateIPsOptions{
677+
ResourceID: &res.ID,
678+
ResourceType: &resourceType,
679+
PrivateNetworkID: &res.Endpoints[0].PrivateNetwork.PrivateNetworkID,
680+
}
681+
682+
endpointPrivateIPs, err := ipam.GetResourcePrivateIPs(ctx, m, region, opts)
683+
if err != nil {
684+
return diag.FromErr(err)
685+
}
686+
687+
privateIPs = append(privateIPs, endpointPrivateIPs...)
688+
}
689+
}
645690
}
646691

692+
_ = d.Set("private_ips", privateIPs)
693+
647694
if lbI, lbExists := flattenLoadBalancer(res.Endpoints); lbExists {
648695
_ = d.Set("load_balancer", lbI)
649696
}

internal/services/rdb/instance_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -990,6 +990,8 @@ func TestAccInstance_Endpoints(t *testing.T) {
990990
resource.TestCheckResourceAttr("scaleway_rdb_instance.test_endpoints", "load_balancer.#", "0"),
991991
resource.TestCheckResourceAttr("scaleway_rdb_instance.test_endpoints", "endpoint_ip", ""), // Deprecated attribute, might be deleted later
992992
resource.TestCheckResourceAttr("scaleway_rdb_instance.test_endpoints", "endpoint_port", "0"), // Deprecated attribute, might be deleted later
993+
resource.TestCheckResourceAttrSet("scaleway_rdb_instance.test_endpoints", "private_ips.0.id"),
994+
resource.TestCheckResourceAttrSet("scaleway_rdb_instance.test_endpoints", "private_ips.0.address"),
993995
),
994996
},
995997
{

internal/services/rdb/testdata/instance-endpoints.cassette.yaml

Lines changed: 805 additions & 511 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)