-
Notifications
You must be signed in to change notification settings - Fork 47
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Framework provider stub and mux functionality
- Loading branch information
Showing
10 changed files
with
588 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
package equinix | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/equinix/terraform-provider-equinix/equinix/helper" | ||
"github.com/equinix/terraform-provider-equinix/equinix/metal_ssh_key" | ||
"github.com/hashicorp/terraform-plugin-framework/datasource" | ||
"github.com/hashicorp/terraform-plugin-framework/provider" | ||
"github.com/hashicorp/terraform-plugin-framework/provider/schema" | ||
"github.com/hashicorp/terraform-plugin-framework/resource" | ||
) | ||
|
||
type FrameworkProvider struct { | ||
ProviderVersion string | ||
Meta *helper.FrameworkProviderMeta | ||
} | ||
|
||
func CreateFrameworkProvider(version string) provider.Provider { | ||
return &FrameworkProvider{ | ||
Check failure on line 21 in equinix/framework_provider.go GitHub Actions / Test
Check failure on line 21 in equinix/framework_provider.go GitHub Actions / Build
|
||
ProviderVersion: version, | ||
} | ||
} | ||
|
||
func (p *FrameworkProvider) Metadata( | ||
ctx context.Context, | ||
req provider.MetadataRequest, | ||
resp *provider.MetadataResponse, | ||
) { | ||
resp.TypeName = "equinixcloud" | ||
} | ||
|
||
func (p *FrameworkProvider) Schema( | ||
ctx context.Context, | ||
req provider.SchemaRequest, | ||
resp *provider.SchemaResponse, | ||
) { | ||
resp.Schema = schema.Schema{ | ||
Attributes: map[string]schema.Attribute{ | ||
"endpoint": schema.StringAttribute{ | ||
Optional: true, | ||
Description: "The Equinix API base URL to point out desired environment. Defaults to " + DefaultBaseURL, | ||
}, | ||
"client_id": schema.StringAttribute{ | ||
Optional: true, | ||
Description: "API Consumer Key available under My Apps section in developer portal", | ||
}, | ||
"client_secret": schema.StringAttribute{ | ||
Optional: true, | ||
Description: "API Consumer secret available under My Apps section in developer portal", | ||
}, | ||
"token": schema.StringAttribute{ | ||
Optional: true, | ||
Description: "API token from the developer sandbox", | ||
}, | ||
"auth_token": schema.StringAttribute{ | ||
Optional: true, | ||
Description: "The Equinix Metal API auth key for API operations", | ||
}, | ||
"request_timeout": schema.Int64Attribute{ | ||
Optional: true, | ||
Description: "The duration of time, in seconds, that the Equinix Platform API Client should wait before canceling an API request. Defaults to " + fmt.Sprint(DefaultTimeout), | ||
}, | ||
"response_max_page_size": schema.Int64Attribute{ | ||
Optional: true, | ||
Description: "The maximum number of records in a single response for REST queries that produce paginated responses", | ||
}, | ||
"max_retries": schema.Int64Attribute{ | ||
Optional: true, | ||
Description: "Maximum number of retries.", | ||
}, | ||
"max_retry_wait_seconds": schema.Int64Attribute{ | ||
Optional: true, | ||
Description: "Maximum number of seconds to wait before retrying a request.", | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func (p *FrameworkProvider) Resources(ctx context.Context) []func() resource.Resource { | ||
return []func() resource.Resource{ | ||
metal_ssh_key.NewResource, | ||
} | ||
} | ||
|
||
func (p *FrameworkProvider) DataSources(ctx context.Context) []func() datasource.DataSource { | ||
// return nil | ||
return []func() datasource.DataSource{ | ||
metal_ssh_key.NewDataSource, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package helper | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/hashicorp/terraform-plugin-framework/datasource" | ||
"github.com/hashicorp/terraform-plugin-framework/datasource/schema" | ||
) | ||
|
||
// 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 | ||
IsEarlyAccess bool | ||
} | ||
|
||
// BaseDataSource contains various re-usable fields and methods | ||
// intended for use in data source implementations by composition. | ||
type BaseDataSource struct { | ||
Config BaseDataSourceConfig | ||
Meta *FrameworkProviderMeta | ||
} | ||
|
||
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package helper | ||
|
||
import ( | ||
"github.com/hashicorp/terraform-plugin-framework/types" | ||
"github.com/packethost/packngo" | ||
) | ||
|
||
type FrameworkProviderModel struct { | ||
Endpoint types.String `tfsdk:"endpoint,omitempty"` | ||
ClientID types.String `tfsdk:"client_id,omitempty"` | ||
ClientSecret types.String `tfsdk:"client_secret,omitempty"` | ||
Token types.String `tfsdk:"token,omitempty"` | ||
AuthToken types.String `tfsdk:"auth_token,omitempty"` | ||
RequestTimeout types.Int64 `tfsdk:"request_timeout,omitempty"` | ||
ResponseMaxPageSize types.Int64 `tfsdk:"response_max_page_size,omitempty"` | ||
MaxRetries types.Int64 `tfsdk:"max_retries,omitempty"` | ||
MaxRetryWaitSeconds types.Int64 `tfsdk:"max_retry_wait_seconds,omitempty"` | ||
} | ||
|
||
type FrameworkProviderMeta struct { | ||
Client *packngo.Client | ||
Config *FrameworkProviderModel | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
package helper | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"strconv" | ||
|
||
"github.com/hashicorp/terraform-plugin-framework/attr" | ||
"github.com/hashicorp/terraform-plugin-framework/path" | ||
"github.com/hashicorp/terraform-plugin-framework/resource" | ||
"github.com/hashicorp/terraform-plugin-framework/resource/schema" | ||
"github.com/hashicorp/terraform-plugin-framework/types" | ||
) | ||
|
||
// NewBaseResource returns a new instance of the BaseResource | ||
// struct for cleaner initialization. | ||
func NewBaseResource(cfg BaseResourceConfig) BaseResource { | ||
return BaseResource{ | ||
Config: cfg, | ||
} | ||
} | ||
|
||
// BaseResourceConfig contains all configurable base resource fields. | ||
type BaseResourceConfig struct { | ||
Name string | ||
IDAttr string | ||
IDType attr.Type | ||
|
||
// Optional | ||
Schema *schema.Schema | ||
IsEarlyAccess bool | ||
} | ||
|
||
// BaseResource contains various re-usable fields and methods | ||
// intended for use in resource implementations by composition. | ||
type BaseResource struct { | ||
Config BaseResourceConfig | ||
Meta *FrameworkProviderMeta | ||
} | ||
|
||
func (r *BaseResource) Configure( | ||
ctx context.Context, | ||
req resource.ConfigureRequest, | ||
resp *resource.ConfigureResponse, | ||
) { | ||
// Prevent panic if the provider has not been configured. | ||
if req.ProviderData == nil { | ||
return | ||
} | ||
|
||
r.Meta = GetResourceMeta(req, resp) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
} | ||
|
||
func (r *BaseResource) Metadata( | ||
ctx context.Context, | ||
req resource.MetadataRequest, | ||
resp *resource.MetadataResponse, | ||
) { | ||
resp.TypeName = r.Config.Name | ||
} | ||
|
||
func (r *BaseResource) Schema( | ||
ctx context.Context, | ||
req resource.SchemaRequest, | ||
resp *resource.SchemaResponse, | ||
) { | ||
if r.Config.Schema == nil { | ||
resp.Diagnostics.AddError( | ||
"Missing Schema", | ||
"Base resource was not provided a schema. "+ | ||
"Please provide a Schema config attribute or implement, the Schema(...) function.", | ||
) | ||
return | ||
} | ||
|
||
resp.Schema = *r.Config.Schema | ||
} | ||
|
||
// ImportState should be overridden for resources with | ||
// complex read logic (e.g. parent ID). | ||
func (r *BaseResource) ImportState( | ||
ctx context.Context, | ||
req resource.ImportStateRequest, | ||
resp *resource.ImportStateResponse, | ||
) { | ||
// Enforce defaults | ||
idAttr := r.Config.IDAttr | ||
if idAttr == "" { | ||
idAttr = "id" | ||
} | ||
|
||
idType := r.Config.IDType | ||
if idType == nil { | ||
idType = types.Int64Type | ||
} | ||
|
||
attrPath := path.Root(idAttr) | ||
|
||
if attrPath.Equal(path.Empty()) { | ||
resp.Diagnostics.AddError( | ||
"Resource Import Passthrough Missing Attribute Path", | ||
"This is always an error in the provider. Please report the following to the provider developer:\n\n"+ | ||
"Resource ImportState path must be set to a valid attribute path.", | ||
) | ||
return | ||
} | ||
|
||
// Handle type conversion | ||
var err error | ||
var idValue any | ||
|
||
switch idType { | ||
case types.Int64Type: | ||
idValue, err = strconv.ParseInt(req.ID, 10, 64) | ||
case types.StringType: | ||
idValue = req.ID | ||
default: | ||
err = fmt.Errorf("unsupported id attribute type: %v", idType) | ||
} | ||
if err != nil { | ||
resp.Diagnostics.AddError( | ||
"Failed to convert ID attribute", | ||
err.Error(), | ||
) | ||
return | ||
} | ||
|
||
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, attrPath, idValue)...) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package helper | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/hashicorp/terraform-plugin-framework/datasource" | ||
"github.com/hashicorp/terraform-plugin-framework/resource" | ||
) | ||
|
||
func GetResourceMeta( | ||
req resource.ConfigureRequest, | ||
resp *resource.ConfigureResponse, | ||
) *FrameworkProviderMeta { | ||
meta, ok := req.ProviderData.(*FrameworkProviderMeta) | ||
|
||
if !ok { | ||
resp.Diagnostics.AddError( | ||
"Unexpected Resource Configure Type", | ||
fmt.Sprintf( | ||
"Expected *http.Client, got: %T. Please report this issue to the provider developers.", | ||
req.ProviderData, | ||
), | ||
) | ||
return nil | ||
} | ||
|
||
return meta | ||
} | ||
|
||
func GetDataSourceMeta( | ||
req datasource.ConfigureRequest, | ||
resp *datasource.ConfigureResponse, | ||
) *FrameworkProviderMeta { | ||
meta, ok := req.ProviderData.(*FrameworkProviderMeta) | ||
|
||
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 | ||
} |
Oops, something went wrong.