Skip to content

Commit 04ec2c0

Browse files
authored
feat(ipam): add ipam ip data source (#2095)
* feat(ipam): add ipam ip data source * remove tags attribute * update request arguments * add helpers and record tests * update address, tests * add doc * add type validation * add TODO
1 parent 4891e62 commit 04ec2c0

File tree

7 files changed

+5048
-0
lines changed

7 files changed

+5048
-0
lines changed

docs/data-sources/ipam_ip.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
---
2+
subcategory: "IPAM"
3+
page_title: "Scaleway: scaleway_ipam_ip"
4+
---
5+
6+
# scaleway_ipam_ip
7+
8+
Gets information about IP managed by IPAM service. IPAM service is used for dhcp bundled in VPCs' private networks.
9+
10+
## Examples
11+
12+
### Instance Private Network IP
13+
14+
```hcl
15+
# Get Instance IP in a private network
16+
resource "scaleway_instance_private_nic" "nic" {
17+
server_id = scaleway_instance_server.server.id
18+
private_network_id = scaleway_vpc_private_network.pn.id
19+
}
20+
21+
# Find server IPv4 using private-nic mac address
22+
data "scaleway_ipam_ip" "ip" {
23+
mac_address = scaleway_instance_private_nic.nic.mac_address
24+
type = "ipv4"
25+
}
26+
```
27+
28+
## Argument Reference
29+
30+
- `type` - (Required) The type of IP to search for (ipv4, ipv6).
31+
32+
- `private_network_id` - (Optional) The ID of the private network the IP belong to.
33+
34+
- `resource_id` - (Optional) The ID of the resource that the IP is bound to.
35+
36+
- `mac_address` - (Optional) The Mac Address linked to the IP.
37+
38+
- `region` - (Defaults to [provider](../index.md#zone) `region`) The [region](../guides/regions_and_zones.md#regions) in which the IP exists.
39+
40+
## Attributes Reference
41+
42+
In addition to all above arguments, the following attributes are exported:
43+
44+
- `id` - The ID of the IP in IPAM
45+
- `address` - The IP address

scaleway/data_source_ipam_ip.go

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
package scaleway
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/hashicorp/go-cty/cty"
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
10+
ipam "github.com/scaleway/scaleway-sdk-go/api/ipam/v1alpha1"
11+
"github.com/scaleway/scaleway-sdk-go/scw"
12+
)
13+
14+
func dataSourceScalewayIPAMIP() *schema.Resource {
15+
return &schema.Resource{
16+
ReadContext: dataSourceScalewayIPAMIPRead,
17+
Schema: map[string]*schema.Schema{
18+
// Input
19+
"private_network_id": {
20+
Type: schema.TypeString,
21+
Optional: true,
22+
},
23+
"resource_id": {
24+
Type: schema.TypeString,
25+
Optional: true,
26+
},
27+
"mac_address": {
28+
Type: schema.TypeString,
29+
Optional: true,
30+
},
31+
"type": {
32+
Type: schema.TypeString,
33+
Required: true,
34+
Description: "IP Type (ipv4, ipv6)",
35+
ValidateDiagFunc: func(i interface{}, path cty.Path) diag.Diagnostics {
36+
switch i.(string) {
37+
case "ipv4":
38+
return nil
39+
case "ipv6":
40+
return nil
41+
default:
42+
return diag.Diagnostics{{
43+
Severity: diag.Error,
44+
Summary: "Invalid IP Type",
45+
Detail: "Expected ipv4 or ipv6",
46+
AttributePath: cty.GetAttrPath("type"),
47+
}}
48+
}
49+
},
50+
},
51+
"region": regionSchema(),
52+
53+
// Computed
54+
"address": {
55+
Type: schema.TypeString,
56+
Computed: true,
57+
},
58+
},
59+
}
60+
}
61+
62+
func dataSourceScalewayIPAMIPRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
63+
api, region, err := ipamAPIWithRegion(d, meta)
64+
if err != nil {
65+
return diag.FromErr(err)
66+
}
67+
68+
req := &ipam.ListIPsRequest{ // TODO: add missing filters
69+
Region: region,
70+
OrganizationID: nil,
71+
PrivateNetworkID: expandStringPtr(d.Get("private_network_id")),
72+
SubnetID: nil,
73+
Attached: nil,
74+
ResourceID: expandStringPtr(d.Get("resource_id")),
75+
ResourceType: ipam.ResourceTypeUnknownType,
76+
MacAddress: expandStringPtr(d.Get("mac_address")),
77+
ResourceName: nil,
78+
ResourceIDs: nil,
79+
}
80+
81+
switch d.Get("type").(string) {
82+
case "ipv4":
83+
req.IsIPv6 = scw.BoolPtr(false)
84+
case "ipv6":
85+
req.IsIPv6 = scw.BoolPtr(true)
86+
default:
87+
return diag.Diagnostics{{
88+
Severity: diag.Error,
89+
Summary: "Invalid IP Type",
90+
Detail: "Expected ipv4 or ipv6",
91+
AttributePath: cty.GetAttrPath("type"),
92+
}}
93+
}
94+
95+
resp, err := api.ListIPs(req, scw.WithAllPages(), scw.WithContext(ctx))
96+
if err != nil {
97+
return diag.FromErr(err)
98+
}
99+
if len(resp.IPs) == 0 {
100+
return diag.FromErr(fmt.Errorf("no ip found with given filters"))
101+
}
102+
if len(resp.IPs) > 1 {
103+
return diag.FromErr(fmt.Errorf("more than one ip found with given filter"))
104+
}
105+
106+
ip := resp.IPs[0]
107+
108+
d.SetId(ip.ID)
109+
_ = d.Set("address", ip.Address.IP.String())
110+
111+
return nil
112+
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package scaleway
2+
3+
import (
4+
"testing"
5+
6+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
7+
)
8+
9+
func TestAccScalewayDataSourceIPAMIP_Instance(t *testing.T) {
10+
tt := NewTestTools(t)
11+
defer tt.Cleanup()
12+
resource.ParallelTest(t, resource.TestCase{
13+
PreCheck: func() { testAccPreCheck(t) },
14+
ProviderFactories: tt.ProviderFactories,
15+
CheckDestroy: testAccCheckScalewayInstanceServerDestroy(tt),
16+
Steps: []resource.TestStep{
17+
{
18+
Config: `
19+
resource "scaleway_vpc" "main" {
20+
name = "tf-tests-ipam-ip-datasource-instance"
21+
}
22+
23+
resource "scaleway_vpc_private_network" "main" {
24+
vpc_id = scaleway_vpc.main.id
25+
name = "tf-tests-ipam-ip-datasource-instance"
26+
}
27+
28+
resource "scaleway_instance_server" "main" {
29+
name = "tf-tests-ipam-ip-datasource-instance"
30+
image = "ubuntu_jammy"
31+
type = "PLAY2-MICRO"
32+
tags = [ "terraform-test", "data_scaleway_instance_servers", "basic" ]
33+
}
34+
35+
resource "scaleway_instance_private_nic" "main" {
36+
private_network_id = scaleway_vpc_private_network.main.id
37+
server_id = scaleway_instance_server.main.id
38+
}
39+
40+
data "scaleway_ipam_ip" "main" {
41+
mac_address = scaleway_instance_private_nic.main.mac_address
42+
type = "ipv4"
43+
}`,
44+
Check: resource.ComposeTestCheckFunc(
45+
resource.TestCheckResourceAttrSet("data.scaleway_ipam_ip.main", "address"),
46+
),
47+
},
48+
},
49+
})
50+
}
51+
52+
func TestAccScalewayDataSourceIPAMIP_InstanceLB(t *testing.T) {
53+
tt := NewTestTools(t)
54+
defer tt.Cleanup()
55+
resource.ParallelTest(t, resource.TestCase{
56+
PreCheck: func() { testAccPreCheck(t) },
57+
ProviderFactories: tt.ProviderFactories,
58+
CheckDestroy: testAccCheckScalewayInstanceServerDestroy(tt),
59+
Steps: []resource.TestStep{
60+
{
61+
Config: `
62+
resource "scaleway_vpc" "main" {
63+
name = "tf-tests-ipam-ip-datasource-instance"
64+
}
65+
66+
resource "scaleway_vpc_private_network" "main" {
67+
vpc_id = scaleway_vpc.main.id
68+
name = "tf-tests-ipam-ip-datasource-instance"
69+
}
70+
71+
resource "scaleway_instance_server" "main" {
72+
name = "tf-tests-ipam-ip-datasource-instance"
73+
image = "ubuntu_jammy"
74+
type = "PLAY2-MICRO"
75+
tags = [ "terraform-test", "data_scaleway_instance_servers", "basic" ]
76+
}
77+
78+
resource "scaleway_instance_private_nic" "main" {
79+
private_network_id = scaleway_vpc_private_network.main.id
80+
server_id = scaleway_instance_server.main.id
81+
}
82+
83+
data "scaleway_ipam_ip" "main" {
84+
mac_address = scaleway_instance_private_nic.main.mac_address
85+
type = "ipv4"
86+
}
87+
88+
resource "scaleway_lb_ip" "main" {}
89+
90+
resource "scaleway_lb" "main" {
91+
ip_id = scaleway_lb_ip.main.id
92+
type = "LB-S"
93+
}
94+
95+
resource "scaleway_lb_backend" "main" {
96+
lb_id = scaleway_lb.main.id
97+
forward_protocol = "http"
98+
forward_port = "80"
99+
server_ips = [data.scaleway_ipam_ip.main.address]
100+
}`,
101+
Check: resource.ComposeTestCheckFunc(
102+
resource.TestCheckResourceAttrSet("data.scaleway_ipam_ip.main", "address"),
103+
),
104+
},
105+
},
106+
})
107+
}

scaleway/helpers_ipam.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package scaleway
2+
3+
import (
4+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
5+
ipam "github.com/scaleway/scaleway-sdk-go/api/ipam/v1alpha1"
6+
"github.com/scaleway/scaleway-sdk-go/scw"
7+
)
8+
9+
// ipamAPIWithRegion returns a new ipam API and the region
10+
func ipamAPIWithRegion(d *schema.ResourceData, m interface{}) (*ipam.API, scw.Region, error) {
11+
meta := m.(*Meta)
12+
ipamAPI := ipam.NewAPI(meta.scwClient)
13+
14+
region, err := extractRegion(d, meta)
15+
if err != nil {
16+
return nil, "", err
17+
}
18+
19+
return ipamAPI, region, nil
20+
}

scaleway/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ func Provider(config *ProviderConfig) plugin.ProviderFunc {
201201
"scaleway_instance_snapshot": dataSourceScalewayInstanceSnapshot(),
202202
"scaleway_iot_hub": dataSourceScalewayIotHub(),
203203
"scaleway_iot_device": dataSourceScalewayIotDevice(),
204+
"scaleway_ipam_ip": dataSourceScalewayIPAMIP(),
204205
"scaleway_k8s_cluster": dataSourceScalewayK8SCluster(),
205206
"scaleway_k8s_pool": dataSourceScalewayK8SPool(),
206207
"scaleway_k8s_version": dataSourceScalewayK8SVersion(),

0 commit comments

Comments
 (0)