Skip to content

Commit

Permalink
Plugin sdk to Framework migration for Vlan
Browse files Browse the repository at this point in the history
Signed-off-by: Ayush Rangwala <[email protected]>
  • Loading branch information
aayushrangwala committed Mar 14, 2024
1 parent 4fa2624 commit 0efac48
Show file tree
Hide file tree
Showing 11 changed files with 576 additions and 387 deletions.
3 changes: 0 additions & 3 deletions equinix/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (

"github.com/equinix/terraform-provider-equinix/internal/config"
metal_project "github.com/equinix/terraform-provider-equinix/internal/resources/metal/project"
"github.com/equinix/terraform-provider-equinix/internal/resources/metal/vlans"
"github.com/equinix/terraform-provider-equinix/internal/resources/metal/vrf"

"github.com/equinix/ecx-go/v2"
Expand Down Expand Up @@ -111,7 +110,6 @@ func Provider() *schema.Provider {
"equinix_metal_reserved_ip_block": dataSourceMetalReservedIPBlock(),
"equinix_metal_spot_market_request": dataSourceMetalSpotMarketRequest(),
"equinix_metal_virtual_circuit": dataSourceMetalVirtualCircuit(),
"equinix_metal_vlan": vlans.DataSource(),
"equinix_metal_vrf": vrf.DataSource(),
},
ResourcesMap: map[string]*schema.Resource{
Expand Down Expand Up @@ -140,7 +138,6 @@ func Provider() *schema.Provider {
"equinix_metal_reserved_ip_block": resourceMetalReservedIPBlock(),
"equinix_metal_ip_attachment": resourceMetalIPAttachment(),
"equinix_metal_spot_market_request": resourceMetalSpotMarketRequest(),
"equinix_metal_vlan": vlans.Resource(),
"equinix_metal_virtual_circuit": resourceMetalVirtualCircuit(),
"equinix_metal_vrf": vrf.Resource(),
"equinix_metal_bgp_session": resourceMetalBGPSession(),
Expand Down
18 changes: 11 additions & 7 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,22 @@ import (
"context"
"fmt"

"github.com/equinix/terraform-provider-equinix/internal/config"
metalconnection "github.com/equinix/terraform-provider-equinix/internal/resources/metal/connection"
metalgateway "github.com/equinix/terraform-provider-equinix/internal/resources/metal/gateway"
metalorganization "github.com/equinix/terraform-provider-equinix/internal/resources/metal/organization"
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"
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"
"github.com/hashicorp/terraform-plugin-framework/provider"
"github.com/hashicorp/terraform-plugin-framework/provider/metaschema"
"github.com/hashicorp/terraform-plugin-framework/provider/schema"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"

"github.com/equinix/terraform-provider-equinix/internal/config"
metalconnection "github.com/equinix/terraform-provider-equinix/internal/resources/metal/connection"
metalgateway "github.com/equinix/terraform-provider-equinix/internal/resources/metal/gateway"
metalorganization "github.com/equinix/terraform-provider-equinix/internal/resources/metal/organization"
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/vlans"
equinix_validation "github.com/equinix/terraform-provider-equinix/internal/validation"
)

type FrameworkProvider struct {
Expand Down Expand Up @@ -116,6 +118,7 @@ func (p *FrameworkProvider) Resources(ctx context.Context) []func() resource.Res
metalsshkey.NewResource,
metalconnection.NewResource,
metalorganization.NewResource,
vlans.NewResource,
}
}

Expand All @@ -125,5 +128,6 @@ func (p *FrameworkProvider) DataSources(ctx context.Context) []func() datasource
metalprojectsshkey.NewDataSource,
metalconnection.NewDataSource,
metalorganization.NewDataSource,
vlans.NewDataSource,
}
}
153 changes: 64 additions & 89 deletions internal/resources/metal/vlans/datasource.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,116 +4,93 @@ import (
"context"
"fmt"

"github.com/equinix/terraform-provider-equinix/internal/config"
"github.com/equinix/terraform-provider-equinix/internal/converters"
equinix_errors "github.com/equinix/terraform-provider-equinix/internal/errors"
equinix_schema "github.com/equinix/terraform-provider-equinix/internal/schema"
"github.com/equinix/terraform-provider-equinix/internal/framework"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/packethost/packngo"
)

