Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(vpc): migrate from zonal to regional #2045

Merged
merged 9 commits into from
Jul 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 4 additions & 27 deletions docs/resources/vpc_private_network.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,40 +38,21 @@ resource "scaleway_vpc_private_network" "pn_priv" {
}
```

-> **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`.

```hcl
resource "scaleway_vpc" "vpc01" {
name = "test-vpc"
tags = ["terraform", "vpc"]
}

resource "scaleway_vpc_private_network" "regional_pn" {
name = "my_regiona_pn"
tags = ["terraform", "pn", "regional"]
is_regional = true
vpc_id = scaleway_vpc.vpc01.id
}
```

## Arguments Reference

The following arguments are supported:

- `name` - (Optional) The name of the private network. If not provided it will be randomly generated.
- `tags` - (Optional) The tags associated with the private network.
- `zone` - (Defaults to [provider](../index.md#zone) `zone`) The [zone](../guides/regions_and_zones.md#zones) in which the private network should be created.
- `project_id` - (Defaults to [provider](../index.md#project_id) `project_id`) The ID of the project the private network is associated with.
- `ipv4_subnet` - (Optional) The IPv4 subnet to associate with the private network.
- `subnet` - (Optional) The subnet CIDR.
- `ipv6_subnets` - (Optional) The IPv6 subnets to associate with the private network.
- `subnet` - (Optional) The subnet CIDR.

-> **Note:** If using Regional Private Network:

- `region` - (Defaults to [provider](../index.md#region) `region`) The [region](../guides/regions_and_zones.md#regions) of the private network.
- `vpc_id` - (Optional) The VPC in which to create the private network.
- `is_regional` - (Optional) Defines whether the private network is Regional. By default, it will be Zonal.
- `is_regional` - (Deprecated) The private networks are necessarily regional now.
- `zone` - (Deprecated) please use `region` instead - (Defaults to [provider](../index.md#zone) `zone`) The [zone](../guides/regions_and_zones.md#zones) in which the private network should be created.

## Attributes Reference

Expand All @@ -95,17 +76,13 @@ In addition to all above arguments, the following attributes are exported:
- `subnet_mask` - The subnet mask expressed in dotted decimal notation, e.g., '255.255.255.0' for a /24 subnet
- `prefix_length` - The length of the network prefix, e.g., 24 for a 255.255.255.0 mask.

~> **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
~> **Important:** Private networks' IDs are [regional](../guides/regions_and_zones.md#resource-ids), which means they are of the form of `{region}/{id}`, e.g. `fr-par/11111111-1111-1111-1111-111111111111

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

## Import

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

```bash
$ terraform import scaleway_vpc_private_network.vpc_demo fr-par-1/11111111-1111-1111-1111-111111111111
```
Private networks can be imported using the `{region}/{id}`, e.g.

```bash
$ terraform import scaleway_vpc_private_network.vpc_demo fr-par/11111111-1111-1111-1111-111111111111
Expand Down
25 changes: 17 additions & 8 deletions scaleway/data_source_vpc_private_network.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/scaleway/scaleway-sdk-go/api/vpc/v1"
"github.com/scaleway/scaleway-sdk-go/api/vpc/v2"
"github.com/scaleway/scaleway-sdk-go/scw"
)

Expand All @@ -33,7 +33,7 @@ func dataSourceScalewayVPCPrivateNetwork() *schema.Resource {
}

func dataSourceScalewayVPCPrivateNetworkRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
vpcAPI, zone, err := vpcAPIWithZone(d, meta)
vpcAPI, region, err := vpcAPIWithRegion(d, meta)
if err != nil {
return diag.FromErr(err)
}
Expand All @@ -42,8 +42,8 @@ func dataSourceScalewayVPCPrivateNetworkRead(ctx context.Context, d *schema.Reso
if !ok {
res, err := vpcAPI.ListPrivateNetworks(
&vpc.ListPrivateNetworksRequest{
Name: expandStringPtr(d.Get("name").(string)),
Zone: zone,
Name: expandStringPtr(d.Get("name").(string)),
Region: region,
}, scw.WithContext(ctx))
if err != nil {
return diag.FromErr(err)
Expand All @@ -68,8 +68,17 @@ func dataSourceScalewayVPCPrivateNetworkRead(ctx context.Context, d *schema.Reso
privateNetworkID = res.PrivateNetworks[0].ID
}

zonedID := datasourceNewZonedID(privateNetworkID, zone)
d.SetId(zonedID)
_ = d.Set("private_network_id", zonedID)
return resourceScalewayVPCPrivateNetworkRead(ctx, d, meta)
regionalID := datasourceNewRegionalID(privateNetworkID, region)
d.SetId(regionalID)
_ = d.Set("private_network_id", regionalID)
diags := resourceScalewayVPCPrivateNetworkRead(ctx, d, meta)
if diags != nil {
return append(diags, diag.Errorf("failed to read private network state")...)
}

if d.Id() == "" {
return diag.Errorf("private network (%s) not found", regionalID)
}

return nil
}
4 changes: 2 additions & 2 deletions scaleway/helpers_baremetal.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,11 +212,11 @@ func flattenBaremetalOptions(zone scw.Zone, options []*baremetal.ServerOption) i
return flattenedOptions
}

func flattenBaremetalPrivateNetworks(privateNetworks []*baremetal.ServerPrivateNetwork) interface{} {
func flattenBaremetalPrivateNetworks(region scw.Region, privateNetworks []*baremetal.ServerPrivateNetwork) interface{} {
flattenedPrivateNetworks := []map[string]interface{}(nil)
for _, privateNetwork := range privateNetworks {
flattenedPrivateNetworks = append(flattenedPrivateNetworks, map[string]interface{}{
"id": privateNetwork.PrivateNetworkID,
"id": newRegionalIDString(region, privateNetwork.PrivateNetworkID),
"vlan": flattenUint32Ptr(privateNetwork.Vlan),
"status": privateNetwork.Status,
"created_at": flattenTime(privateNetwork.CreatedAt),
Expand Down
8 changes: 7 additions & 1 deletion scaleway/helpers_lb.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

"github.com/hashicorp/go-cty/cty"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
lbSDK "github.com/scaleway/scaleway-sdk-go/api/lb/v1"
"github.com/scaleway/scaleway-sdk-go/scw"
Expand Down Expand Up @@ -203,8 +204,13 @@ func flattenPrivateNetworkConfigs(privateNetworks []*lbSDK.PrivateNetwork) inter
if pn.DHCPConfig != nil {
dhcpConfigExist = true
}
pnRegion, err := pn.LB.Zone.Region()
if err != nil {
return diag.FromErr(err)
}
pnRegionalID := newRegionalIDString(pnRegion, pn.PrivateNetworkID)
pnI = append(pnI, map[string]interface{}{
"private_network_id": pn.PrivateNetworkID,
"private_network_id": pnRegionalID,
"dhcp_config": dhcpConfigExist,
"status": pn.Status.String(),
"zone": pn.LB.Zone.String(),
Expand Down
15 changes: 13 additions & 2 deletions scaleway/helpers_rdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"time"

"github.com/hashicorp/go-cty/cty"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/scaleway/scaleway-sdk-go/api/rdb/v1"
"github.com/scaleway/scaleway-sdk-go/scw"
Expand Down Expand Up @@ -211,6 +212,11 @@ func flattenPrivateNetwork(endpoints []*rdb.Endpoint) (interface{}, bool) {
for _, endpoint := range endpoints {
if endpoint.PrivateNetwork != nil {
pn := endpoint.PrivateNetwork
fetchRegion, err := pn.Zone.Region()
if err != nil {
return diag.FromErr(err), false
}
pnRegionalID := newRegionalIDString(fetchRegion, pn.PrivateNetworkID)
serviceIP, err := flattenIPNet(pn.ServiceIP)
if err != nil {
return pnI, false
Expand All @@ -221,7 +227,7 @@ func flattenPrivateNetwork(endpoints []*rdb.Endpoint) (interface{}, bool) {
"port": int(endpoint.Port),
"name": endpoint.Name,
"ip_net": serviceIP,
"pn_id": pn.PrivateNetworkID,
"pn_id": pnRegionalID,
"hostname": flattenStringPtr(endpoint.Hostname),
})
return pnI, true
Expand Down Expand Up @@ -316,7 +322,12 @@ func flattenReadReplicaEndpoints(endpoints []*rdb.Endpoint) (directAccess, priva
directAccess = rawEndpoint
}
if endpoint.PrivateNetwork != nil {
rawEndpoint["private_network_id"] = endpoint.PrivateNetwork.PrivateNetworkID
fetchRegion, err := endpoint.PrivateNetwork.Zone.Region()
if err != nil {
return diag.FromErr(err), false
}
pnRegionalID := newRegionalIDString(fetchRegion, endpoint.PrivateNetwork.PrivateNetworkID)
rawEndpoint["private_network_id"] = pnRegionalID
rawEndpoint["service_ip"] = endpoint.PrivateNetwork.ServiceIP.String()
rawEndpoint["zone"] = endpoint.PrivateNetwork.Zone
privateNetwork = rawEndpoint
Expand Down
8 changes: 7 additions & 1 deletion scaleway/helpers_redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"sort"
"time"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/scaleway/scaleway-sdk-go/api/redis/v1"
"github.com/scaleway/scaleway-sdk-go/scw"
Expand Down Expand Up @@ -148,14 +149,19 @@ func flattenRedisPrivateNetwork(endpoints []*redis.Endpoint) (interface{}, bool)
continue
}
pn := endpoint.PrivateNetwork
fetchRegion, err := pn.Zone.Region()
if err != nil {
return diag.FromErr(err), false
}
pnRegionalID := newRegionalIDString(fetchRegion, pn.ID)
serviceIps := []interface{}(nil)
for _, ip := range pn.ServiceIPs {
serviceIps = append(serviceIps, ip.String())
}
pnFlat = append(pnFlat, map[string]interface{}{
"endpoint_id": endpoint.ID,
"zone": pn.Zone,
"id": pn.ID,
"id": pnRegionalID,
"service_ips": serviceIps,
})
}
Expand Down
51 changes: 0 additions & 51 deletions scaleway/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,54 +302,3 @@ func TestStringHashcode_positiveIndex(t *testing.T) {
}
}
}

func testAccCheckRawIDsMatch(res1, attr1, res2, attr2 string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs1, ok1 := s.RootModule().Resources[res1]
if !ok1 {
return fmt.Errorf("not found: %s", res1)
}

rs2, ok2 := s.RootModule().Resources[res2]
if !ok2 {
return fmt.Errorf("not found: %s", res2)
}

// Check if attr1 uses the wildcard syntax
if strings.Contains(attr1, ".*.") {
parts := strings.SplitN(attr1, ".*.", 2)
prefix, suffix := parts[0], parts[1]

var id1s []string
for key, value := range rs1.Primary.Attributes {
if strings.HasPrefix(key, prefix+".") && strings.HasSuffix(key, "."+suffix) {
id1s = append(id1s, expandID(value))
}
}

id2 := expandID(rs2.Primary.Attributes[attr2])

matches := false
for _, id1 := range id1s {
if id1 == id2 {
matches = true
break
}
}

if !matches {
return fmt.Errorf("ID %s from resource %s does not match ID %s from resource %s", strings.Join(id1s, ", "), res1, id2, res2)
}
} else {
// attr1 doesn't use the wildcard syntax, so use it as is
id1 := expandID(rs1.Primary.Attributes[attr1])
id2 := expandID(rs2.Primary.Attributes[attr2])

if id1 != id2 {
return fmt.Errorf("ID %s from resource %s does not match ID %s from resource %s", id1, res1, id2, res2)
}
}

return nil
}
}
55 changes: 43 additions & 12 deletions scaleway/helpers_vpc.go
Original file line number Diff line number Diff line change
@@ -1,29 +1,20 @@
package scaleway

import (
"context"
"fmt"
"net"
"strconv"
"strings"

"github.com/hashicorp/go-cty/cty"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
v1 "github.com/scaleway/scaleway-sdk-go/api/vpc/v1"
v2 "github.com/scaleway/scaleway-sdk-go/api/vpc/v2"
"github.com/scaleway/scaleway-sdk-go/scw"
validator "github.com/scaleway/scaleway-sdk-go/validation"
)

// vpcAPIWithZone returns a new VPC API and the zone for a Create request
func vpcAPIWithZone(d *schema.ResourceData, m interface{}) (*v1.API, scw.Zone, error) {
meta := m.(*Meta)
vpcAPI := v1.NewAPI(meta.scwClient)

zone, err := extractZone(d, meta)
if err != nil {
return nil, "", err
}
return vpcAPI, zone, err
}

// vpcAPIWithZoneAndID
func vpcAPIWithZoneAndID(m interface{}, id string) (*v1.API, scw.Zone, string, error) {
meta := m.(*Meta)
Expand Down Expand Up @@ -203,3 +194,43 @@ func getPrefixLength(mask net.IPMask) int {
ones, _ := mask.Size()
return ones
}

func vpcPrivateNetworkUpgradeV1SchemaType() cty.Type {
return cty.Object(map[string]cty.Type{
"id": cty.String,
})
}

func vpcPrivateNetworkV1SUpgradeFunc(_ context.Context, rawState map[string]interface{}, _ interface{}) (map[string]interface{}, error) {
var err error

ID, exist := rawState["id"]
if !exist {
return nil, fmt.Errorf("upgrade: id not exist")
}
rawState["id"], err = vpcPrivateNetworkUpgradeV1ZonalToRegionalID(ID.(string))
if err != nil {
return nil, err
}

return rawState, nil
}

func vpcPrivateNetworkUpgradeV1ZonalToRegionalID(element string) (string, error) {
locality, id, err := parseLocalizedID(element)
// return error if can't parse
if err != nil {
return "", fmt.Errorf("upgrade: could not retrieve the locality from `%s`", element)
}
// if locality is already regional return
if validator.IsRegion(locality) {
return element, nil
}

fetchRegion, err := scw.Zone(locality).Region()
if err != nil {
return "", err
}

return fmt.Sprintf("%s/%s", fetchRegion.String(), id), nil
}
6 changes: 5 additions & 1 deletion scaleway/resource_baremetal_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,11 @@ func resourceScalewayBaremetalServerRead(ctx context.Context, d *schema.Resource
if err != nil {
return diag.FromErr(fmt.Errorf("failed to list server's private networks: %w", err))
}
_ = d.Set("private_network", flattenBaremetalPrivateNetworks(listPrivateNetworks.ServerPrivateNetworks))
pnRegion, err := server.Zone.Region()
if err != nil {
return diag.FromErr(err)
}
_ = d.Set("private_network", flattenBaremetalPrivateNetworks(pnRegion, listPrivateNetworks.ServerPrivateNetworks))

return nil
}
Expand Down
Loading