Skip to content

Commit

Permalink
Initial framework scaffolding
Browse files Browse the repository at this point in the history
  • Loading branch information
acwest committed Oct 28, 2024
1 parent 152ca2d commit 2a46719
Show file tree
Hide file tree
Showing 6 changed files with 296 additions and 18 deletions.
15 changes: 10 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
module github.com/auth0/terraform-provider-auth0

go 1.22
go 1.22.0

toolchain go1.22.5

require (
github.com/PuerkitoBio/rehttp v1.4.0
Expand All @@ -9,6 +11,10 @@ require (
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320
github.com/hashicorp/go-multierror v1.1.1
github.com/hashicorp/terraform-plugin-docs v0.19.4
github.com/hashicorp/terraform-plugin-framework v1.12.0
github.com/hashicorp/terraform-plugin-framework-validators v0.13.0
github.com/hashicorp/terraform-plugin-go v0.24.0
github.com/hashicorp/terraform-plugin-mux v0.16.0
github.com/hashicorp/terraform-plugin-sdk/v2 v2.34.0
github.com/hashicorp/terraform-plugin-testing v1.10.0
github.com/stretchr/testify v1.9.0
Expand Down Expand Up @@ -46,7 +52,6 @@ require (
github.com/hashicorp/logutils v1.0.0 // indirect
github.com/hashicorp/terraform-exec v0.21.0 // indirect
github.com/hashicorp/terraform-json v0.22.1 // indirect
github.com/hashicorp/terraform-plugin-go v0.23.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 Expand Up @@ -84,9 +89,9 @@ require (
golang.org/x/text v0.17.0 // indirect
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240521202816-d264139d666e // indirect
google.golang.org/grpc v1.64.1 // indirect
google.golang.org/protobuf v1.34.1 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 // indirect
google.golang.org/grpc v1.66.2 // indirect
google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
22 changes: 14 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,16 @@ github.com/hashicorp/terraform-json v0.22.1 h1:xft84GZR0QzjPVWs4lRUwvTcPnegqlyS7
github.com/hashicorp/terraform-json v0.22.1/go.mod h1:JbWSQCLFSXFFhg42T7l9iJwdGXBYV8fmmD6o/ML4p3A=
github.com/hashicorp/terraform-plugin-docs v0.19.4 h1:G3Bgo7J22OMtegIgn8Cd/CaSeyEljqjH3G39w28JK4c=
github.com/hashicorp/terraform-plugin-docs v0.19.4/go.mod h1:4pLASsatTmRynVzsjEhbXZ6s7xBlUw/2Kt0zfrq8HxA=
github.com/hashicorp/terraform-plugin-go v0.23.0 h1:AALVuU1gD1kPb48aPQUjug9Ir/125t+AAurhqphJ2Co=
github.com/hashicorp/terraform-plugin-go v0.23.0/go.mod h1:1E3Cr9h2vMlahWMbsSEcNrOCxovCZhOOIXjFHbjc/lQ=
github.com/hashicorp/terraform-plugin-framework v1.12.0 h1:7HKaueHPaikX5/7cbC1r9d1m12iYHY+FlNZEGxQ42CQ=
github.com/hashicorp/terraform-plugin-framework v1.12.0/go.mod h1:N/IOQ2uYjW60Jp39Cp3mw7I/OpC/GfZ0385R0YibmkE=
github.com/hashicorp/terraform-plugin-framework-validators v0.13.0 h1:bxZfGo9DIUoLLtHMElsu+zwqI4IsMZQBRRy4iLzZJ8E=
github.com/hashicorp/terraform-plugin-framework-validators v0.13.0/go.mod h1:wGeI02gEhj9nPANU62F2jCaHjXulejm/X+af4PdZaNo=
github.com/hashicorp/terraform-plugin-go v0.24.0 h1:2WpHhginCdVhFIrWHxDEg6RBn3YaWzR2o6qUeIEat2U=
github.com/hashicorp/terraform-plugin-go v0.24.0/go.mod h1:tUQ53lAsOyYSckFGEefGC5C8BAaO0ENqzFd3bQeuYQg=
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.16.0 h1:RCzXHGDYwUwwqfYYWJKBFaS3fQsWn/ZECEiW7p2023I=
github.com/hashicorp/terraform-plugin-mux v0.16.0/go.mod h1:PF79mAsPc8CpusXPfEVa4X8PtkB+ngWoiUClMrNZlYo=
github.com/hashicorp/terraform-plugin-sdk/v2 v2.34.0 h1:kJiWGx2kiQVo97Y5IOGR4EMcZ8DtMswHhUuFibsCQQE=
github.com/hashicorp/terraform-plugin-sdk/v2 v2.34.0/go.mod h1:sl/UoabMc37HA6ICVMmGO+/0wofkVIRxf+BMb/dnoIg=
github.com/hashicorp/terraform-plugin-testing v1.10.0 h1:2+tmRNhvnfE4Bs8rB6v58S/VpqzGC6RCh9Y8ujdn+aw=
Expand Down Expand Up @@ -283,14 +289,14 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240521202816-d264139d666e h1:Elxv5MwEkCI9f5SkoL6afed6NTdxaGoAo39eANBwHL8=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240521202816-d264139d666e/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA=
google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 h1:1GBuWVLM/KMVUv1t1En5Gs+gFZCNd360GGb4sSxtrhU=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo=
google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand Down
40 changes: 40 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ import (
"github.com/PuerkitoBio/rehttp"
"github.com/auth0/go-auth0"
"github.com/auth0/go-auth0/management"
frameworkDiag "github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/meta"

internalError "github.com/auth0/terraform-provider-auth0/internal/error"
"github.com/auth0/terraform-provider-auth0/internal/mutex"
)

Expand Down Expand Up @@ -78,6 +80,28 @@ func ConfigureProvider(terraformVersion *string) schema.ConfigureContextFunc {
}
}

// ConfigureFrameworkProvider will configure the provider.Provider so that
// *management.Management client and *mutex.KeyValue is stored
// and passed into the subsequent resources Configure method as the ConfigureRequest.ProviderData.
func ConfigureFrameworkProvider(
terraformVersion, domain, clientID, clientSecret, apiToken, audience string,
debug bool,
) (interface{}, frameworkDiag.Diagnostics) {
apiClient, err := management.New(domain,
authenticationOption(clientID, clientSecret, apiToken, audience),
management.WithDebug(debug),
management.WithUserAgent(userAgentFramework(terraformVersion)),
management.WithAuth0ClientEnvEntry(providerName, version),
management.WithNoRetries(),
management.WithClient(customClientWithRetries()),
)
if err != nil {
return nil, internalError.DiagnosticsFromError(err)
}

return New(apiClient), nil
}

// userAgent computes the desired User-Agent header for the *management.Management client.
func userAgent(terraformVersion *string) string {
sdkVersion := auth0.Version
Expand All @@ -95,6 +119,22 @@ func userAgent(terraformVersion *string) string {
return userAgent
}

// userAgentFramework computes the desired User-Agent header for the
// *management.Management client using the Terraform Framework.
func userAgentFramework(terraformVersion string) string {
sdkVersion := auth0.Version

userAgent := fmt.Sprintf(
"%s/%s (Go-Auth0-SDK/%s; Terraform/%s)",
providerName,
version,
sdkVersion,
terraformVersion,
)

return userAgent
}

// authenticationOption computes the desired authentication option for the *management.Management client.
func authenticationOption(clientID, clientSecret, apiToken, audience string) management.Option {
ctx := context.Background()
Expand Down
25 changes: 25 additions & 0 deletions internal/error/diag_error.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package error

import (
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/terraform-plugin-framework/diag"
)

func DiagnosticsFromError(err error) diag.Diagnostics {
result := diag.Diagnostics{}
if err == nil {
return result
}
if mErr, ok := err.(*multierror.Error); ok {
if len(mErr.Errors) == 0 {
return result
}
for _, err := range mErr.Errors {
result.AddError("Error", err.Error())
}
} else {
result.AddError("Error", err.Error())
}

return result
}
170 changes: 170 additions & 0 deletions internal/provider/framework_provider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
package provider

import (
"context"
"os"

"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/provider"
"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/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"

"github.com/auth0/terraform-provider-auth0/internal/config"
)

type auth0Provider struct {
}

type auth0ProviderModel struct {
Domain types.String `tfsdk:"domain"`
Audience types.String `tfsdk:"audience"`
ClientID types.String `tfsdk:"client_id"`
ClientSecret types.String `tfsdk:"client_secret"`
ApiToken types.String `tfsdk:"api_token"`
Debug types.Bool `tfsdk:"debug"`
}

func (p *auth0Provider) Metadata(_ context.Context, _ provider.MetadataRequest, _ *provider.MetadataResponse) {
}

func (p *auth0Provider) Schema(_ context.Context, _ provider.SchemaRequest, response *provider.SchemaResponse) {
if response != nil {
response.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
"domain": schema.StringAttribute{
Optional: true,
Description: "Your Auth0 domain name. " +
"It can also be sourced from the AUTH0_DOMAIN environment variable.",
MarkdownDescription: "Your Auth0 domain name. " +
"It can also be sourced from the `AUTH0_DOMAIN` environment variable.",
},
"audience": schema.StringAttribute{
Optional: true,
Description: "Your Auth0 audience when using a custom domain. " +
"It can also be sourced from the AUTH0_AUDIENCE environment variable.",
MarkdownDescription: "Your Auth0 audience when using a custom domain. " +
"It can also be sourced from the `AUTH0_AUDIENCE` environment variable.",
},
"client_id": schema.StringAttribute{
Optional: true,
Validators: []validator.String{
stringvalidator.ConflictsWith(path.Expressions{
path.MatchRoot("api_token"),
}...),
stringvalidator.AlsoRequires(path.Expressions{
path.MatchRoot("client_secret"),
}...),
},
Description: "Your Auth0 client ID. " +
"It can also be sourced from the AUTH0_CLIENT_ID environment variable.",
MarkdownDescription: "Your Auth0 client ID. " +
"It can also be sourced from the `AUTH0_CLIENT_ID` environment variable.",
},
"client_secret": schema.StringAttribute{
Optional: true,
Validators: []validator.String{
stringvalidator.ConflictsWith(path.Expressions{
path.MatchRoot("api_token"),
}...),
stringvalidator.AlsoRequires(path.Expressions{
path.MatchRoot("client_id"),
}...),
},
Description: "Your Auth0 client secret. " +
"It can also be sourced from the AUTH0_CLIENT_SECRET environment variable.",
MarkdownDescription: "Your Auth0 client secret. " +
"It can also be sourced from the `AUTH0_CLIENT_SECRET` environment variable.",
},
"api_token": schema.StringAttribute{
Optional: true,
Validators: []validator.String{
stringvalidator.ConflictsWith(path.Expressions{
path.MatchRoot("client_id"),
}...),
stringvalidator.ConflictsWith(path.Expressions{
path.MatchRoot("client_secret"),
}...),
},
Description: "Your Auth0 management api access token. " +
"It can also be sourced from the AUTH0_API_TOKEN environment variable. " +
"It can be used instead of client_id + client_secret. " +
"If both are specified, api_token will be used over client_id + client_secret fields.",
MarkdownDescription: "Your Auth0 [management api access token]" +
"(https://auth0.com/docs/security/tokens/access-tokens/management-api-access-tokens). " +
"It can also be sourced from the `AUTH0_API_TOKEN` environment variable. " +
"It can be used instead of `client_id` + `client_secret`. " +
"If both are specified, `api_token` will be used over `client_id` + `client_secret` fields.",
},
"debug": schema.BoolAttribute{
Optional: true,
Description: "Indicates whether to turn on debug mode.",
MarkdownDescription: "Indicates whether to turn on debug mode.",
},
},
}
}
}

func (p *auth0Provider) Configure(ctx context.Context, request provider.ConfigureRequest, response *provider.ConfigureResponse) {
domain := os.Getenv("AUTH0_DOMAIN")
clientID := os.Getenv("AUTH0_CLIENT_ID")
clientSecret := os.Getenv("AUTH0_CLIENT_SECRET")
apiToken := os.Getenv("AUTH0_API_TOKEN")
audience := os.Getenv("AUTH0_AUDIENCE")
debugStr := os.Getenv("AUTH0_DEBUG")

var debug bool
switch debugStr {
case "1", "true", "on":
debug = true
default:
debug = false
}

var data auth0ProviderModel
response.Diagnostics.Append(request.Config.Get(ctx, &data)...)

if data.Domain.ValueString() != "" {
domain = data.Domain.ValueString()
}
if data.ClientID.ValueString() != "" {
clientID = data.ClientID.ValueString()
}
if data.ClientSecret.ValueString() != "" {
clientSecret = data.ClientSecret.ValueString()
}
if data.ApiToken.ValueString() != "" {
apiToken = data.ApiToken.ValueString()
}
if data.Audience.ValueString() != "" {
audience = data.Audience.ValueString()
}
if !data.Debug.IsNull() && !data.Debug.IsUnknown() {
debug = data.Debug.ValueBool()
}

config, diag := config.ConfigureFrameworkProvider(request.TerraformVersion, domain, clientID, clientSecret, apiToken, audience, debug)
if config != nil {
response.ResourceData = config
response.DataSourceData = config
}

response.Diagnostics.Append(diag...)
}

func (p *auth0Provider) DataSources(_ context.Context) []func() datasource.DataSource {
return []func() datasource.DataSource{}
}

func (p *auth0Provider) Resources(_ context.Context) []func() resource.Resource {
return []func() resource.Resource{}
}

// NewAuth0Provider returns a terraform Framework provider.Provider.
func NewAuth0Provider() provider.Provider {
return &auth0Provider{}
}
Loading

0 comments on commit 2a46719

Please sign in to comment.