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): add routes datasource #2621

Merged
merged 8 commits into from
Jun 21, 2024
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
2 changes: 1 addition & 1 deletion docs/data-sources/marketplace_image.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ data "scaleway_marketplace_image" "my_image" {

## Argument Reference

- `label` - (Required) Exact label of the desired image. You can use [this endpoint](https://api-marketplace.scaleway.com/images?page=1&per_page=100)
- `label` - (Required) Exact label of the desired image. You can use [this endpoint](https://www.scaleway.com/en/developers/api/marketplace/#path-marketplace-images-list-marketplace-images)
to find the right `label`.

- `instance_type` - (Optional, default `DEV1-S`) The instance type the image is compatible with.
Expand Down
79 changes: 79 additions & 0 deletions docs/data-sources/vpc_routes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
---
subcategory: "VPC"
page_title: "Scaleway: scaleway_vpc_routes"
---

# scaleway_vpc_routes

Gets information about multiple VPC routes.

## Example Usage

```hcl
resource scaleway_vpc vpc01 {
name = "tf-vpc-route"
enable_routing = true
}

resource scaleway_vpc_private_network pn01 {
name = "tf-pn-route"
vpc_id = scaleway_vpc.vpc01.id
}

resource scaleway_vpc_private_network pn02 {
name = "tf-pn_route-2"
vpc_id = scaleway_vpc.vpc01.id
}

# Find routes with a matching VPC ID
data "scaleway_vpc_routes" "routes_by_vpc_id" {
vpc_id = scaleway_vpc.vpc01.id
}

# Find routes with a matching next hop private network ID
data "scaleway_vpc_routes" "routes_by_pn_id" {
vpc_id = scaleway_vpc.vpc01.id
nexthop_private_network_id = scaleway_vpc_private_network.pn01.id
}

# Find routes with an IPv6 destination
data "scaleway_vpc_routes" "routes_by_pn_id" {
vpc_id = scaleway_vpc.vpc01.id
is_ipv6 = true
}

# Find routes with a nexthop resource type
data "scaleway_vpc_routes" "routes_by_pn_id" {
vpc_id = scaleway_vpc.vpc01.id
nexthop_resource_type = "vpc_gateway_network"
}
```

## Argument Reference

- `vpc_id` - (Optional) The VPC ID to filter for. routes with a similar VPC ID are listed.

- `nexthop_resource_id` - (Optional) The next hop resource ID to filter for. routes with a similar next hop resource ID are listed.

- `nexthop_private_network_id` - (Optional) The next hop private network ID to filter for. routes with a similar next hop private network ID are listed.

- `nexthop_resource_type` - (Optional) The next hop resource type to filter for. routes with a similar next hop resource type are listed.

- `is_ipv6` - (Optional) Routes with an IPv6 destination will be listed.

- `tags` - (Optional) List of tags to filter for. routes with these exact tags are listed.

- `region` - (Defaults to [provider](../index.md#region) `region`). The [region](../guides/regions_and_zones.md#regions) in which the routes exist.

## Attributes Reference

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

- `routes` - List of retrieved routes
- `id` - The ID of the route.
~> **Important:** route IDs are [regional](../guides/regions_and_zones.md#resource-ids), which means they are of the form `{region}/{id}`, e.g. `fr-par/11111111-1111-1111-1111-111111111111
- `created_at` - The date on which the route was created (RFC 3339 format).
- `destination` - The destination IP or IP range of the route.
- `description` - The description of the route.
- `nexthop_ip` - The IP of the route's next hop.
- `nexthop_name` - The name of the route's next hop.
2 changes: 1 addition & 1 deletion docs/resources/instance_server.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ Use `replace_on_type_change` to trigger replacement instead of migration.

~> **Important:** If `type` change and migration occurs, the server will be stopped and changed backed to its original state. It will be started again if it was running.

- `image` - (Optional) The UUID or the label of the base image used by the server. You can use [this endpoint](https://api-marketplace.scaleway.com/images?page=1&per_page=100)
- `image` - (Optional) The UUID or the label of the base image used by the server. You can use [this endpoint](https://www.scaleway.com/en/developers/api/marketplace/#path-marketplace-images-list-marketplace-images)
to find either the right `label` or the right local image `ID` for a given `type`. Optional when creating an instance with an existing root volume.

You can check the available labels with our [CLI](https://www.scaleway.com/en/docs/compute/instances/api-cli/creating-managing-instances-with-cliv2/). ```scw marketplace image list```
Expand Down
1 change: 1 addition & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ func Provider(config *Config) plugin.ProviderFunc {
"scaleway_vpc_public_gateway_dhcp_reservation": vpcgw.DataSourceDHCPReservation(),
"scaleway_vpc_public_gateway_ip": vpcgw.DataSourceIP(),
"scaleway_vpc_public_gateway_pat_rule": vpcgw.DataSourcePATRule(),
"scaleway_vpc_routes": vpc.DataSourceRoutes(),
"scaleway_vpcs": vpc.DataSourceVPCs(),
"scaleway_webhosting": webhosting.DataSourceWebhosting(),
"scaleway_webhosting_offer": webhosting.DataSourceOffer(),
Expand Down
11 changes: 11 additions & 0 deletions internal/services/vpc/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,17 @@ func NewAPI(m interface{}) (*vpc.API, error) {
return vpc.NewAPI(meta.ExtractScwClient(m)), nil
}

// routesAPIWithRegion returns a new VPC API and the region for a Create request
func routesAPIWithRegion(d *schema.ResourceData, m interface{}) (*vpc.RoutesWithNexthopAPI, scw.Region, error) {
routesAPI := vpc.NewRoutesWithNexthopAPI(meta.ExtractScwClient(m))

region, err := meta.ExtractRegion(d, m)
if err != nil {
return nil, "", err
}
return routesAPI, region, err
}

func vpcPrivateNetworkUpgradeV1SchemaType() cty.Type {
return cty.Object(map[string]cty.Type{
"id": cty.String,
Expand Down
184 changes: 184 additions & 0 deletions internal/services/vpc/routes_data_source.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
package vpc

import (
"context"

"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/v2"
"github.com/scaleway/scaleway-sdk-go/scw"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality/regional"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/types"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/verify"
)

func DataSourceRoutes() *schema.Resource {
return &schema.Resource{
ReadContext: DataSourceRoutesRead,
Schema: map[string]*schema.Schema{
"vpc_id": {
Type: schema.TypeString,
Optional: true,
Description: "Only routes within this VPC will be returned",
},
"nexthop_resource_id": {
Type: schema.TypeString,
Optional: true,
Description: "Only routes with a matching next hop resource ID will be returned",
},
"nexthop_private_network_id": {
Type: schema.TypeString,
Optional: true,
Description: "Only routes with a matching next hop private network ID will be returned",
},
"nexthop_resource_type": {
Type: schema.TypeString,
Optional: true,
Description: "Only Routes with a matching next hop resource type will be returned",
ValidateDiagFunc: verify.ValidateEnum[vpc.RouteWithNexthopResourceType](),
},
"is_ipv6": {
Type: schema.TypeBool,
Optional: true,
Description: "Only routes with an IPv6 destination will be returned",
},
"tags": {
Type: schema.TypeList,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Optional: true,
Description: "Routes with these exact tags are listed.",
},
"routes": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"id": {
Computed: true,
Type: schema.TypeString,
Description: "The associated route ID",
},
"vpc_id": {
Computed: true,
Type: schema.TypeString,
Description: "The VPC ID associated with the route",
},
"tags": {
Computed: true,
Type: schema.TypeList,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Description: "The tags associated with the route",
},
"created_at": {
Computed: true,
Type: schema.TypeString,
Description: "Date and time of route's creation (RFC 3339 format)",
},
"description": {
Computed: true,
Type: schema.TypeString,
Description: "The description of the route",
},
"destination": {
Computed: true,
Type: schema.TypeString,
Description: "The destination IP or IP range of the route",
},
"nexthop_resource_id": {
Computed: true,
Type: schema.TypeString,
Description: "The resource ID of the route's next hop",
},
"nexthop_private_network_id": {
Computed: true,
Type: schema.TypeString,
Description: "The private network ID of the route's next hop",
},
"nexthop_ip": {
Computed: true,
Type: schema.TypeString,
Description: "The IP of the route's next hop",
},
"nexthop_name": {
Computed: true,
Type: schema.TypeString,
Description: "The name of the route's next hop",
},
"nexthop_resource_type": {
Computed: true,
Type: schema.TypeString,
Description: "The resource type of the route's next hop",
},
"region": regional.Schema(),
},
},
},
"region": regional.Schema(),
},
}
}

func DataSourceRoutesRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
routesAPI, region, err := routesAPIWithRegion(d, m)
if err != nil {
return diag.FromErr(err)
}

req := &vpc.RoutesWithNexthopAPIListRoutesWithNexthopRequest{
Region: region,
Tags: types.ExpandStrings(d.Get("tags")),
VpcID: types.ExpandStringPtr(locality.ExpandID(d.Get("vpc_id"))),
NexthopResourceID: types.ExpandStringPtr(locality.ExpandID(d.Get("nexthop_resource_id"))),
NexthopPrivateNetworkID: types.ExpandStringPtr(locality.ExpandID(d.Get("nexthop_private_network_id"))),
NexthopResourceType: vpc.RouteWithNexthopResourceType(d.Get("nexthop_resource_type").(string)),
}

isipv6, isipv6Exists := d.GetOk("is_ipv6")
if isipv6Exists {
req.IsIPv6 = types.ExpandBoolPtr(isipv6)
}

res, err := routesAPI.ListRoutesWithNexthop(req, scw.WithContext(ctx))
if err != nil {
return diag.FromErr(err)
}

routes := []interface{}(nil)
for _, route := range res.Routes {
rawRoute := make(map[string]interface{})
if route.Route != nil {
rawRoute["id"] = regional.NewIDString(region, route.Route.ID)
rawRoute["created_at"] = types.FlattenTime(route.Route.CreatedAt)
rawRoute["vpc_id"] = route.Route.VpcID
rawRoute["nexthop_resource_id"] = types.FlattenStringPtr(route.Route.NexthopResourceID)
rawRoute["nexthop_private_network_id"] = types.FlattenStringPtr(route.Route.NexthopPrivateNetworkID)
rawRoute["description"] = route.Route.Description
rawRoute["region"] = region.String()

destination, err := types.FlattenIPNet(route.Route.Destination)
if err != nil {
return diag.FromErr(err)
}
rawRoute["destination"] = destination

if len(route.Route.Tags) > 0 {
rawRoute["tags"] = route.Route.Tags
}
}
rawRoute["nexthop_ip"] = types.FlattenIPPtr(route.NexthopIP)
rawRoute["nexthop_name"] = types.FlattenStringPtr(route.NexthopName)
rawRoute["nexthop_resource_type"] = route.NexthopResourceType.String()

routes = append(routes, rawRoute)
}

d.SetId(region.String())
_ = d.Set("routes", routes)

return nil
}
Loading
Loading