Skip to content

Commit

Permalink
feat: add support for VRF BGP dynamic neighbors
Browse files Browse the repository at this point in the history
  • Loading branch information
ctreatma committed Aug 1, 2024
1 parent f984775 commit f26180a
Show file tree
Hide file tree
Showing 10 changed files with 624 additions and 3 deletions.
24 changes: 24 additions & 0 deletions docs/data-sources/metal_vrf_bgp_dynamic_neighbor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
subcategory: "Metal"
---

# equinix_metal_vrf_bgp_dynamic_neighbor (Data Source)

This resource manages BGP dynamic neighbor ranges for an Equinix Metal VRF, but with markdown



<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `id` (String) The unique identifier for this the dynamic BGP neighbor

### Read-Only

- `asn` (Number) The ASN of the dynamic BGP neighbor
- `gateway_id` (String) The ID of the Equinix Metal VRF gateway for this dynamic BGP neighbor range
- `range` (String) Network range of the dynamic BGP neighbor in CIDR format
- `state` (String) The state of the dynamic BGP neighbor
- `tags` (List of String) Tags attached to the dynamic BGP neighbor
27 changes: 27 additions & 0 deletions docs/resources/metal_vrf_bgp_dynamic_neighbor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
subcategory: "Metal"
---

# equinix_metal_vrf_bgp_dynamic_neighbor (Resource)

This resource manages BGP dynamic neighbor ranges for an Equinix Metal VRF, but with markdown



<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `asn` (Number) The ASN of the dynamic BGP neighbor
- `gateway_id` (String) The ID of the Equinix Metal VRF gateway for this dynamic BGP neighbor range
- `range` (String) Network range of the dynamic BGP neighbor in CIDR format

### Optional

- `tags` (List of String) Tags attached to the dynamic BGP neighbor

### Read-Only

- `id` (String) The unique identifier for this the dynamic BGP neighbor
- `state` (String) The state of the dynamic BGP neighbor
9 changes: 6 additions & 3 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import (
metalproject "github.com/equinix/terraform-provider-equinix/internal/resources/metal/project"
metalprojectsshkey "github.com/equinix/terraform-provider-equinix/internal/resources/metal/project_ssh_key"
metalsshkey "github.com/equinix/terraform-provider-equinix/internal/resources/metal/ssh_key"
"github.com/equinix/terraform-provider-equinix/internal/resources/metal/vlan"
metalvlan "github.com/equinix/terraform-provider-equinix/internal/resources/metal/vlan"
metalvrfbgpdynamicneighbor "github.com/equinix/terraform-provider-equinix/internal/resources/metal/vrf_bgp_dynamic_neighbor"
equinix_validation "github.com/equinix/terraform-provider-equinix/internal/validation"
"github.com/hashicorp/terraform-plugin-framework-validators/int64validator"
"github.com/hashicorp/terraform-plugin-framework/datasource"
Expand Down Expand Up @@ -121,7 +122,8 @@ func (p *FrameworkProvider) Resources(ctx context.Context) []func() resource.Res
metalconnection.NewResource,
metalorganization.NewResource,
metalorganizationmember.NewResource,
vlan.NewResource,
metalvlan.NewResource,
metalvrfbgpdynamicneighbor.NewResource,
}
}

Expand All @@ -132,6 +134,7 @@ func (p *FrameworkProvider) DataSources(ctx context.Context) []func() datasource
metalprojectsshkey.NewDataSource,
metalconnection.NewDataSource,
metalorganization.NewDataSource,
vlan.NewDataSource,
metalvlan.NewDataSource,
metalvrfbgpdynamicneighbor.NewDataSource,
}
}
70 changes: 70 additions & 0 deletions internal/resources/metal/vrf_bgp_dynamic_neighbor/datasource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package vrfbgpdynamicneighbor

import (
"context"

"github.com/equinix/terraform-provider-equinix/internal/framework"

"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
)

type DataSource struct {
framework.BaseDataSource
framework.WithTimeouts
}

func NewDataSource() datasource.DataSource {
return &DataSource{
BaseDataSource: framework.NewBaseDataSource(
framework.BaseDataSourceConfig{
Name: "equinix_metal_vrf_bgp_dynamic_neighbor",
},
),
}
}

func (r *DataSource) Schema(
ctx context.Context,
req datasource.SchemaRequest,
resp *datasource.SchemaResponse,
) {
s := datasourceSchema(ctx)
if s.Blocks == nil {
s.Blocks = make(map[string]schema.Block)
}

resp.Schema = s
}