func DataSource() *schema.Resource {
return &schema.Resource{
ReadWithoutTimeout: dataSourceMetalVlanRead,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},
Schema: map[string]*schema.Schema{
"project_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ConflictsWith: []string{"vlan_id"},
Description: "ID of parent project of the VLAN. Use together with vxlan and metro or facility",
func NewDataSource() datasource.DataSource {
return &DataSource{
BaseDataSource: framework.NewBaseDataSource(
framework.BaseDataSourceConfig{
Name: "equinix_metal_vlan",
},
"vxlan": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
ConflictsWith: []string{"vlan_id"},
Description: "VXLAN numner of the VLAN. Unique in a project and facility or metro. Use with project_id",
},
"facility": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ConflictsWith: []string{"vlan_id", "metro"},
Description: "Facility where the VLAN is deployed",
Deprecated: "Use metro instead of facility. For more information, read the migration guide: https://registry.terraform.io/providers/equinix/equinix/latest/docs/guides/migration_guide_facilities_to_metros_devices",
},
"metro": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ConflictsWith: []string{"vlan_id", "facility"},
Description: "Metro where the VLAN is deployed",
StateFunc: converters.ToLowerIf,
},
"vlan_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ConflictsWith: []string{"project_id", "vxlan", "metro", "facility"},
Description: "Metal UUID of the VLAN resource",
},
"description": {
Type: schema.TypeString,
Computed: true,
Description: "VLAN description text",
},
"assigned_devices_ids": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
Description: "List of device IDs to which this VLAN is assigned",
},
},
),
}
}

func dataSourceMetalVlanRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*config.Config).Metal
func (r *DataSource) Schema(
ctx context.Context,
req datasource.SchemaRequest,
resp *datasource.SchemaResponse,
) {
s := dataSourceSchema()
if s.Blocks == nil {
s.Blocks = make(map[string]schema.Block)
}
resp.Schema = s
}

type DataSource struct {
framework.BaseDataSource
framework.WithTimeouts
}

projectRaw, projectOk := d.GetOk("project_id")
vxlanRaw, vxlanOk := d.GetOk("vxlan")
vlanIdRaw, vlanIdOk := d.GetOk("vlan_id")
metroRaw, metroOk := d.GetOk("metro")
facilityRaw, facilityOk := d.GetOk("facility")
func (r *DataSource) Read(
ctx context.Context,
req datasource.ReadRequest,
resp *datasource.ReadResponse,
) {
r.Meta.AddFwModuleToMetalUserAgent(ctx, req.ProviderMeta)
client := r.Meta.Metal

var data DataSourceModel
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}

