Skip to content

Commit 6474acc

Browse files
yfodilremyleonequantumsheep
authored
feat(vpc): add support for regional private networks (#1975)
* feat(vpc): add support for regional private networks * fix * add doc * Apply suggestions from code review Co-authored-by: Nathanael Demacon <[email protected]> * lint * renaming * fix --------- Co-authored-by: Rémy Léone <[email protected]> Co-authored-by: Nathanael Demacon <[email protected]> Co-authored-by: Rémy Léone <[email protected]>
1 parent 4ac9d10 commit 6474acc

14 files changed

+1898
-341
lines changed

docs/data-sources/vpc_private_network.md

+14-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,17 @@ Gets information about a private network.
99

1010
## Example Usage
1111

12-
N/A, the usage will be meaningful in the next releases of VPC.
12+
```hcl
13+
# Get info by name
14+
data "scaleway_vpc_private_network" "my_name" {
15+
name = "foobar"
16+
}
17+
18+
# Get info by IP ID
19+
data "scaleway_vpc_private_network" "my_id" {
20+
private_network_id_id = "11111111-1111-1111-1111-111111111111"
21+
}
22+
```
1323

1424
## Argument Reference
1525

@@ -21,6 +31,7 @@ N/A, the usage will be meaningful in the next releases of VPC.
2131
In addition to all above arguments, the following attributes are exported:
2232

2333
- `id` - The ID of the private network.
24-
- `subnets` - The subnets CIDR associated with private network.
34+
- `ipv4_subnet` - (Optional) The IPv4 subnet associated with the private network.
35+
- `ipv6_subnets` - (Optional) The IPv6 subnets associated with the private network.
2536

26-
~> **Important:** Private networks' IDs are [zoned](../guides/regions_and_zones.md#resource-ids), which means they are of the form `{zone}/{id}`, e.g. `fr-par-1/11111111-1111-1111-1111-111111111111`
37+
~> **Important:** Private networks' IDs are [zoned](../guides/regions_and_zones.md#resource-ids) or [regional](../guides/regions_and_zones.md#resource-ids) if using beta, which means they are of the form `{zone}/{id}`, e.g. `fr-par-1/11111111-1111-1111-1111-111111111111` or `{region}/{id}`, e.g. `fr-par/11111111-1111-1111-1111-111111111111

docs/resources/vpc_private_network.md

+30-3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,22 @@ resource "scaleway_vpc_private_network" "pn_priv" {
1717
}
1818
```
1919

20+
-> **Note:** Regional Private Network is now in Public Beta. You can create a regional private network directly using this resource by setting `is_regional` to `true`.
21+
22+
```hcl
23+
resource "scaleway_vpc" "vpc01" {
24+
name = "test-vpc"
25+
tags = ["terraform", "vpc"]
26+
}
27+
28+
resource "scaleway_vpc_private_network" "regional_pn" {
29+
name = "my_regiona_pn"
30+
tags = ["terraform", "pn", "regional"]
31+
is_regional = true
32+
vpc_id = scaleway_vpc.vpc01.id
33+
}
34+
```
35+
2036
## Arguments Reference
2137

2238
The following arguments are supported:
@@ -25,22 +41,33 @@ The following arguments are supported:
2541
- `tags` - (Optional) The tags associated with the private network.
2642
- `zone` - (Defaults to [provider](../index.md#zone) `zone`) The [zone](../guides/regions_and_zones.md#zones) in which the private network should be created.
2743
- `project_id` - (Defaults to [provider](../index.md#project_id) `project_id`) The ID of the project the private network is associated with.
28-
- `subnets` - (Optional) The subnets CIDR associated with private network.
44+
- `ipv4_subnet` - (Optional) The IPv4 subnet associated with the private network.
45+
- `ipv6_subnets` - (Optional) The IPv6 subnets associated with the private network.
46+
47+
-> **Note:** If using Regional Private Network:
48+
49+
- `region` - (Defaults to [provider](../index.md#region) `region`) The [region](../guides/regions_and_zones.md#regions) of the private network.
50+
- `vpc_id` - (Optional) The VPC in which to create the private network.
51+
- `is_regional` - (Optional) Defines whether the private network is Regional. By default, it will be Zonal.
2952

3053
## Attributes Reference
3154

3255
In addition to all above arguments, the following attributes are exported:
3356

3457
- `id` - The ID of the private network.
3558

36-
~> **Important:** Private networks' IDs are [zoned](../guides/regions_and_zones.md#resource-ids), which means they are of the form `{zone}/{id}`, e.g. `fr-par-1/11111111-1111-1111-1111-111111111111`
59+
~> **Important:** Private networks' IDs are [zoned](../guides/regions_and_zones.md#resource-ids) or [regional](../guides/regions_and_zones.md#resource-ids) if using beta, which means they are of the form `{zone}/{id}`, e.g. `fr-par-1/11111111-1111-1111-1111-111111111111` or `{region}/{id}`, e.g. `fr-par/11111111-1111-1111-1111-111111111111
3760

3861
- `organization_id` - The organization ID the private network is associated with.
3962

4063
## Import
4164

42-
Private networks can be imported using the `{zone}/{id}`, e.g.
65+
Private networks can be imported using the `{zone}/{id}` or `{region}/{id}` using beta, e.g.
4366

4467
```bash
4568
$ terraform import scaleway_vpc_private_network.vpc_demo fr-par-1/11111111-1111-1111-1111-111111111111
4669
```
70+
71+
```bash
72+
$ terraform import scaleway_vpc_private_network.vpc_demo fr-par/11111111-1111-1111-1111-111111111111
73+
```

scaleway/data_source_vpc_private_network_test.go

+16-10
Original file line numberDiff line numberDiff line change
@@ -43,25 +43,31 @@ func TestAccScalewayDataSourceVPCPrivateNetwork_Basic(t *testing.T) {
4343
"scaleway_vpc_private_network.pn_test", "name"),
4444
resource.TestCheckResourceAttr(
4545
"data.scaleway_vpc_private_network.pn_test_by_name",
46-
"subnets.#", "2"),
46+
"ipv4_subnet.#", "1"),
47+
resource.TestCheckResourceAttr(
48+
"data.scaleway_vpc_private_network.pn_test_by_name",
49+
"ipv6_subnets.#", "1"),
4750
resource.TestCheckTypeSetElemAttrPair(
48-
"data.scaleway_vpc_private_network.pn_test_by_name", "subnets.*",
49-
"scaleway_vpc_private_network.pn_test", "subnets.0"),
51+
"data.scaleway_vpc_private_network.pn_test_by_name", "ipv4_subnet.0.subnet",
52+
"scaleway_vpc_private_network.pn_test", "ipv4_subnet.0.subnet"),
5053
resource.TestCheckTypeSetElemAttrPair(
51-
"data.scaleway_vpc_private_network.pn_test_by_name", "subnets.*",
52-
"scaleway_vpc_private_network.pn_test", "subnets.1"),
54+
"data.scaleway_vpc_private_network.pn_test_by_name", "ipv6_subnets.0.subnet",
55+
"scaleway_vpc_private_network.pn_test", "ipv6_subnets.0.subnet"),
5356
resource.TestCheckResourceAttrPair(
5457
"data.scaleway_vpc_private_network.pn_test_by_id", "private_network_id",
5558
"scaleway_vpc_private_network.pn_test", "id"),
5659
resource.TestCheckResourceAttr(
5760
"data.scaleway_vpc_private_network.pn_test_by_id",
58-
"subnets.#", "2"),
61+
"ipv4_subnet.#", "1"),
62+
resource.TestCheckResourceAttr(
63+
"data.scaleway_vpc_private_network.pn_test_by_id",
64+
"ipv6_subnets.#", "1"),
5965
resource.TestCheckTypeSetElemAttrPair(
60-
"data.scaleway_vpc_private_network.pn_test_by_id", "subnets.*",
61-
"scaleway_vpc_private_network.pn_test", "subnets.0"),
66+
"data.scaleway_vpc_private_network.pn_test_by_id", "ipv4_subnet.0.subnet",
67+
"scaleway_vpc_private_network.pn_test", "ipv4_subnet.0.subnet"),
6268
resource.TestCheckTypeSetElemAttrPair(
63-
"data.scaleway_vpc_private_network.pn_test_by_id", "subnets.*",
64-
"scaleway_vpc_private_network.pn_test", "subnets.1"),
69+
"data.scaleway_vpc_private_network.pn_test_by_id", "ipv6_subnets.0.subnet",
70+
"scaleway_vpc_private_network.pn_test", "ipv6_subnets.0.subnet"),
6571
),
6672
},
6773
},

