diff --git a/internal/resources/metal/vlan/datasource.go b/internal/resources/metal/vlan/datasource.go index d5d93373f..ad27e608b 100644 --- a/internal/resources/metal/vlan/datasource.go +++ b/internal/resources/metal/vlan/datasource.go @@ -1,7 +1,7 @@ package vlan import ( - "fmt" + "context" "github.com/equinix/terraform-provider-equinix/internal/converters" @@ -10,13 +10,14 @@ import ( "github.com/equinix/terraform-provider-equinix/internal/config" + "github.com/equinix/equinix-sdk-go/services/metalv1" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/packethost/packngo" ) func DataSource() *schema.Resource { return &schema.Resource{ - Read: dataSourceMetalVlanRead, + ReadWithoutTimeout: dataSourceMetalVlanRead, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, @@ -73,8 +74,8 @@ func DataSource() *schema.Resource { } } -func dataSourceMetalVlanRead(d *schema.ResourceData, meta interface{}) error { - client := meta.(*config.Config).Metal +func dataSourceMetalVlanRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + client := meta.(*config.Config).Metalgo projectRaw, projectOk := d.GetOk("project_id") vxlanRaw, vxlanOk := d.GetOk("vxlan") @@ -83,19 +84,19 @@ func dataSourceMetalVlanRead(d *schema.ResourceData, meta interface{}) error { facilityRaw, facilityOk := d.GetOk("facility") if !(vlanIdOk || (vxlanOk || projectOk || metroOk || facilityOk)) { - return equinix_errors.FriendlyError(fmt.Errorf("You must set either vlan_id or a combination of vxlan, project_id, and, metro or facility")) + return diag.Errorf("You must set either vlan_id or a combination of vxlan, project_id, and, metro or facility") } - var vlan *packngo.VirtualNetwork + var vlan *metalv1.VirtualNetwork if vlanIdOk { var err error - vlan, _, err = client.ProjectVirtualNetworks.Get( - vlanIdRaw.(string), - &packngo.GetOptions{Includes: []string{"assigned_to"}}, - ) + vlan, _, err = client.VLANsApi. + GetVirtualNetwork(ctx, vlanIdRaw.(string)). + Include([]string{"assigned_to"}).Execute() + if err != nil { - return equinix_errors.FriendlyError(err) + return diag.FromErr(equinix_errors.FriendlyError(err)) } } else { @@ -103,33 +104,33 @@ func dataSourceMetalVlanRead(d *schema.ResourceData, meta interface{}) error { vxlan := vxlanRaw.(int) metro := metroRaw.(string) facility := facilityRaw.(string) - vlans, _, err := client.ProjectVirtualNetworks.List( - projectRaw.(string), - &packngo.GetOptions{Includes: []string{"assigned_to"}}, - ) + vlans, _, err := client.VLANsApi. + FindVirtualNetworks(ctx, projectRaw.(string)). + Include([]string{"assigned_to"}).Execute() + if err != nil { - return equinix_errors.FriendlyError(err) + return diag.FromErr(equinix_errors.FriendlyError(err)) } vlan, err = MatchingVlan(vlans.VirtualNetworks, vxlan, projectID, facility, metro) if err != nil { - return equinix_errors.FriendlyError(err) + return diag.FromErr(equinix_errors.FriendlyError(err)) } } assignedDevices := []string{} for _, d := range vlan.Instances { - assignedDevices = append(assignedDevices, d.ID) + assignedDevices = append(assignedDevices, d.GetId()) // instances is a list of href, should be list of device? } - d.SetId(vlan.ID) + d.SetId(vlan.GetId()) - return equinix_schema.SetMap(d, map[string]interface{}{ - "vlan_id": vlan.ID, - "project_id": vlan.Project.ID, - "vxlan": vlan.VXLAN, - "facility": vlan.FacilityCode, + return diag.FromErr(equinix_schema.SetMap(d, map[string]interface{}{ + "vlan_id": vlan.GetId(), + "project_id": vlan.AssignedTo.GetId(), // vlan assigned_to is an href; should be project? + "vxlan": vlan.GetVxlan(), + "facility": vlan.FacilityCode, // facility is deprecated, vlan is metro-scoped; remove this attr? "metro": vlan.MetroCode, "description": vlan.Description, - }) + })) } diff --git a/internal/resources/metal/vlan/datasource_test.go b/internal/resources/metal/vlan/datasource_test.go index 080fa85b8..b41bd3312 100644 --- a/internal/resources/metal/vlan/datasource_test.go +++ b/internal/resources/metal/vlan/datasource_test.go @@ -9,10 +9,10 @@ import ( "github.com/equinix/terraform-provider-equinix/internal/config" "github.com/equinix/terraform-provider-equinix/internal/resources/metal/vlan" + "github.com/equinix/equinix-sdk-go/services/metalv1" "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" - "github.com/packethost/packngo" ) func TestAccDataSourceMetalVlan_byVxlanFacility(t *testing.T) { @@ -227,7 +227,7 @@ data "equinix_metal_vlan" "dsvlan" { func TestMetalVlan_MatchingVlan(t *testing.T) { type args struct { - vlans []packngo.VirtualNetwork + vlans []metalv1.VirtualNetwork vxlan int projectID string facility string @@ -236,52 +236,52 @@ func TestMetalVlan_MatchingVlan(t *testing.T) { tests := []struct { name string args args - want *packngo.VirtualNetwork + want *metalv1.VirtualNetwork wantErr bool }{ { name: "MatchingVLAN", args: args{ - vlans: []packngo.VirtualNetwork{{VXLAN: 123}}, + vlans: []metalv1.VirtualNetwork{{Vxlan: metalv1.PtrInt32(123)}}, vxlan: 123, projectID: "", facility: "", metro: "", }, - want: &packngo.VirtualNetwork{VXLAN: 123}, + want: &metalv1.VirtualNetwork{Vxlan: metalv1.PtrInt32(123)}, wantErr: false, }, { name: "MatchingFac", args: args{ - vlans: []packngo.VirtualNetwork{{FacilityCode: "fac"}}, + vlans: []metalv1.VirtualNetwork{{FacilityCode: "fac"}}, facility: "fac", }, - want: &packngo.VirtualNetwork{FacilityCode: "fac"}, + want: &metalv1.VirtualNetwork{FacilityCode: "fac"}, wantErr: false, }, { name: "MatchingMet", args: args{ - vlans: []packngo.VirtualNetwork{{MetroCode: "met"}}, + vlans: []metalv1.VirtualNetwork{{MetroCode: metalv1.PtrString("met")}}, metro: "met", }, - want: &packngo.VirtualNetwork{MetroCode: "met"}, + want: &metalv1.VirtualNetwork{MetroCode: metalv1.PtrString("met")}, wantErr: false, }, { name: "SecondMatch", args: args{ - vlans: []packngo.VirtualNetwork{{FacilityCode: "fac"}, {MetroCode: "met"}}, + vlans: []metalv1.VirtualNetwork{{FacilityCode: "fac"}, {MetroCode: metalv1.PtrString("met")}}, metro: "met", }, - want: &packngo.VirtualNetwork{MetroCode: "met"}, + want: &metalv1.VirtualNetwork{MetroCode: metalv1.PtrString("met")}, wantErr: false, }, { name: "TwoMatches", args: args{ - vlans: []packngo.VirtualNetwork{{MetroCode: "met"}, {MetroCode: "met"}}, + vlans: []metalv1.VirtualNetwork{{MetroCode: metalv1.PtrString("met")}, {MetroCode: metalv1.PtrString("met")}}, metro: "met", }, want: nil, @@ -290,10 +290,10 @@ func TestMetalVlan_MatchingVlan(t *testing.T) { { name: "ComplexMatch", args: args{ - vlans: []packngo.VirtualNetwork{{VXLAN: 987, FacilityCode: "fac", MetroCode: "skip"}, {VXLAN: 123, FacilityCode: "fac", MetroCode: "met"}, {VXLAN: 456, FacilityCode: "fac", MetroCode: "nope"}}, + vlans: []metalv1.VirtualNetwork{{Vxlan: metalv1.PtrInt32(987), FacilityCode: "fac", MetroCode: metalv1.PtrString("skip")}, {VXLAN: metalv1.PtrInt32(123), FacilityCode: "fac", MetroCode: metalv1.PtrString("met")}, {Vxlan: metalv1.PtrInt32(456), FacilityCode: "fac", MetroCode: metalv1.PtrString("nope")}}, metro: "met", }, - want: &packngo.VirtualNetwork{VXLAN: 123, FacilityCode: "fac", MetroCode: "met"}, + want: &metalv1.VirtualNetwork{Vxlan: metalv1.PtrInt32(123), FacilityCode: "fac", MetroCode: metalv1.PtrString("met")}, wantErr: false, }, { diff --git a/internal/resources/metal/vlan/matcher.go b/internal/resources/metal/vlan/matcher.go index 55f4293ce..05c1634fa 100644 --- a/internal/resources/metal/vlan/matcher.go +++ b/internal/resources/metal/vlan/matcher.go @@ -3,20 +3,20 @@ package vlan import ( "fmt" + "github.com/equinix/equinix-sdk-go/services/metalv1" equinix_errors "github.com/equinix/terraform-provider-equinix/internal/errors" - "github.com/packethost/packngo" ) -func MatchingVlan(vlans []packngo.VirtualNetwork, vxlan int, projectID, facility, metro string) (*packngo.VirtualNetwork, error) { - matches := []packngo.VirtualNetwork{} +func MatchingVlan(vlans []metalv1.VirtualNetwork, vxlan int, projectID, facility, metro string) (*metalv1.VirtualNetwork, error) { + matches := []metalv1.VirtualNetwork{} for _, v := range vlans { - if vxlan != 0 && v.VXLAN != vxlan { + if vxlan != 0 && int(v.GetVxlan()) != vxlan { continue } if facility != "" && v.FacilityCode != facility { continue } - if metro != "" && v.MetroCode != metro { + if metro != "" && v.GetMetroCode() != metro { continue } matches = append(matches, v) diff --git a/internal/resources/metal/vlan/resource.go b/internal/resources/metal/vlan/resource.go index 90daa62b8..7a8a06254 100644 --- a/internal/resources/metal/vlan/resource.go +++ b/internal/resources/metal/vlan/resource.go @@ -1,7 +1,7 @@ package vlan import ( - "errors" + "context" "path" "github.com/equinix/terraform-provider-equinix/internal/converters" @@ -10,15 +10,16 @@ import ( "github.com/equinix/terraform-provider-equinix/internal/config" + "github.com/equinix/equinix-sdk-go/services/metalv1" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/packethost/packngo" ) func Resource() *schema.Resource { return &schema.Resource{ - Create: resourceMetalVlanCreate, - Read: resourceMetalVlanRead, - Delete: resourceMetalVlanDelete, + CreateWithoutTimeout: resourceMetalVlanCreate, + ReadWithoutTimeout: resourceMetalVlanRead, + DeleteWithoutTimeout: resourceMetalVlanDelete, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, @@ -81,71 +82,70 @@ func Resource() *schema.Resource { } } -func resourceMetalVlanCreate(d *schema.ResourceData, meta interface{}) error { - meta.(*config.Config).AddModuleToMetalUserAgent(d) - client := meta.(*config.Config).Metal +func resourceMetalVlanCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + meta.(*config.Config).AddModuleToMetalGoUserAgent(d) + client := meta.(*config.Config).Metalgo facRaw, facOk := d.GetOk("facility") metroRaw, metroOk := d.GetOk("metro") vxlanRaw, vxlanOk := d.GetOk("vxlan") if !facOk && !metroOk { - return equinix_errors.FriendlyError(errors.New("one of facility or metro must be configured")) + return diag.Errorf("one of facility or metro must be configured") } if facOk && vxlanOk { - return equinix_errors.FriendlyError(errors.New("you can set vxlan only for metro vlans")) + return diag.Errorf("you can set vxlan only for metro vlans") } - createRequest := &packngo.VirtualNetworkCreateRequest{ - ProjectID: d.Get("project_id").(string), - Description: d.Get("description").(string), + createRequest := &metalv1.VirtualNetworkCreateInput{ + Description: metalv1.PtrString(d.Get("description").(string)), } if metroOk { - createRequest.Metro = metroRaw.(string) - createRequest.VXLAN = vxlanRaw.(int) + createRequest.Metro = metalv1.PtrString(metroRaw.(string)) + createRequest.Vxlan = metalv1.PtrInt32(int32(vxlanRaw.(int))) } if facOk { createRequest.Facility = facRaw.(string) } - vlan, _, err := client.ProjectVirtualNetworks.Create(createRequest) + vlan, _, err := client.VLANsApi.CreateVirtualNetwork(ctx, d.Get("project_id").(string)).VirtualNetworkCreateInput(createRequest).Execute() if err != nil { - return equinix_errors.FriendlyError(err) + return diag.FromErr(equinix_errors.FriendlyError(err)) } - d.SetId(vlan.ID) - return resourceMetalVlanRead(d, meta) + d.SetId(vlan.GetId()) + return resourceMetalVlanRead(ctx, d, meta) } -func resourceMetalVlanRead(d *schema.ResourceData, meta interface{}) error { - meta.(*config.Config).AddModuleToMetalUserAgent(d) - client := meta.(*config.Config).Metal +func resourceMetalVlanRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + meta.(*config.Config).AddModuleToMetalGoUserAgent(d) + client := meta.(*config.Config).Metalgo - vlan, _, err := client.ProjectVirtualNetworks.Get(d.Id(), - &packngo.GetOptions{Includes: []string{"assigned_to"}}) + vlan, _, err := client.VLANsApi.GetVirtualNetwork(ctx, d.Id()). + Include([]string{"assigned_to"}).Execute() if err != nil { err = equinix_errors.FriendlyError(err) if equinix_errors.IsNotFound(err) { d.SetId("") return nil } - return err + return diag.FromErr(err) } d.Set("description", vlan.Description) - d.Set("project_id", vlan.Project.ID) - d.Set("vxlan", vlan.VXLAN) - d.Set("facility", vlan.FacilityCode) + d.Set("project_id", vlan.AssignedTo.GetId()) // assigned_to is a project but specced as an href + d.Set("vxlan", vlan.GetVxlan()) + d.Set("facility", vlan.FacilityCode) // vlan spec does not include facility_code; should we remove it? d.Set("metro", vlan.MetroCode) return nil } -func resourceMetalVlanDelete(d *schema.ResourceData, meta interface{}) error { - meta.(*config.Config).AddModuleToMetalUserAgent(d) - client := meta.(*config.Config).Metal +func resourceMetalVlanDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + meta.(*config.Config).AddModuleToMetalGoUserAgent(d) + client := meta.(*config.Config).Metalgo id := d.Id() - vlan, resp, err := client.ProjectVirtualNetworks.Get(id, &packngo.GetOptions{Includes: []string{"instances", "instances.network_ports.virtual_networks", "internet_gateway"}}) - if equinix_errors.IgnoreResponseErrors(equinix_errors.HttpForbidden, equinix_errors.HttpNotFound)(resp, err) != nil { - return equinix_errors.FriendlyError(err) + vlan, resp, err := client.VLANsApi.GetVirtualNetwork(ctx, id).Include([]string{"instances", "instances.network_ports.virtual_networks", "internet_gateway"}).Execute() + if equinix_errors.IgnoreHttpResponseErrors(equinix_errors.HttpForbidden, equinix_errors.HttpNotFound)(resp, err) != nil { + return diag.FromErr(equinix_errors.FriendlyError(err)) } else if err != nil { // missing vlans are deleted return nil @@ -153,17 +153,20 @@ func resourceMetalVlanDelete(d *schema.ResourceData, meta interface{}) error { // all device ports must be unassigned before delete for _, i := range vlan.Instances { - for _, p := range i.NetworkPorts { + for _, p := range i.NetworkPorts { // instances is specced as a list of href; should be devices? for _, a := range p.AttachedVirtualNetworks { // a.ID is not set despite including instaces.network_ports.virtual_networks // TODO(displague) packngo should offer GetID() that uses ID or Href aID := path.Base(a.Href) if aID == id { - _, resp, err := client.Ports.Unassign(p.ID, id) + portInput := metalv1.PortAssignInput{ + Vnid: &id, + } + _, resp, err := client.PortsApi.UnassignPort(ctx, p.GetId()).PortAssignInput(portInput).Execute() - if equinix_errors.IgnoreResponseErrors(equinix_errors.HttpForbidden, equinix_errors.HttpNotFound)(resp, err) != nil { - return equinix_errors.FriendlyError(err) + if equinix_errors.IgnoreHttpResponseErrors(equinix_errors.HttpForbidden, equinix_errors.HttpNotFound)(resp, err) != nil { + return diag.FromErr(equinix_errors.FriendlyError(err)) } } } @@ -171,6 +174,11 @@ func resourceMetalVlanDelete(d *schema.ResourceData, meta interface{}) error { } // TODO(displague) do we need to unassign gateway connections before delete? + _, _, err = client.VLANsApi.DeleteVirtualNetwork(ctx, id).Execute() + + if equinix_errors.IgnoreResponseErrors(equinix_errors.HttpForbidden, equinix_errors.HttpNotFound)(err) != nil { + return diag.FromErr(equinix_errors.FriendlyError(err)) + } - return equinix_errors.FriendlyError(equinix_errors.IgnoreResponseErrors(equinix_errors.HttpForbidden, equinix_errors.HttpNotFound)(client.ProjectVirtualNetworks.Delete(id))) + return nil } diff --git a/internal/resources/metal/vlan/resource_test.go b/internal/resources/metal/vlan/resource_test.go index 06e1510d0..9f35c9ef2 100644 --- a/internal/resources/metal/vlan/resource_test.go +++ b/internal/resources/metal/vlan/resource_test.go @@ -1,6 +1,7 @@ package vlan_test import ( + "context" "fmt" "log" "testing" @@ -8,10 +9,10 @@ import ( "github.com/equinix/terraform-provider-equinix/internal/acceptance" "github.com/equinix/terraform-provider-equinix/internal/config" + "github.com/equinix/equinix-sdk-go/services/metalv1" "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" - "github.com/packethost/packngo" ) func init() { @@ -102,7 +103,7 @@ func TestAccMetalVlan_metro(t *testing.T) { } func TestAccMetalVlan_basic(t *testing.T) { - var vlan packngo.VirtualNetwork + var vlan metalv1.VirtualNetwork rs := acctest.RandString(10) fac := "ny5" @@ -126,7 +127,7 @@ func TestAccMetalVlan_basic(t *testing.T) { }) } -func testAccCheckMetalVlanExists(n string, vlan *packngo.VirtualNetwork) resource.TestCheckFunc { +func testAccCheckMetalVlanExists(n string, vlan *metalv1.VirtualNetwork) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] if !ok { @@ -136,13 +137,13 @@ func testAccCheckMetalVlanExists(n string, vlan *packngo.VirtualNetwork) resourc return fmt.Errorf("No Record ID is set") } - client := acceptance.TestAccProvider.Meta().(*config.Config).Metal + client := acceptance.TestAccProvider.Meta().(*config.Config).Metalgo - foundVlan, _, err := client.ProjectVirtualNetworks.Get(rs.Primary.ID, nil) + foundVlan, _, err := client.VLANsApi.GetVirtualNetwork(context.Background(), rs.Primary.ID).Execute() if err != nil { return err } - if foundVlan.ID != rs.Primary.ID { + if foundVlan.GetId() != rs.Primary.ID { return fmt.Errorf("Record not found: %v - %v", rs.Primary.ID, foundVlan) }