Skip to content

Commit 48ed559

Browse files
committed
feat(instance): support private ips on servers datasource
1 parent 1cd8d76 commit 48ed559

File tree

4 files changed

+8688
-0
lines changed

4 files changed

+8688
-0
lines changed

docs/data-sources/instance_servers.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ In addition to all above arguments, the following attributes are exported:
4646
- `tags` - The tags associated with the server.
4747
- `public_ip` - The public IP address of the server.
4848
- `private_ip` - The Scaleway internal IP address of the server.
49+
- `private_ips` - The list of private IPv4 and IPv6 addresses associated with the server.
50+
- `id` - The ID of the IP address resource.
51+
- `address` - The private IP address.
4952
- `public_ips` - The list of public IPs of the server
5053
- `id` - The ID of the IP
5154
- `address` - The address of the IP

internal/services/instance/servers_data_source.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,16 @@ import (
55
"fmt"
66
"strconv"
77

8+
"github.com/hashicorp/go-cty/cty"
89
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
910
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
1011
"github.com/scaleway/scaleway-sdk-go/api/instance/v1"
12+
ipamAPI "github.com/scaleway/scaleway-sdk-go/api/ipam/v1"
1113
"github.com/scaleway/scaleway-sdk-go/scw"
14+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/httperrors"
1215
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality/zonal"
1316
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/account"
17+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/ipam"
1418
"github.com/scaleway/terraform-provider-scaleway/v2/internal/types"
1519
)
1620

@@ -65,6 +69,26 @@ func DataSourceServers() *schema.Resource {
6569
Computed: true,
6670
Type: schema.TypeString,
6771
},
72+
"private_ips": {
73+
Type: schema.TypeList,
74+
Computed: true,
75+
Optional: true,
76+
Description: "List of private IPv4 and IPv6 addresses associated with the resource",
77+
Elem: &schema.Resource{
78+
Schema: map[string]*schema.Schema{
79+
"id": {
80+
Type: schema.TypeString,
81+
Computed: true,
82+
Description: "The ID of the IPv4/v6 address resource",
83+
},
84+
"address": {
85+
Type: schema.TypeString,
86+
Computed: true,
87+
Description: "The private IPv4/v6 address",
88+
},
89+
},
90+
},
91+
},
6892
"state": {
6993
Computed: true,
7094
Type: schema.TypeString,
@@ -227,6 +251,62 @@ func DataSourceInstanceServersRead(ctx context.Context, d *schema.ResourceData,
227251
rawServer["ipv6_prefix_length"] = prefixLength
228252
}
229253

254+
ph, err := newPrivateNICHandler(instanceAPI, server.ID, zone)
255+
if err != nil {
256+
return diag.FromErr(err)
257+
}
258+
259+
privateNICIDs := []string(nil)
260+
for _, nic := range ph.privateNICsMap {
261+
privateNICIDs = append(privateNICIDs, nic.ID)
262+
}
263+
264+
// Read server's private IPs if possible
265+
allPrivateIPs := []map[string]any(nil)
266+
resourceType := ipamAPI.ResourceTypeInstancePrivateNic
267+
268+
region, err := zone.Region()
269+
if err != nil {
270+
return append(diags, diag.Diagnostic{
271+
Severity: diag.Warning,
272+
Summary: "Unable to get server's private IPs",
273+
Detail: err.Error(),
274+
})
275+
}
276+
277+
for _, nicID := range privateNICIDs {
278+
opts := &ipam.GetResourcePrivateIPsOptions{
279+
ResourceType: &resourceType,
280+
ResourceID: &nicID,
281+
ProjectID: &server.Project,
282+
}
283+
284+
privateIPs, err := ipam.GetResourcePrivateIPs(ctx, m, region, opts)
285+
286+
switch {
287+
case err == nil:
288+
allPrivateIPs = append(allPrivateIPs, privateIPs...)
289+
case httperrors.Is403(err):
290+
return append(diags, diag.Diagnostic{
291+
Severity: diag.Warning,
292+
Summary: "Unauthorized to read server's private IPs, please check your IAM permissions",
293+
Detail: err.Error(),
294+
AttributePath: cty.GetAttrPath("private_ips"),
295+
})
296+
default:
297+
diags = append(diags, diag.Diagnostic{
298+
Severity: diag.Warning,
299+
Summary: fmt.Sprintf("Unable to get private IPs for server %s (pnic_id: %s)", server.ID, nicID),
300+
Detail: err.Error(),
301+
AttributePath: cty.GetAttrPath("private_ips"),
302+
})
303+
}
304+
305+
if len(allPrivateIPs) > 0 {
306+
rawServer["private_ips"] = allPrivateIPs
307+
}
308+
}
309+
230310
servers = append(servers, rawServer)
231311
}
232312