scaleway/helpers_vpc.go

+96-16
Original file line numberDiff line numberDiff line change
@@ -66,28 +66,108 @@ func vpcAPI(m interface{}) (*v1.API, error) {
6666
return v1.NewAPI(meta.scwClient), nil
6767
}
6868

69-
func expandSubnets(data interface{}) ([]scw.IPNet, error) {
70-
var ipNets []scw.IPNet
71-
for _, s := range data.([]interface{}) {
72-
if s == nil {
73-
s = ""
69+
func expandSubnets(d *schema.ResourceData) (ipv4Subnets []scw.IPNet, ipv6Subnets []scw.IPNet, err error) {
70+
if v, ok := d.GetOk("ipv4_subnet"); ok {
71+
for _, s := range v.([]interface{}) {
72+
rawSubnet := s.(map[string]interface{})
73+
ipNet, err := expandIPNet(rawSubnet["subnet"].(string))
74+
if err != nil {
75+
return nil, nil, err
76+
}
77+
ipv4Subnets = append(ipv4Subnets, ipNet)
7478
}
75-
ipNet, err := expandIPNet(s.(string))
76-
if err != nil {
77-
return nil, err
79+
}
80+
81+
if v, ok := d.GetOk("ipv6_subnets"); ok {
82+
for _, s := range v.(*schema.Set).List() {
83+
rawSubnet := s.(map[string]interface{})
84+
ipNet, err := expandIPNet(rawSubnet["subnet"].(string))
85+
if err != nil {
86+
return nil, nil, err
87+
}
88+
ipv6Subnets = append(ipv6Subnets, ipNet)
89+
}
90+
}
91+
return
92+
}
93+
94+
func flattenAndSortSubnets(sub interface{}) (interface{}, interface{}) {
95+
switch subnets := sub.(type) {
96+
case []scw.IPNet:
97+
return flattenAndSortIPNetSubnets(subnets)
98+
case []*v2.Subnet:
99+
return flattenAndSortSubnetV2s(subnets)
100+
default:
101+
return "", nil
102+
}
103+
}
104+
105+
func flattenAndSortIPNetSubnets(subnets []scw.IPNet) (interface{}, interface{}) {
106+
if subnets == nil {
107+
return "", nil
108+
}
109+
110+
flattenedipv4Subnets := []map[string]interface{}(nil)
111+
flattenedipv6Subnets := []map[string]interface{}(nil)
112+
113+
for _, s := range subnets {
114+
// If it's an IPv4 subnet
115+
if s.IP.To4() != nil {
116+
sub, err := flattenIPNet(s)
117+
if err != nil {
118+
return "", nil
119+
}
120+
flattenedipv4Subnets = append(flattenedipv4Subnets, map[string]interface{}{
121+
"subnet": sub,
122+
})
123+
} else {
124+
sub, err := flattenIPNet(s)
125+
if err != nil {
126+
return "", nil
127+
}
128+
flattenedipv6Subnets = append(flattenedipv6Subnets, map[string]interface{}{
129+
"subnet": sub,
130+
})
78131
}
79-
ipNets = append(ipNets, ipNet)
80132
}
81133

82-
return ipNets, nil
134+
return flattenedipv4Subnets, flattenedipv6Subnets
83135
}
84136

85-
func flattenSubnets(subnets []scw.IPNet) *schema.Set {
86-
var rawSubnets []interface{}
137+
func flattenAndSortSubnetV2s(subnets []*v2.Subnet) (interface{}, interface{}) {
138+
if subnets == nil {
139+
return "", nil
140+
}
141+
142+
flattenedipv4Subnets := []map[string]interface{}(nil)
143+
flattenedipv6Subnets := []map[string]interface{}(nil)
144+
87145
for _, s := range subnets {
88-
rawSubnets = append(rawSubnets, s.String())
146+
// If it's an IPv4 subnet
147+
if s.Subnet.IP.To4() != nil {
148+
sub, err := flattenIPNet(s.Subnet)
149+
if err != nil {
150+
return "", nil
151+
}
152+
flattenedipv4Subnets = append(flattenedipv4Subnets, map[string]interface{}{
153+
"id": s.ID,
154+
"created_at": flattenTime(s.CreatedAt),
155+
"updated_at": flattenTime(s.UpdatedAt),
156+
"subnet": sub,
157+
})
158+
} else {
159+
sub, err := flattenIPNet(s.Subnet)
160+
if err != nil {
161+
return "", nil
162+
}
163+
flattenedipv6Subnets = append(flattenedipv6Subnets, map[string]interface{}{
164+
"id": s.ID,
165+
"created_at": flattenTime(s.CreatedAt),
166+
"updated_at": flattenTime(s.UpdatedAt),
167+
"subnet": sub,
168+
})
169+
}
89170
}
90-
return schema.NewSet(func(i interface{}) int {
91-
return StringHashcode(i.(string))
92-
}, rawSubnets)
171+
172+
return flattenedipv4Subnets, flattenedipv6Subnets
93173
}

0 commit comments

Comments
 (0)