From 3d019541e7cbba5e92f9857987c8587ae3e8c221 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20Sch=C3=A4fer?= Date: Tue, 30 Jan 2024 14:13:53 +0100 Subject: [PATCH] SYSENG-1726: initialize terraform-plugin-framework --- Makefile | 2 +- anxcloud/provider.go | 70 ++++++++++++------------- anxcloud/provider_test.go | 12 +++-- go.mod | 4 +- go.sum | 4 ++ internal/provider/provider.go | 89 ++++++++++++++++++++++++++++++++ main.go | 57 ++++++++++++++++---- terraform-registry-manifest.json | 6 +++ 8 files changed, 193 insertions(+), 51 deletions(-) create mode 100644 internal/provider/provider.go create mode 100644 terraform-registry-manifest.json diff --git a/Makefile b/Makefile index e6e96b68..8dace309 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ NAME=anxcloud BINARY=terraform-provider-${NAME} VERSION=0.3.1 OS_ARCH=linux_amd64 -GOLDFLAGS= -s -X github.com/anexia-it/terraform-provider-anxcloud/anxcloud.providerVersion=$(VERSION) +GOLDFLAGS= -s -X github.com/anexia-it/terraform-provider-anxcloud.version=$(VERSION) GOFMT_FILES := $(shell find ./anxcloud -name '*.go' |grep -v vendor) diff --git a/anxcloud/provider.go b/anxcloud/provider.go index 7df1ce41..84488157 100644 --- a/anxcloud/provider.go +++ b/anxcloud/provider.go @@ -15,12 +15,10 @@ import ( "go.anx.io/go-anxcloud/pkg/client" ) -var providerVersion = "development" - var logger logr.Logger // Provider Anexia -func Provider() *schema.Provider { +func Provider(version string) *schema.Provider { return &schema.Provider{ Schema: map[string]*schema.Schema{ "token": { @@ -59,7 +57,7 @@ func Provider() *schema.Provider { "anxcloud_dns_zones": datasourceDNSZones(), "anxcloud_kubernetes_cluster": dataSourceKubernetesCluster(), }, - ConfigureContextFunc: providerConfigure, + ConfigureContextFunc: providerConfigure(version), } } @@ -68,42 +66,44 @@ type providerContext struct { legacyClient client.Client } -func providerConfigure(ctx context.Context, d *schema.ResourceData) (interface{}, diag.Diagnostics) { - logger = NewTerraformr(log.Default().Writer()) - var diags diag.Diagnostics +func providerConfigure(version string) func(context.Context, *schema.ResourceData) (interface{}, diag.Diagnostics) { + return func(ctx context.Context, d *schema.ResourceData) (interface{}, diag.Diagnostics) { + logger = NewTerraformr(log.Default().Writer()) + var diags diag.Diagnostics - token := d.Get("token").(string) + token := d.Get("token").(string) - opts := []client.Option{ - client.TokenFromString(token), - client.Logger(logger.WithName("client")), - client.UserAgent(fmt.Sprintf("%s/%s (%s)", "terraform-provider-anxcloud", providerVersion, runtime.GOOS)), - } + opts := []client.Option{ + client.TokenFromString(token), + client.Logger(logger.WithName("client")), + client.UserAgent(fmt.Sprintf("%s/%s (%s)", "terraform-provider-anxcloud", version, runtime.GOOS)), + } - c, err := client.New(opts...) - if err != nil { - diags = append(diags, diag.Diagnostic{ - Severity: diag.Error, - Summary: "Unable to create Anexia client", - Detail: "Unable to create Anexia client with the given token, either the token is empty or invalid", - }) - return nil, diags - } + c, err := client.New(opts...) + if err != nil { + diags = append(diags, diag.Diagnostic{ + Severity: diag.Error, + Summary: "Unable to create Anexia client", + Detail: "Unable to create Anexia client with the given token, either the token is empty or invalid", + }) + return nil, diags + } - apiClient, err := api.NewAPI(api.WithClientOptions(opts...)) - if err != nil { - diags = append(diags, diag.Diagnostic{ - Severity: diag.Error, - Summary: "Unable to create generic Anexia client", - Detail: "Unable to create generic Anexia client with the given token, either the token is empty or invalid", - }) - return nil, diags - } + apiClient, err := api.NewAPI(api.WithClientOptions(opts...)) + if err != nil { + diags = append(diags, diag.Diagnostic{ + Severity: diag.Error, + Summary: "Unable to create generic Anexia client", + Detail: "Unable to create generic Anexia client with the given token, either the token is empty or invalid", + }) + return nil, diags + } - return providerContext{ - api: apiClient, - legacyClient: c, - }, diags + return providerContext{ + api: apiClient, + legacyClient: c, + }, diags + } } func handleNotFoundError(err error) error { diff --git a/anxcloud/provider_test.go b/anxcloud/provider_test.go index 325156ca..60b8640d 100644 --- a/anxcloud/provider_test.go +++ b/anxcloud/provider_test.go @@ -22,13 +22,15 @@ import ( var testAccProviderFactories map[string]func() (*schema.Provider, error) var testAccProvider *schema.Provider +var providerVersion = "development" + func init() { - testAccProvider = Provider() + testAccProvider = Provider(providerVersion) testAccProviderFactories = map[string]func() (*schema.Provider, error){ //nolint:unparam // ^ signature set by tf framework; test provider does not produce any errors "anxcloud": func() (*schema.Provider, error) { - return Provider(), nil + return Provider(providerVersion), nil }, } @@ -56,7 +58,7 @@ func testAccProviderFactoriesWithMockedClient(t tt.T, srv *ghttp.Server) map[str //nolint:unparam // ^ signature set by tf framework; test provider does not produce any errors "anxcloud": func() (*schema.Provider, error) { - provider := Provider() + provider := Provider(providerVersion) provider.ConfigureContextFunc = func(ctx context.Context, rd *schema.ResourceData) (interface{}, diag.Diagnostics) { return providerContext{api: c, legacyClient: lc}, nil } @@ -66,13 +68,13 @@ func testAccProviderFactoriesWithMockedClient(t tt.T, srv *ghttp.Server) map[str } func TestProvider(t *testing.T) { - if err := Provider().InternalValidate(); err != nil { + if err := Provider(providerVersion).InternalValidate(); err != nil { t.Fatalf("err: %s", err) } } func TestProvider_impl(t *testing.T) { - var _ *schema.Provider = Provider() + var _ *schema.Provider = Provider(providerVersion) } func testAccPreCheck(t *testing.T) { diff --git a/go.mod b/go.mod index d499eb16..e42440ca 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,9 @@ require ( github.com/google/go-cmp v0.6.0 github.com/goombaio/namegenerator v0.0.0-20181006234301-989e774b106e github.com/hashicorp/go-cty v1.4.1-0.20200723130312-85980079f637 + github.com/hashicorp/terraform-plugin-framework v1.5.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/mitchellh/go-testing-interface v1.14.1 github.com/onsi/ginkgo/v2 v2.13.2 @@ -53,7 +56,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 diff --git a/go.sum b/go.sum index d13fdac7..6f1b7884 100644 --- a/go.sum +++ b/go.sum @@ -109,10 +109,14 @@ github.com/hashicorp/terraform-exec v0.19.0 h1:FpqZ6n50Tk95mItTSS9BjeOVUb4eg81Sp github.com/hashicorp/terraform-exec v0.19.0/go.mod h1:tbxUpe3JKruE9Cuf65mycSIT8KiNPZ0FkuTE3H4urQg= github.com/hashicorp/terraform-json v0.18.0 h1:pCjgJEqqDESv4y0Tzdqfxr/edOIGkjs8keY42xfNBwU= github.com/hashicorp/terraform-json v0.18.0/go.mod h1:qdeBs11ovMzo5puhrRibdD6d2Dq6TyE/28JiU4tIQxk= +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-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-registry-address v0.2.3 h1:2TAiKJ1A3MAkZlH1YI/aTVcLZRu7JseiXNRHbOAyoTI= diff --git a/internal/provider/provider.go b/internal/provider/provider.go new file mode 100644 index 00000000..121e7fc8 --- /dev/null +++ b/internal/provider/provider.go @@ -0,0 +1,89 @@ +package provider + +import ( + "context" + "fmt" + "log" + "os" + "runtime" + + "github.com/anexia-it/terraform-provider-anxcloud/anxcloud" + "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" + "github.com/hashicorp/terraform-plugin-framework/types" + "go.anx.io/go-anxcloud/pkg/client" +) + +var _ provider.Provider = &AnexiaProvider{} + +type AnexiaProvider struct { + version string +} + +type AnexiaProviderModel struct { + Token types.String `tfsdk:"token"` +} + +func (p *AnexiaProvider) Metadata(ctx context.Context, req provider.MetadataRequest, resp *provider.MetadataResponse) { + resp.TypeName = "anxcloud" + resp.Version = p.version +} + +func (p *AnexiaProvider) Schema(ctx context.Context, req provider.SchemaRequest, resp *provider.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "token": schema.StringAttribute{ + Optional: true, + Description: "Anexia Cloud token.", + Sensitive: true, + }, + }, + } +} + +func (p *AnexiaProvider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) { + apiToken := os.Getenv("ANEXIA_TOKEN") + + var data AnexiaProviderModel + + resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + if data.Token.ValueString() != "" { + apiToken = data.Token.ValueString() + } + + if apiToken == "" { + resp.Diagnostics.AddError("Missing Anexia Engine token", "The Anexia Engine token was neither configured via `ANEXIA_TOKEN` env var nor via provider argument") + } + + logger := anxcloud.NewTerraformr(log.Default().Writer()) + opts := []client.Option{ + client.TokenFromString(apiToken), + client.Logger(logger.WithName("client")), + client.UserAgent(fmt.Sprintf("%s/%s (%s)", "terraform-provider-anxcloud", p.version, runtime.GOOS)), + } + + resp.ResourceData = opts + resp.DataSourceData = opts +} + +func (p *AnexiaProvider) Resources(ctx context.Context) []func() resource.Resource { + return nil +} + +func (p *AnexiaProvider) DataSources(ctx context.Context) []func() datasource.DataSource { + return nil +} + +func New(version string) func() provider.Provider { + return func() provider.Provider { + return &AnexiaProvider{ + version: version, + } + } +} diff --git a/main.go b/main.go index 1f338f94..04e2c23b 100644 --- a/main.go +++ b/main.go @@ -1,24 +1,63 @@ package main import ( + "context" "flag" + "log" "github.com/anexia-it/terraform-provider-anxcloud/anxcloud" - - "github.com/hashicorp/terraform-plugin-sdk/v2/plugin" + "github.com/anexia-it/terraform-provider-anxcloud/internal/provider" + "github.com/hashicorp/terraform-plugin-framework/providerserver" + "github.com/hashicorp/terraform-plugin-go/tfprotov6" + "github.com/hashicorp/terraform-plugin-go/tfprotov6/tf6server" + "github.com/hashicorp/terraform-plugin-mux/tf5to6server" + "github.com/hashicorp/terraform-plugin-mux/tf6muxserver" ) +var version = "development" + func main() { - var debugMode bool + ctx := context.Background() - flag.BoolVar(&debugMode, "debuggable", false, "set to true to run the provider with support for debuggers like delve") + var debug bool + + flag.BoolVar(&debug, "debug", false, "set to true to run the provider with support for debuggers like delve") flag.Parse() - opts := &plugin.ServeOpts{ - Debug: debugMode, - ProviderAddr: "registry.terraform.io/hashicorp/anxcloud", - ProviderFunc: anxcloud.Provider, + upgradedSdkServer, err := tf5to6server.UpgradeServer( + ctx, + anxcloud.Provider(version).GRPCProvider, + ) + if err != nil { + log.Fatal(err) } - plugin.Serve(opts) + providers := []func() tfprotov6.ProviderServer{ + providerserver.NewProtocol6(provider.New(version)()), + func() tfprotov6.ProviderServer { + return upgradedSdkServer + }, + } + + muxServer, err := tf6muxserver.NewMuxServer(ctx, providers...) + + if err != nil { + log.Fatal(err) + } + + var serveOpts []tf6server.ServeOpt + + if debug { + serveOpts = append(serveOpts, tf6server.WithManagedDebug()) + } + + err = tf6server.Serve( + "registry.terraform.io/anexia-it/anxcloud", + muxServer.ProviderServer, + serveOpts..., + ) + + if err != nil { + log.Fatal(err) + } } diff --git a/terraform-registry-manifest.json b/terraform-registry-manifest.json new file mode 100644 index 00000000..fec2a569 --- /dev/null +++ b/terraform-registry-manifest.json @@ -0,0 +1,6 @@ +{ + "version": 1, + "metadata": { + "protocol_versions": ["6.0"] + } +}