func (d *DataSource) Read(ctx context.Context, request datasource.ReadRequest, response *datasource.ReadResponse) {
client := d.Meta.NewMetalClientForFramework(ctx, request.ProviderMeta)

var data Model
response.Diagnostics.Append(request.Config.Get(ctx, &data)...)
if response.Diagnostics.HasError() {
return
}

neighbor, _, err := client.VRFsApi.BgpDynamicNeighborsIdGet(ctx, data.ID.ValueString()).
// `created_by` is specified as a UserLimited. To avoid an error
// due to missing UserLimited.id field, have to either exclude
// or include `created_by`
Exclude(bgpNeighborExcludes).
Include(bgpNeighborIncludes).
Execute()

if err != nil {
response.Diagnostics.AddError(
"Error reading VRF BGP dynamic neighbor range",
"Could not read VRF BGP dynamic neighbor with ID "+data.ID.ValueString()+": "+err.Error(),
)
}

response.Diagnostics.Append(data.parse(ctx, neighbor)...)
if response.Diagnostics.HasError() {
return
}

response.Diagnostics.Append(response.State.Set(ctx, &data)...)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package vrfbgpdynamicneighbor

import (
"context"

"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
)

func datasourceSchema(_ context.Context) schema.Schema {
return schema.Schema{
Description: "This resource manages BGP dynamic neighbor ranges for an Equinix Metal VRF",
MarkdownDescription: "This resource manages BGP dynamic neighbor ranges for an Equinix Metal VRF, but with markdown",
Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{
Description: "The unique identifier for this the dynamic BGP neighbor",
Required: true,
},
"gateway_id": schema.StringAttribute{
Description: "The ID of the Equinix Metal VRF gateway for this dynamic BGP neighbor range",
Computed: true,
},
"range": schema.StringAttribute{
Description: "Network range of the dynamic BGP neighbor in CIDR format",
Computed: true,
},
"asn": schema.Int64Attribute{
Description: "The ASN of the dynamic BGP neighbor",
Computed: true,
},
"state": schema.StringAttribute{
Description: "The state of the dynamic BGP neighbor",
Computed: true,
},
"tags": schema.ListAttribute{
Description: "Tags attached to the dynamic BGP neighbor",
ElementType: types.StringType,
Computed: true,
},
},
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package vrfbgpdynamicneighbor_test

import (
"fmt"
"testing"

"github.com/equinix/terraform-provider-equinix/internal/acceptance"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
)

func TestAccDataSourceMetalVrfBgpDynamicNeighbor_basic(t *testing.T) {
rs := acctest.RandString(10)
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acceptance.TestAccPreCheckMetal(t) },
ExternalProviders: acceptance.TestExternalProviders,
ProtoV5ProviderFactories: acceptance.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckDestroyed,
Steps: []resource.TestStep{
{
Config: testAccDataSourceMetalVrfBgpDynamicNeighborConfig(rs),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrPair(
"data.equinix_metal_vrf_bgp_dynamic_neighbor.test", "gateway_id",
"equinix_metal_gateway.test", "id"),
resource.TestCheckResourceAttr(
"data.equinix_metal_vrf_bgp_dynamic_neighbor.test", "range",
"2001:d78:0:0:4000::/66"),
resource.TestCheckResourceAttr(
"data.equinix_metal_vrf_bgp_dynamic_neighbor.test", "asn",
"56789"),
),
},
},
})
}

func testAccDataSourceMetalVrfBgpDynamicNeighborConfig(projSuffix string) string {
return fmt.Sprintf(`
resource "equinix_metal_project" "test" {
name = "tfacc-vrf-bgp-neighbor-test-%s"
}
resource "equinix_metal_vlan" "test" {
description = "tfacc-vlan VLAN in SV"
metro = "sv"
project_id = equinix_metal_project.test.id
}
resource "equinix_metal_vrf" "test" {
description = "tfacc-vrf VRF in SV"
name = "tfacc-vrf-%s"
metro = "sv"
local_asn = "65000"
ip_ranges = ["2001:d78::/59"]
project_id = equinix_metal_project.test.id
}
resource "equinix_metal_reserved_ip_block" "test" {
project_id = equinix_metal_project.test.id
type = "vrf"
vrf_id = equinix_metal_vrf.test.id
network = "2001:d78::"
metro = "sv"
cidr = 64
}
resource "equinix_metal_gateway" "test" {
project_id = equinix_metal_project.test.id
vlan_id = equinix_metal_vlan.test.id
ip_reservation_id = equinix_metal_reserved_ip_block.test.id
}
resource "equinix_metal_vrf_bgp_dynamic_neighbor" "test" {
gateway_id = equinix_metal_gateway.test.id
range = "2001:d78:0:0:4000::/66"
asn = "56789"
}
data "equinix_metal_vrf_bgp_dynamic_neighbor" "test" {
id = equinix_metal_vrf_bgp_dynamic_neighbor.test.id
}
`, projSuffix, projSuffix)
}
36 changes: 36 additions & 0 deletions internal/resources/metal/vrf_bgp_dynamic_neighbor/model.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package vrfbgpdynamicneighbor

import (
"context"

"github.com/equinix/equinix-sdk-go/services/metalv1"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/types"
)

type Model struct {
ID types.String `tfsdk:"id"`
GatewayID types.String `tfsdk:"gateway_id"`
Range types.String `tfsdk:"range"`
ASN types.Int64 `tfsdk:"asn"`
State types.String `tfsdk:"state"`
Tags types.List `tfsdk:"tags"` // List of strings
}

func (m *Model) parse(ctx context.Context, neighbor *metalv1.BgpDynamicNeighbor) (d diag.Diagnostics) {
m.ID = types.StringValue(neighbor.GetId())

m.GatewayID = types.StringValue(neighbor.MetalGateway.GetId())
m.Range = types.StringValue(neighbor.GetBgpNeighborRange())
m.ASN = types.Int64Value(neighbor.GetBgpNeighborAsn())
m.State = types.StringValue(string(neighbor.GetState()))

tags, diags := types.ListValueFrom(ctx, types.StringType, neighbor.GetTags())
if diags.HasError() {
return diags
}

m.Tags = tags

return nil
}
Loading

0 comments on commit f26180a

Please sign in to comment.