diff --git a/docs/resources/metal_vrf.md b/docs/resources/metal_vrf.md index 92848e959..a28b97890 100644 --- a/docs/resources/metal_vrf.md +++ b/docs/resources/metal_vrf.md @@ -75,20 +75,27 @@ resource "equinix_metal_virtual_circuit" "example" { } ``` -## Argument Reference + +## Schema -The following arguments are supported: +### Required -* `name` - (Required) User-supplied name of the VRF, unique to the project -* `metro` - (Required) Metro ID or Code where the VRF will be deployed. -* `project_id` - (Required) Project ID where the VRF will be deployed. -* `description` - (Optional) Description of the VRF. -* `local_asn` - (Optional) The 4-byte ASN set on the VRF. -* `ip_ranges` - (Optional) All IPv4 and IPv6 Ranges that will be available to BGP Peers. IPv4 addresses must be /8 or smaller with a minimum size of /29. IPv6 must be /56 or smaller with a minimum size of /64. Ranges must not overlap other ranges within the VRF. +- `metro` (String) Metro ID or Code where the VRF will be deployed +- `name` (String) User-supplied name of the VRF, unique to the project +- `project_id` (String) Project ID where the VRF will be deployed -## Attributes Reference +### Optional -No additional attributes are exported. +- `bgp_dynamic_neighbors_bfd_enabled` (Boolean) Toggle BFD on dynamic bgp neighbors sessions +- `bgp_dynamic_neighbors_enabled` (Boolean) Toggle to enable the dynamic bgp neighbors feature on the VRF +- `bgp_dynamic_neighbors_export_route_map` (Boolean) Toggle to export the VRF route-map to the dynamic bgp neighbors +- `description` (String) Description of the VRF +- `ip_ranges` (Set of String) All IPv4 and IPv6 Ranges that will be available to BGP Peers. IPv4 addresses must be /8 or smaller with a minimum size of /29. IPv6 must be /56 or smaller with a minimum size of /64. Ranges must not overlap other ranges within the VRF. +- `local_asn` (Number) The 4-byte ASN set on the VRF + +### Read-Only + +- `id` (String) The ID of this resource. ## Import diff --git a/internal/resources/metal/vrf/datasource.go b/internal/resources/metal/vrf/datasource.go index 5662511b3..9ee326abf 100644 --- a/internal/resources/metal/vrf/datasource.go +++ b/internal/resources/metal/vrf/datasource.go @@ -48,6 +48,34 @@ func DataSource() *schema.Resource { Computed: true, Description: "Project ID", }, + "bgp_dynamic_neighbors": { + Type: schema.TypeList, + Description: "BGP dynamic neighbor settings for this VRF", + Optional: true, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + Description: "Toggle to enable the dynamic bgp neighbors feature on the VRF", + }, + "export_route_map": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + Description: "Toggle to export the VRF route-map to the dynamic bgp neighbors", + }, + "bfd_enabled": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + Description: "Toggle BFD on dynamic bgp neighbors sessions", + }, + }, + }, + }, }, } } diff --git a/internal/resources/metal/vrf/resource.go b/internal/resources/metal/vrf/resource.go index e8bf6688d..d8e447322 100644 --- a/internal/resources/metal/vrf/resource.go +++ b/internal/resources/metal/vrf/resource.go @@ -38,13 +38,13 @@ func Resource() *schema.Resource { "metro": { Type: schema.TypeString, Required: true, - Description: "Metro Code", + Description: "Metro ID or Code where the VRF will be deployed", }, "local_asn": { Type: schema.TypeInt, Optional: true, Computed: true, - Description: "The 4-byte ASN set on the VRF.", + Description: "The 4-byte ASN set on the VRF", }, "ip_ranges": { Type: schema.TypeSet, @@ -55,7 +55,25 @@ func Resource() *schema.Resource { "project_id": { Type: schema.TypeString, Required: true, - Description: "Project ID", + Description: "Project ID where the VRF will be deployed", + }, + "bgp_dynamic_neighbors_enabled": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + Description: "Toggle to enable the dynamic bgp neighbors feature on the VRF", + }, + "bgp_dynamic_neighbors_export_route_map": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + Description: "Toggle to export the VRF route-map to the dynamic bgp neighbors", + }, + "bgp_dynamic_neighbors_bfd_enabled": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + Description: "Toggle BFD on dynamic bgp neighbors sessions", }, // TODO: created_by, created_at, updated_at, href }, @@ -75,6 +93,15 @@ func resourceMetalVRFCreate(ctx context.Context, d *schema.ResourceData, meta in if value, ok := d.GetOk("local_asn"); ok { createRequest.LocalAsn = metalv1.PtrInt64(int64(value.(int))) } + if value, ok := d.GetOk("bgp_dynamic_neighbors_enabled"); ok { + createRequest.SetBgpDynamicNeighborsEnabled(value.(bool)) + } + if value, ok := d.GetOk("bgp_dynamic_neighbors_export_route_map"); ok { + createRequest.SetBgpDynamicNeighborsExportRouteMap(value.(bool)) + } + if value, ok := d.GetOk("bgp_dynamic_neighbors_bfd_enabled"); ok { + createRequest.SetBgpDynamicNeighborsBfdEnabled(value.(bool)) + } projectId := d.Get("project_id").(string) vrf, _, err := client.VRFsApi. @@ -107,6 +134,15 @@ func resourceMetalVRFUpdate(ctx context.Context, d *schema.ResourceData, meta in ipRanges := converters.SetToStringList(d.Get("ip_ranges").(*schema.Set)) updateRequest.SetIpRanges(ipRanges) } + if d.HasChange("bgp_dynamic_neighbors_enabled") { + updateRequest.SetBgpDynamicNeighborsEnabled(d.Get("bgp_dynamic_neighbors_enabled").(bool)) + } + if d.HasChange("bgp_dynamic_neighbors_export_route_map") { + updateRequest.SetBgpDynamicNeighborsExportRouteMap(d.Get("bgp_dynamic_neighbors_export_route_map").(bool)) + } + if d.HasChange("bgp_dynamic_neighbors_bfd_enabled") { + updateRequest.SetBgpDynamicNeighborsBfdEnabled(d.Get("bgp_dynamic_neighbors_bfd_enabled").(bool)) + } _, _, err := client.VRFsApi. UpdateVrf(ctx, d.Id()). @@ -136,12 +172,15 @@ func resourceMetalVRFRead(ctx context.Context, d *schema.ResourceData, meta inte return diag.FromErr(err) } m := map[string]interface{}{ - "name": vrf.GetName(), - "description": vrf.GetDescription(), - "metro": vrf.Metro.GetCode(), - "local_asn": vrf.GetLocalAsn(), - "ip_ranges": vrf.GetIpRanges(), - "project_id": vrf.Project.GetId(), + "name": vrf.GetName(), + "description": vrf.GetDescription(), + "metro": vrf.Metro.GetCode(), + "local_asn": vrf.GetLocalAsn(), + "ip_ranges": vrf.GetIpRanges(), + "project_id": vrf.Project.GetId(), + "bgp_dynamic_neighbors_enabled": vrf.GetBgpDynamicNeighborsEnabled(), + "bgp_dynamic_neighbors_export_route_map": vrf.GetBgpDynamicNeighborsExportRouteMap(), + "bgp_dynamic_neighbors_bfd_enabled": vrf.GetBgpDynamicNeighborsBfdEnabled(), } return diag.FromErr(equinix_schema.SetMap(d, m)) diff --git a/internal/resources/metal/vrf/resource_test.go b/internal/resources/metal/vrf/resource_test.go index 4dde01138..4359a1107 100644 --- a/internal/resources/metal/vrf/resource_test.go +++ b/internal/resources/metal/vrf/resource_test.go @@ -17,6 +17,9 @@ import ( const ( metalDedicatedConnIDEnvVar = "TF_ACC_METAL_DEDICATED_CONNECTION_ID" + // This used to be repeated in each config function + // Extracting it for now but other test suites pick a dynamic metro + testMetro = "da" ) func TestAccMetalVRF_basic(t *testing.T) { @@ -48,6 +51,58 @@ func TestAccMetalVRF_basic(t *testing.T) { }) } +func TestAccMetalVRF_bgpDynamicNeighbors(t *testing.T) { + var vrf metalv1.Vrf + rInt := acctest.RandInt() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.TestAccPreCheckMetal(t) }, + ExternalProviders: acceptance.TestExternalProviders, + ProtoV5ProviderFactories: acceptance.ProtoV5ProviderFactories, + CheckDestroy: testAccMetalVRFCheckDestroyed, + Steps: []resource.TestStep{ + { + Config: testAccMetalVRFConfig_bgpDynamicNeighbors(rInt, true, true, true), + Check: resource.ComposeTestCheckFunc( + testAccMetalVRFExists("equinix_metal_vrf.test", &vrf), + resource.TestCheckResourceAttr( + "equinix_metal_vrf.test", "bgp_dynamic_neighbors_enabled", "true"), + resource.TestCheckResourceAttr( + "equinix_metal_vrf.test", "bgp_dynamic_neighbors_export_route_map", "true"), + resource.TestCheckResourceAttr( + "equinix_metal_vrf.test", "bgp_dynamic_neighbors_bfd_enabled", "true"), + ), + }, + { + ResourceName: "equinix_metal_vrf.test", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccMetalVRFConfig_bgpDynamicNeighbors(rInt, false, false, false), + Check: resource.ComposeTestCheckFunc( + testAccMetalVRFExists("equinix_metal_vrf.test", &vrf), + resource.TestCheckResourceAttr( + "equinix_metal_vrf.test", "bgp_dynamic_neighbors_enabled", "false"), + resource.TestCheckResourceAttr( + "equinix_metal_vrf.test", "bgp_dynamic_neighbors_export_route_map", "false"), + resource.TestCheckResourceAttr( + "equinix_metal_vrf.test", "bgp_dynamic_neighbors_bfd_enabled", "false"), + ), + }, + { + ResourceName: "equinix_metal_vrf.test", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccMetalVRFConfig_basic(rInt), + PlanOnly: true, + }, + }, + }) +} + func TestAccMetalVRF_withIPRanges(t *testing.T) { var vrf metalv1.Vrf rInt := acctest.RandInt() @@ -289,8 +344,6 @@ func testAccMetalVRFExists(n string, vrf *metalv1.Vrf) resource.TestCheckFunc { } func testAccMetalVRFConfig_basic(r int) string { - testMetro := "da" - return fmt.Sprintf(` resource "equinix_metal_project" "test" { name = "tfacc-vrfs-%d" @@ -303,9 +356,23 @@ resource "equinix_metal_vrf" "test" { }`, r, r, testMetro) } -func testAccMetalVRFConfig_withIPRanges(r int) string { - testMetro := "da" +func testAccMetalVRFConfig_bgpDynamicNeighbors(r int, enabled, export_route_map, bfd_enabled bool) string { + return fmt.Sprintf(` +resource "equinix_metal_project" "test" { + name = "tfacc-vrfs-%d" +} + +resource "equinix_metal_vrf" "test" { + name = "tfacc-vrf-%d" + metro = "%s" + project_id = "${equinix_metal_project.test.id}" + bgp_dynamic_neighbors_enabled = %v + bgp_dynamic_neighbors_export_route_map = %v + bgp_dynamic_neighbors_bfd_enabled = %v +}`, r, r, testMetro, enabled, export_route_map, bfd_enabled) +} +func testAccMetalVRFConfig_withIPRanges(r int) string { return fmt.Sprintf(` resource "equinix_metal_project" "test" { name = "tfacc-vrfs-%d" @@ -322,8 +389,6 @@ resource "equinix_metal_vrf" "test" { } func testAccMetalVRFConfig_withIPReservations(r int) string { - testMetro := "da" - return testAccMetalVRFConfig_withIPRanges(r) + fmt.Sprintf(` resource "equinix_metal_reserved_ip_block" "test" { @@ -339,8 +404,6 @@ resource "equinix_metal_reserved_ip_block" "test" { } func testAccMetalVRFConfig_withGateway(r int) string { - testMetro := "da" - return testAccMetalVRFConfig_withIPReservations(r) + fmt.Sprintf(` resource "equinix_metal_vlan" "test" { diff --git a/templates/resources/metal_vrf.md.tmpl b/templates/resources/metal_vrf.md.tmpl index 4d7e4732a..b496ed370 100644 --- a/templates/resources/metal_vrf.md.tmpl +++ b/templates/resources/metal_vrf.md.tmpl @@ -26,20 +26,7 @@ Attach a Virtual Circuit from a Dedicated Metal Connection to the Metal Gateway. {{tffile "examples/resources/metal_vrf/example_3.tf"}} -## Argument Reference - -The following arguments are supported: - -* `name` - (Required) User-supplied name of the VRF, unique to the project -* `metro` - (Required) Metro ID or Code where the VRF will be deployed. -* `project_id` - (Required) Project ID where the VRF will be deployed. -* `description` - (Optional) Description of the VRF. -* `local_asn` - (Optional) The 4-byte ASN set on the VRF. -* `ip_ranges` - (Optional) All IPv4 and IPv6 Ranges that will be available to BGP Peers. IPv4 addresses must be /8 or smaller with a minimum size of /29. IPv6 must be /56 or smaller with a minimum size of /64. Ranges must not overlap other ranges within the VRF. - -## Attributes Reference - -No additional attributes are exported. +{{ .SchemaMarkdown | trimspace }} ## Import