internal/services/instance/servers_data_source_test.go

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,120 @@ func TestAccDataSourceServers_Basic(t *testing.T) {
8888
},
8989
})
9090
}
91+
92+
func TestAccDataSourceServers_PrivateIPs(t *testing.T) {
93+
tt := acctest.NewTestTools(t)
94+
defer tt.Cleanup()
95+
resource.ParallelTest(t, resource.TestCase{
96+
PreCheck: func() { acctest.PreCheck(t) },
97+
ProviderFactories: tt.ProviderFactories,
98+
CheckDestroy: instancechecks.IsServerDestroyed(tt),
99+
Steps: []resource.TestStep{
100+
{
101+
Config: `
102+
resource "scaleway_vpc_private_network" "pn01" {
103+
name = "private_network_instance_servers"
104+
}
105+
106+
resource "scaleway_instance_server" "server1" {
107+
name = "tf-server-datasource-private-ips-0"
108+
image = "ubuntu_focal"
109+
type = "DEV1-S"
110+
state = "stopped"
111+
tags = [ "terraform-test", "data_scaleway_instance_servers", "basic" ]
112+
113+
private_network {
114+
pn_id = scaleway_vpc_private_network.pn01.id
115+
}
116+
}`,
117+
},
118+
{
119+
Config: `
120+
resource "scaleway_vpc_private_network" "pn01" {
121+
name = "private_network_instance_servers"
122+
}
123+
124+
resource "scaleway_instance_server" "server1" {
125+
name = "tf-server-datasource-private-ips-0"
126+
image = "ubuntu_focal"
127+
type = "DEV1-S"
128+
state = "stopped"
129+
tags = [ "terraform-test", "data_scaleway_instance_servers", "basic" ]
130+
131+
private_network {
132+
pn_id = scaleway_vpc_private_network.pn01.id
133+
}
134+
}
135+
136+
resource "scaleway_instance_server" "server2" {
137+
name = "tf-server-datasource-private-ips-1"
138+
image = "ubuntu_focal"
139+
type = "DEV1-S"
140+
state = "stopped"
141+
tags = [ "terraform-test", "data_scaleway_instance_servers", "basic" ]
142+
143+
private_network {
144+
pn_id = scaleway_vpc_private_network.pn01.id
145+
}
146+
}`,
147+
},
148+
{
149+
Config: `
150+
resource "scaleway_vpc_private_network" "pn01" {
151+
name = "private_network_instance_servers"
152+
}
153+
154+
resource "scaleway_instance_server" "server1" {
155+
name = "tf-server-datasource-private-ips-0"
156+
image = "ubuntu_focal"
157+
type = "DEV1-S"
158+
state = "stopped"
159+
tags = [ "terraform-test", "data_scaleway_instance_servers", "basic" ]
160+
161+
private_network {
162+
pn_id = scaleway_vpc_private_network.pn01.id
163+
}
164+
}
165+
166+
resource "scaleway_instance_server" "server2" {
167+
name = "tf-server-datasource-private-ips-1"
168+
image = "ubuntu_focal"
169+
type = "DEV1-S"
170+
state = "stopped"
171+
tags = [ "terraform-test", "data_scaleway_instance_servers", "basic" ]
172+
173+
private_network {
174+
pn_id = scaleway_vpc_private_network.pn01.id
175+
}
176+
}
177+
178+
data "scaleway_instance_servers" "servers_by_name" {
179+
name = "tf-server-datasource-private-ips"
180+
}
181+
182+
data "scaleway_instance_servers" "servers_by_tag" {
183+
tags = ["data_scaleway_instance_servers", "terraform-test"]
184+
}
185+
186+
data "scaleway_instance_servers" "servers_by_name_other_zone" {
187+
name = "tf-server-datasource-private-ips"
188+
zone = "fr-par-2"
189+
}
190+
`,
191+
Check: resource.ComposeTestCheckFunc(
192+
resource.TestCheckResourceAttrSet("data.scaleway_instance_servers.servers_by_tag", "servers.0.private_ips.0.id"),
193+
resource.TestCheckResourceAttrSet("data.scaleway_instance_servers.servers_by_tag", "servers.0.private_ips.1.id"),
194+
resource.TestCheckResourceAttrSet("data.scaleway_instance_servers.servers_by_tag", "servers.1.private_ips.0.id"),
195+
resource.TestCheckResourceAttrSet("data.scaleway_instance_servers.servers_by_tag", "servers.1.private_ips.1.id"),
196+
197+
resource.TestCheckResourceAttrSet("data.scaleway_instance_servers.servers_by_name", "servers.0.private_ips.0.id"),
198+
resource.TestCheckResourceAttrSet("data.scaleway_instance_servers.servers_by_name", "servers.0.private_ips.1.id"),
199+
resource.TestCheckResourceAttrSet("data.scaleway_instance_servers.servers_by_name", "servers.1.private_ips.0.id"),
200+
resource.TestCheckResourceAttrSet("data.scaleway_instance_servers.servers_by_name", "servers.1.private_ips.1.id"),
201+
202+
resource.TestCheckNoResourceAttr("data.scaleway_instance_servers.servers_by_name_other_zone", "servers.0.id"),
203+
),
204+
},
205+
},
206+
})
207+
}

internal/services/instance/testdata/data-source-servers-private-ips.cassette.yaml

Lines changed: 8488 additions & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)