if !(vlanIdOk || (vxlanOk || projectOk || metroOk || facilityOk)) {
return diag.FromErr(equinix_errors.FriendlyError(fmt.Errorf("You must set either vlan_id or a combination of vxlan, project_id, and, metro or facility")))
if data.VlanID.IsNull() &&
(data.Vxlan.IsNull() && data.ProjectID.IsNull() && data.Metro.IsNull() && data.Facility.IsNull()) {
resp.Diagnostics.AddError("Error fetching Vlan datasource",
equinix_errors.
FriendlyError(fmt.Errorf("You must set either vlan_id or a combination of vxlan, project_id, and, metro or facility")).
Error())
return
}

var vlan *packngo.VirtualNetwork

if vlanIdOk {
if !data.VlanID.IsNull() {
var err error
vlan, _, err = client.ProjectVirtualNetworks.Get(
vlanIdRaw.(string),
data.VlanID.ValueString(),
&packngo.GetOptions{Includes: []string{"assigned_to"}},
)
if err != nil {
return diag.FromErr(equinix_errors.FriendlyError(err))
resp.Diagnostics.AddError("Error fetching Vlan using vlanId", equinix_errors.FriendlyError(err).Error())
return
}

} else {
projectID := projectRaw.(string)
vxlan := vxlanRaw.(int)
metro := metroRaw.(string)
facility := facilityRaw.(string)
vlans, _, err := client.ProjectVirtualNetworks.List(
projectRaw.(string),
data.ProjectID.ValueString(),
&packngo.GetOptions{Includes: []string{"assigned_to"}},
)
if err != nil {
return diag.FromErr(equinix_errors.FriendlyError(err))
resp.Diagnostics.AddError("Error fetching vlans list for projectId",
equinix_errors.FriendlyError(err).Error())
return
}

vlan, err = MatchingVlan(vlans.VirtualNetworks, vxlan, projectID, facility, metro)
vlan, err = MatchingVlan(vlans.VirtualNetworks, int(data.Vxlan.ValueInt64()), data.ProjectID.ValueString(),
data.Facility.ValueString(), data.Metro.ValueString())
if err != nil {
return diag.FromErr(equinix_errors.FriendlyError(err))
resp.Diagnostics.AddError("Error expected vlan not found", equinix_errors.FriendlyError(err).Error())
return
}
}

Expand All @@ -122,16 +99,14 @@ func dataSourceMetalVlanRead(ctx context.Context, d *schema.ResourceData, meta i
assignedDevices = append(assignedDevices, d.ID)
}

d.SetId(vlan.ID)
// Set state to fully populated data
resp.Diagnostics.Append(data.parse(vlan)...)
if resp.Diagnostics.HasError() {
return
}

return diag.FromErr(equinix_schema.SetMap(d, map[string]interface{}{
"vlan_id": vlan.ID,
"project_id": vlan.Project.ID,
"vxlan": vlan.VXLAN,
"facility": vlan.FacilityCode,
"metro": vlan.MetroCode,
"description": vlan.Description,
}))
// Update the Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

func MatchingVlan(vlans []packngo.VirtualNetwork, vxlan int, projectID, facility, metro string) (*packngo.VirtualNetwork, error) {
Expand Down
86 changes: 86 additions & 0 deletions internal/resources/metal/vlans/datasource_schema.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package vlans

import (
"github.com/hashicorp/terraform-plugin-framework-validators/int64validator"
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
)

func dataSourceSchema() schema.Schema {
return schema.Schema{
Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{
Description: "The unique identifier for this Metal Vlan",
Computed: true,
},
"project_id": schema.StringAttribute{
Description: "ID of parent project of the VLAN. Use together with vxlan and metro or facility",
Computed: true,
Optional: true,
Validators: []validator.String{
stringvalidator.ConflictsWith(path.Expressions{
path.MatchRoot("vlan_id"),
}...),
},
},
"vxlan": schema.Int64Attribute{
Optional: true,
Computed: true,
Validators: []validator.Int64{
int64validator.ConflictsWith(path.Expressions{
path.MatchRoot("vlan_id"),
}...),
},
Description: "VXLAN numner of the VLAN. Unique in a project and facility or metro. Use with project_id",
},
"facility": schema.StringAttribute{
Optional: true,
Computed: true,
Validators: []validator.String{
stringvalidator.ConflictsWith(path.Expressions{
path.MatchRoot("vlan_id"),
path.MatchRoot("metro"),
}...),
},
Description: "Facility where the VLAN is deployed",
DeprecationMessage: "Use metro instead of facility. For more information, read the migration guide: https://registry.terraform.io/providers/equinix/equinix/latest/docs/guides/migration_guide_facilities_to_metros_devices",
},
"metro": schema.StringAttribute{
Optional: true,
Computed: true,
Validators: []validator.String{
stringvalidator.ConflictsWith(path.Expressions{
path.MatchRoot("vlan_id"),
path.MatchRoot("facility"),
}...),
},
Description: "Metro where the VLAN is deployed",
},
"vlan_id": schema.StringAttribute{
Optional: true,
Computed: true,
Validators: []validator.String{
stringvalidator.ConflictsWith(path.Expressions{
path.MatchRoot("project_id"),
path.MatchRoot("vxlan"),
path.MatchRoot("metro"),
path.MatchRoot("facility"),
}...),
},
Description: "Metal UUID of the VLAN resource",
},
"description": schema.StringAttribute{
Computed: true,
Description: "VLAN description text",
},
"assigned_devices_ids": schema.ListAttribute{
Computed: true,
ElementType: types.StringType,
Description: "List of device IDs to which this VLAN is assigned",
},
},
}
}
Loading

0 comments on commit 0efac48

Please sign in to comment.