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: stub for framework provider, mux, frameworking resource and datasource for metal_ssh_key #406

Merged
merged 16 commits into from
Feb 2, 2024
Merged
2 changes: 1 addition & 1 deletion docs/resources/equinix_metal_port.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ subcategory: "Metal"

# equinix_metal_port (Resource)

Use this resource to configure network ports on an Equnix Metal device. This resource can control both
Use this resource to configure network ports on an Equinix Metal device. This resource can control both
physical and bond ports.

This Terraform resource doesn't create an API resource in Equinix Metal, but rather provides finer
Expand Down
19 changes: 8 additions & 11 deletions equinix/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import (
"time"

"github.com/equinix/terraform-provider-equinix/internal/resources/metal/metal_connection"
"github.com/equinix/terraform-provider-equinix/internal/resources/metal/metal_project_ssh_key"
"github.com/equinix/terraform-provider-equinix/internal/resources/metal/metal_ssh_key"

"github.com/equinix/ecx-go/v2"
"github.com/equinix/terraform-provider-equinix/internal/config"
Expand Down Expand Up @@ -66,14 +64,16 @@ func Provider() *schema.Provider {
Description: "The maximum number of records in a single response for REST queries that produce paginated responses",
},
"max_retries": {
Type: schema.TypeInt,
Optional: true,
Default: 10,
Type: schema.TypeInt,
Optional: true,
Default: 10,
Description: "Maximum number of retries.",
},
"max_retry_wait_seconds": {
Type: schema.TypeInt,
Optional: true,
Default: 30,
Type: schema.TypeInt,
Optional: true,
Default: 30,
Description: "Maximum number of seconds to wait before retrying a request.",
},
},
DataSourcesMap: map[string]*schema.Resource{
Expand Down Expand Up @@ -108,7 +108,6 @@ func Provider() *schema.Provider {
"equinix_metal_plans": dataSourceMetalPlans(),
"equinix_metal_port": dataSourceMetalPort(),
"equinix_metal_project": dataSourceMetalProject(),
"equinix_metal_project_ssh_key": metal_project_ssh_key.DataSource(),
"equinix_metal_reserved_ip_block": dataSourceMetalReservedIPBlock(),
"equinix_metal_spot_market_request": dataSourceMetalSpotMarketRequest(),
"equinix_metal_virtual_circuit": dataSourceMetalVirtualCircuit(),
Expand All @@ -135,10 +134,8 @@ func Provider() *schema.Provider {
"equinix_metal_connection": metal_connection.Resource(),
"equinix_metal_device": resourceMetalDevice(),
"equinix_metal_device_network_type": resourceMetalDeviceNetworkType(),
"equinix_metal_ssh_key": metal_ssh_key.Resource(),
"equinix_metal_organization_member": resourceMetalOrganizationMember(),
"equinix_metal_port": resourceMetalPort(),
"equinix_metal_project_ssh_key": metal_project_ssh_key.Resource(),
"equinix_metal_project": resourceMetalProject(),
"equinix_metal_organization": resourceMetalOrganization(),
"equinix_metal_reserved_ip_block": resourceMetalReservedIPBlock(),
Expand Down
31 changes: 30 additions & 1 deletion equinix/provider_test.go
Original file line number Diff line number Diff line change
@@ -1,24 +1,50 @@
package equinix

import (
"context"
"fmt"
"os"
"regexp"
"strings"
"testing"

"github.com/equinix/ecx-go/v2"
"github.com/equinix/terraform-provider-equinix/internal/config"
"github.com/equinix/terraform-provider-equinix/internal/provider"
"github.com/equinix/terraform-provider-equinix/version"

"github.com/equinix/ecx-go/v2"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/stretchr/testify/assert"

"github.com/hashicorp/terraform-plugin-framework/providerserver"
"github.com/hashicorp/terraform-plugin-go/tfprotov5"
"github.com/hashicorp/terraform-plugin-mux/tf5muxserver"
)

var (
testAccProviders map[string]*schema.Provider
testAccProviderFactories map[string]func() (*schema.Provider, error)
testAccProvider *schema.Provider
testExternalProviders map[string]resource.ExternalProvider
testAccFrameworkProvider *provider.FrameworkProvider

testAccProtoV5ProviderFactories = map[string]func() (tfprotov5.ProviderServer, error){
"equinix": func() (tfprotov5.ProviderServer, error) {
ctx := context.Background()
providers := []func() tfprotov5.ProviderServer{
testAccProviders["equinix"].GRPCProvider,
providerserver.NewProtocol5(
testAccFrameworkProvider,
),
}
muxServer, err := tf5muxserver.NewMuxServer(ctx, providers...)
if err != nil {
return nil, err
}
return muxServer.ProviderServer(), nil
},
}
)

type mockECXClient struct {
Expand Down Expand Up @@ -113,6 +139,9 @@ func init() {
Source: "hashicorp/random",
},
}
// during framework migration, it is required to duplicate this (TestAccFrameworkProvider declared in internal package)
// for e2e tests that need already migrated resources. Importing from internal produces and import cycle error
testAccFrameworkProvider = provider.CreateFrameworkProvider(version.ProviderVersion).(*provider.FrameworkProvider)
}

func TestProvider(t *testing.T) {
Expand Down
8 changes: 4 additions & 4 deletions equinix/resource_metal_device_acc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,10 +223,10 @@ func TestAccMetalDevice_sshConfig(t *testing.T) {
t.Fatalf("Cannot generate test SSH key pair: %s", err)
}
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ExternalProviders: testExternalProviders,
Providers: testAccProviders,
CheckDestroy: testAccMetalDeviceCheckDestroyed,
PreCheck: func() { testAccPreCheck(t) },
ProtoV5ProviderFactories: testAccProtoV5ProviderFactories,
ExternalProviders: testExternalProviders,
CheckDestroy: testAccMetalDeviceCheckDestroyed,
Steps: []resource.TestStep{
{
Config: testAccMetalDeviceConfig_ssh_key(rs, userSSHKey, projSSHKey),
Expand Down
5 changes: 4 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ require (
github.com/hashicorp/go-multierror v1.1.1
github.com/hashicorp/go-retryablehttp v0.7.5
github.com/hashicorp/terraform-plugin-docs v0.16.0
github.com/hashicorp/terraform-plugin-framework v1.5.0
github.com/hashicorp/terraform-plugin-framework-validators v0.12.0
github.com/hashicorp/terraform-plugin-go v0.20.0
github.com/hashicorp/terraform-plugin-mux v0.13.0
github.com/hashicorp/terraform-plugin-sdk/v2 v2.31.0
github.com/hashicorp/terraform-plugin-testing v1.6.0
github.com/packethost/packngo v0.31.0
Expand Down Expand Up @@ -65,7 +69,6 @@ require (
github.com/hashicorp/logutils v1.0.0 // indirect
github.com/hashicorp/terraform-exec v0.19.0 // indirect
github.com/hashicorp/terraform-json v0.18.0 // indirect
github.com/hashicorp/terraform-plugin-go v0.20.0 // indirect
github.com/hashicorp/terraform-plugin-log v0.9.0 // indirect
github.com/hashicorp/terraform-registry-address v0.2.3 // indirect
github.com/hashicorp/terraform-svchost v0.1.1 // indirect
Expand Down
8 changes: 6 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -443,10 +443,16 @@ github.com/hashicorp/terraform-json v0.18.0 h1:pCjgJEqqDESv4y0Tzdqfxr/edOIGkjs8k
github.com/hashicorp/terraform-json v0.18.0/go.mod h1:qdeBs11ovMzo5puhrRibdD6d2Dq6TyE/28JiU4tIQxk=
github.com/hashicorp/terraform-plugin-docs v0.16.0 h1:UmxFr3AScl6Wged84jndJIfFccGyBZn52KtMNsS12dI=
github.com/hashicorp/terraform-plugin-docs v0.16.0/go.mod h1:M3ZrlKBJAbPMtNOPwHicGi1c+hZUh7/g0ifT/z7TVfA=
github.com/hashicorp/terraform-plugin-framework v1.5.0 h1:8kcvqJs/x6QyOFSdeAyEgsenVOUeC/IyKpi2ul4fjTg=
github.com/hashicorp/terraform-plugin-framework v1.5.0/go.mod h1:6waavirukIlFpVpthbGd2PUNYaFedB0RwW3MDzJ/rtc=
github.com/hashicorp/terraform-plugin-framework-validators v0.12.0 h1:HOjBuMbOEzl7snOdOoUfE2Jgeto6JOjLVQ39Ls2nksc=
github.com/hashicorp/terraform-plugin-framework-validators v0.12.0/go.mod h1:jfHGE/gzjxYz6XoUwi/aYiiKrJDeutQNUtGQXkaHklg=
github.com/hashicorp/terraform-plugin-go v0.20.0 h1:oqvoUlL+2EUbKNsJbIt3zqqZ7wi6lzn4ufkn/UA51xQ=
github.com/hashicorp/terraform-plugin-go v0.20.0/go.mod h1:Rr8LBdMlY53a3Z/HpP+ZU3/xCDqtKNCkeI9qOyT10QE=
github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0=
github.com/hashicorp/terraform-plugin-log v0.9.0/go.mod h1:rKL8egZQ/eXSyDqzLUuwUYLVdlYeamldAHSxjUFADow=
github.com/hashicorp/terraform-plugin-mux v0.13.0 h1:79U401/3nd8CWwDGtTHc8F3miSCAS9XGtVarxSTDgwA=
github.com/hashicorp/terraform-plugin-mux v0.13.0/go.mod h1:Ndv0FtwDG2ogzH59y64f2NYimFJ6I0smRgFUKfm6dyQ=
github.com/hashicorp/terraform-plugin-sdk/v2 v2.31.0 h1:Bl3e2ei2j/Z3Hc2HIS15Gal2KMKyLAZ2om1HCEvK6es=
github.com/hashicorp/terraform-plugin-sdk/v2 v2.31.0/go.mod h1:i2C41tszDjiWfziPQDL5R/f3Zp0gahXe5No/MIO9rCE=
github.com/hashicorp/terraform-plugin-testing v1.6.0 h1:Wsnfh+7XSVRfwcr2jZYHsnLOnZl7UeaOBvsx6dl/608=
Expand Down Expand Up @@ -531,8 +537,6 @@ github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/packethost/packngo v0.30.0 h1:JVeTwbXXETsLTDQncUbYwIFpkOp/xevXrffM2HrFECI=
github.com/packethost/packngo v0.30.0/go.mod h1:BT/XcdwLVmeMtGPbovnxCpnI1s9ylSE1cs/7pq007NE=
github.com/packethost/packngo v0.31.0 h1:LLH90ardhULWbagBIc3I3nl2uU75io0a7AwY6hyi0S4=
github.com/packethost/packngo v0.31.0/go.mod h1:Io6VJqzkiqmIEQbpOjeIw9v8q9PfcTEq8TEY/tMQsfw=
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
Expand Down
4 changes: 4 additions & 0 deletions internal/acceptance/acceptance.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import (

"github.com/equinix/terraform-provider-equinix/equinix"
"github.com/equinix/terraform-provider-equinix/internal/config"
"github.com/equinix/terraform-provider-equinix/version"

"github.com/equinix/terraform-provider-equinix/internal/provider"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
)
Expand All @@ -26,6 +28,7 @@ var (
TestAccProviders map[string]*schema.Provider
TestAccProviderFactories map[string]func() (*schema.Provider, error)
TestExternalProviders map[string]resource.ExternalProvider
TestAccFrameworkProvider *provider.FrameworkProvider
)

func init() {
Expand All @@ -43,6 +46,7 @@ func init() {
Source: "hashicorp/random",
},
}
TestAccFrameworkProvider = provider.CreateFrameworkProvider(version.ProviderVersion).(*provider.FrameworkProvider)
}

func TestAccPreCheck(t *testing.T) {
Expand Down
28 changes: 28 additions & 0 deletions internal/acceptance/provider_factories.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package acceptance

import (
"context"

"github.com/hashicorp/terraform-plugin-framework/providerserver"
"github.com/hashicorp/terraform-plugin-go/tfprotov5"
"github.com/hashicorp/terraform-plugin-mux/tf5muxserver"
)

var ProtoV5ProviderFactories = map[string]func() (tfprotov5.ProviderServer, error){
"equinix": func() (tfprotov5.ProviderServer, error) {
ctx := context.Background()
providers := []func() tfprotov5.ProviderServer{
TestAccProviders["equinix"].GRPCProvider,
providerserver.NewProtocol5(
TestAccFrameworkProvider,
),
}

muxServer, err := tf5muxserver.NewMuxServer(ctx, providers...)
if err != nil {
return nil, err
}

return muxServer.ProviderServer(), nil
},
}
22 changes: 22 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/equinix/oauth2-go"
"github.com/equinix/terraform-provider-equinix/version"
"github.com/hashicorp/go-retryablehttp"
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/logging"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/meta"
Expand Down Expand Up @@ -315,6 +316,27 @@ func (c *Config) AddModuleToNEUserAgent(client *ne.Client, d *schema.ResourceDat
// the UserAgent resulting in swapped UserAgent.
// This can be fixed by letting the headers be overwritten on the initialized Packngo ServiceOp
// clients on a query-by-query basis.
func (c *Config) AddFwModuleToMetalUserAgent(ctx context.Context, meta tfsdk.Config) {
c.Metal.UserAgent = generateFwModuleUserAgentString(ctx, meta, c.metalUserAgent)
}

func (c *Config) AddFwModuleToMetaGolUserAgent(ctx context.Context, meta tfsdk.Config) {
c.Metalgo.GetConfig().UserAgent = generateFwModuleUserAgentString(ctx, meta, c.metalGoUserAgent)
}

func generateFwModuleUserAgentString(ctx context.Context, meta tfsdk.Config, baseUserAgent string) string {
var m ProviderMeta
diags := meta.Get(ctx, &m)
if diags.HasError() {
log.Printf("[WARN] error retrieving provider_meta")
return baseUserAgent
}
if m.ModuleName != "" {
return strings.Join([]string{m.ModuleName, baseUserAgent}, " ")
}
return baseUserAgent
}

func (c *Config) AddModuleToMetalUserAgent(d *schema.ResourceData) {
c.Metal.UserAgent = generateModuleUserAgentString(d, c.metalUserAgent)
}
Expand Down
25 changes: 25 additions & 0 deletions internal/framework/attributes_base.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package framework

import (
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
)

func IDAttributeDefaultDescription() schema.StringAttribute {
return IDAttribute("The unique identifier of the resource")
}

func IDAttribute(description string) schema.StringAttribute {
att := schema.StringAttribute{
Computed: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
},
Description: "The unique identifier of the resource",
}
if description != "" {
att.Description = description
}
return att
}
94 changes: 94 additions & 0 deletions internal/framework/datasource_base.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package framework

import (
"context"
"fmt"

"github.com/equinix/terraform-provider-equinix/internal/config"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
)

func GetDataSourceMeta(
req datasource.ConfigureRequest,
resp *datasource.ConfigureResponse,
) *config.Config {
meta, ok := req.ProviderData.(*config.Config)

if !ok {
resp.Diagnostics.AddError(
"Unexpected DataSource Configure Type",
fmt.Sprintf(
"Expected *http.Client, got: %T. Please report this issue to the provider developers.",
req.ProviderData,
),
)
return nil
}

return meta
}

// NewBaseDataSource returns a new instance of the BaseDataSource
// struct for cleaner initialization.
func NewBaseDataSource(cfg BaseDataSourceConfig) BaseDataSource {
return BaseDataSource{
Config: cfg,
}
}

// BaseDataSourceConfig contains all configurable base resource fields.
type BaseDataSourceConfig struct {
Name string

// Optional
Schema *schema.Schema
}

// BaseDataSource contains various re-usable fields and methods
// intended for use in data source implementations by composition.
type BaseDataSource struct {
Config BaseDataSourceConfig
Meta *config.Config
}

func (r *BaseDataSource) Configure(
ctx context.Context,
req datasource.ConfigureRequest,
resp *datasource.ConfigureResponse,
) {
// Prevent panic if the provider has not been configured.
if req.ProviderData == nil {
return
}

r.Meta = GetDataSourceMeta(req, resp)
if resp.Diagnostics.HasError() {
return
}
}

func (r *BaseDataSource) Metadata(
ctx context.Context,
req datasource.MetadataRequest,
resp *datasource.MetadataResponse,
) {
resp.TypeName = r.Config.Name
}

func (r *BaseDataSource) Schema(
ctx context.Context,
req datasource.SchemaRequest,
resp *datasource.SchemaResponse,
) {
if r.Config.Schema == nil {
resp.Diagnostics.AddError(
"Missing Schema",
"Base data source was not provided a schema. "+
"Please provide a Schema config attribute or implement, the Schema(...) function.",
)
return
}

resp.Schema = *r.Config.Schema
}
Loading
Loading