Skip to content

feat(vpc): add support for private network, private nic #649

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

Merged
merged 17 commits into from
Nov 17, 2020
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
22 changes: 22 additions & 0 deletions docs/data-sources/vpc_private_network.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
page_title: "Scaleway: scaleway_vpc_private_network"
description: |-
Get information about Scaleway VPC Private Networks.
---

# scaleway_vpc_private_network

Gets information about a private network.

## Example Usage

N/A, the usage will be meaningful in the next releases of VPC.

## Argument Reference

* `name` - (Required) Exact name of the private network.

## Attributes Reference

`id` is set to the ID of the found private network. Addition attributes are
exported.
40 changes: 40 additions & 0 deletions docs/resources/instance_private_nic.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
page_title: "Scaleway: scaleway_instance_private_nic"
description: |-
Manages Scaleway Compute Instance Private NICs.
---

# scaleway_instance_private_nic

Creates and manages Scaleway Instance Private NICs. For more information, see
[the documentation](https://developers.scaleway.com/en/products/instance/api/#private-nics-a42eea).

## Example

```hcl
resource "scaleway_instance_private_nic" "pnic01" {
server_id = "fr-par-1/11111111-1111-1111-1111-111111111111"
private_network_id = "fr-par-1/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
}
```

## Arguments Reference

The following arguments are required:

- `server_id` - (Required) The ID of the server associated with.
- `private_network_id` - (Required) The ID of the private network attached to.

## Attributes Reference

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

- `id` - The ID of the private NIC.

## Import

Private NICs can be imported using the `{zone}/{server_id}/{private_nic_id}`, e.g.

```bash
$ terraform import scaleway_instance_volume.server_volume fr-par-1/11111111-1111-1111-1111-111111111111/22222222-2222-2222-2222-222222222222
```
43 changes: 43 additions & 0 deletions docs/resources/vpc_private_network.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
page_title: "Scaleway: scaleway_vpc_private_network"
description: |-
Manages Scaleway VPC Private Networks.
---

# scaleway_vpc_private_network

Creates and manages Scaleway VPC Private Networks. For more information, see
[the documentation](https://developers.scaleway.com/en/products/vpc/api/#private-networks-ac2df4).

## Example

```hcl
resource "scaleway_vpc_private_network" "pn_priv" {
name = "subnet_demo"
tags = ["demo", "tarraform"]
}
```

## 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.

## Attributes Reference

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

- `id` - The ID of the private network.
- `organization_id` - (Defaults to [provider](../index.md#organization_id) `organization_id`) The ID of the organization the private network is associated with.

## Import

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

```bash
$ terraform import scaleway_vpc_private_network.vpc_demo fr-par-1/11111111-1111-1111-1111-111111111111
```
76 changes: 76 additions & 0 deletions scaleway/data_source_vpc_private_network.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package scaleway

import (
"context"
"fmt"

"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/scw"
)

func dataSourceScalewayVPCPrivateNetwork() *schema.Resource {
// Generate datasource schema from resource
dsSchema := datasourceSchemaFromResourceSchema(resourceScalewayVPCPrivateNetwork().Schema)

// Set 'Optional' schema elements
addOptionalFieldsToSchema(dsSchema, "name")

dsSchema["name"].ConflictsWith = []string{"private_network_id"}
dsSchema["private_network_id"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
Description: "The ID of the private network",
ValidateFunc: validationUUIDorUUIDWithLocality(),
ConflictsWith: []string{"name"},
}

return &schema.Resource{
Schema: dsSchema,
ReadContext: dataSourceScalewayVPCPrivateNetworkRead,
}
}

func dataSourceScalewayVPCPrivateNetworkRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
meta := m.(*Meta)
vpcAPI, zone, err := vpcAPIWithZone(d, meta)
if err != nil {
return diag.FromErr(err)
}

privateNetworkID, ok := d.GetOk("private_network_id")
if !ok {
res, err := vpcAPI.ListPrivateNetworks(
&vpc.ListPrivateNetworksRequest{
Name: expandStringPtr(d.Get("name").(string)),
Zone: zone,
}, scw.WithContext(ctx))
if err != nil {
return diag.FromErr(err)
}
if res.TotalCount == 0 {
return diag.FromErr(
fmt.Errorf(
"no private network found with the name %s",
d.Get("name"),
),
)
}
if res.TotalCount > 1 {
return diag.FromErr(
fmt.Errorf(
"%d private networks found with the name %s",
res.TotalCount,
d.Get("name"),
),
)
}
privateNetworkID = res.PrivateNetworks[0].ID
}

zonedID := datasourceNewZonedID(privateNetworkID, zone)
d.SetId(zonedID)
_ = d.Set("private_network_id", zonedID)
return resourceScalewayVPCPrivateNetworkRead(ctx, d, m)
}
51 changes: 51 additions & 0 deletions scaleway/data_source_vpc_private_network_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package scaleway

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

func TestAccScalewayDataSourceVPCPrivateNetwork_Basic(t *testing.T) {
tt := NewTestTools(t)
defer tt.Cleanup()
pnName := "TestAccScalewayDataSourceVPCPrivateNetwork_Basic"
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProviderFactories: tt.ProviderFactories,
CheckDestroy: testAccCheckScalewayVPCPrivateNetworkDestroy(tt),
Steps: []resource.TestStep{
{
Config: fmt.Sprintf(`
resource "scaleway_vpc_private_network" "pn_test" {
name = "%s"
}`, pnName),
},
{
Config: fmt.Sprintf(`
resource "scaleway_vpc_private_network" "pn_test" {
name = "%s"
}

data "scaleway_vpc_private_network" "pn_test_by_name" {
name = "${scaleway_vpc_private_network.pn_test.name}"
}

data "scaleway_vpc_private_network" "pn_test_by_id" {
private_network_id = "${scaleway_vpc_private_network.pn_test.id}"
}
`, pnName),
Check: resource.ComposeTestCheckFunc(
testAccCheckScalewayVPCPrivateNetworkExists(tt, "scaleway_vpc_private_network.pn_test"),
resource.TestCheckResourceAttrPair(
"data.scaleway_vpc_private_network.pn_test_by_name", "name",
"scaleway_vpc_private_network.pn_test", "name"),
resource.TestCheckResourceAttrPair(
"data.scaleway_vpc_private_network.pn_test_by_id", "private_network_id",
"scaleway_vpc_private_network.pn_test", "id"),
),
},
},
})
}
25 changes: 25 additions & 0 deletions scaleway/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,15 @@ func parseLocalizedID(localizedID string) (locality string, ID string, err error
return tab[0], tab[1], nil
}

// parseLocalizedNestedID parses a localizedNestedID and extracts the resource locality, the inner and outer id.
func parseLocalizedNestedID(localizedID string) (locality string, innerID, outerID string, err error) {
tab := strings.SplitN(localizedID, "/", -1)
if len(tab) != 3 {
return "", "", localizedID, fmt.Errorf("cant parse localized id: %s", localizedID)
}
return tab[0], tab[1], tab[2], nil
}

// parseZonedID parses a zonedID and extracts the resource zone and id.
func parseZonedID(zonedID string) (zone scw.Zone, id string, err error) {
locality, id, err := parseLocalizedID(zonedID)
Expand All @@ -101,6 +110,17 @@ func parseZonedID(zonedID string) (zone scw.Zone, id string, err error) {
return
}

// parseZonedNestedID parses a zonedNestedID and extracts the resource zone ,inner and outer ID.
func parseZonedNestedID(zonedNestedID string) (zone scw.Zone, outerID, innerID string, err error) {
locality, innerID, outerID, err := parseLocalizedNestedID(zonedNestedID)
if err != nil {
return
}

zone, err = scw.ParseZone(locality)
return
}

// expandID returns the id whether it is a localizedID or a raw ID.
func expandID(id interface{}) string {
_, ID, err := parseLocalizedID(id.(string))
Expand All @@ -126,6 +146,11 @@ func newZonedIDString(zone scw.Zone, id string) string {
return fmt.Sprintf("%s/%s", zone, id)
}

// newZonedNestedIDString constructs a unique identifier based on resource zone, inner and outer IDs
func newZonedNestedIDString(zone scw.Zone, outerID, innerID string) string {
return fmt.Sprintf("%s/%s/%s", zone, outerID, innerID)
}

// newRegionalIDString constructs a unique identifier based on resource region and id
func newRegionalIDString(region scw.Region, id string) string {
return fmt.Sprintf("%s/%s", region, id)
Expand Down
9 changes: 9 additions & 0 deletions scaleway/helpers_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@ func instanceAPIWithZoneAndID(m interface{}, zonedID string) (*instance.API, scw
return instanceAPI, zone, ID, err
}

// instanceAPIWithZoneAndNestedID returns an instance API with zone and inner/outer ID extracted from the state
func instanceAPIWithZoneAndNestedID(m interface{}, zonedNestedID string) (*instance.API, scw.Zone, string, string, error) {
meta := m.(*Meta)
instanceAPI := instance.NewAPI(meta.scwClient)

zone, innerID, outerID, err := parseZonedNestedID(zonedNestedID)
return instanceAPI, zone, innerID, outerID, err
}

// hash hashes a string to a unique hashcode.
//
// crc32 returns a uint32, but for our use we need
Expand Down
25 changes: 25 additions & 0 deletions scaleway/helpers_vpc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package scaleway

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

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

zone, err := extractZone(d, meta)
return vpcAPI, zone, err
}

// vpcAPIWithZoneAndID
func vpcAPIWithZoneAndID(m interface{}, id string) (*vpc.API, scw.Zone, string, error) {
meta := m.(*Meta)
vpcAPI := vpc.NewAPI(meta.scwClient)

zone, ID, err := parseZonedID(id)
return vpcAPI, zone, ID, err
}
3 changes: 3 additions & 0 deletions scaleway/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ func Provider(config *ProviderConfig) plugin.ProviderFunc {
"scaleway_instance_security_group_rules": resourceScalewayInstanceSecurityGroupRules(),
"scaleway_instance_server": resourceScalewayInstanceServer(),
"scaleway_instance_placement_group": resourceScalewayInstancePlacementGroup(),
"scaleway_instance_private_nic": resourceScalewayInstancePrivateNIC(),
"scaleway_k8s_cluster": resourceScalewayK8SCluster(),
"scaleway_k8s_pool": resourceScalewayK8SPool(),
"scaleway_lb": resourceScalewayLb(),
Expand All @@ -86,6 +87,7 @@ func Provider(config *ProviderConfig) plugin.ProviderFunc {
"scaleway_rdb_instance": resourceScalewayRdbInstance(),
"scaleway_rdb_user": resourceScalewayRdbUser(),
"scaleway_object_bucket": resourceScalewayObjectBucket(),
"scaleway_vpc_private_network": resourceScalewayVPCPrivateNetwork(),
},

DataSourcesMap: map[string]*schema.Resource{
Expand All @@ -100,6 +102,7 @@ func Provider(config *ProviderConfig) plugin.ProviderFunc {
"scaleway_marketplace_image": dataSourceScalewayMarketplaceImage(),
"scaleway_registry_namespace": dataSourceScalewayRegistryNamespace(),
"scaleway_registry_image": dataSourceScalewayRegistryImage(),
"scaleway_vpc_private_network": dataSourceScalewayVPCPrivateNetwork(),
},
}

Expand Down
Loading