From 042152ef0e360b87400cad73b7a960ae91c7f6f7 Mon Sep 17 00:00:00 2001 From: Ben Pearce Date: Tue, 9 Jul 2024 10:37:58 +1000 Subject: [PATCH] chore: added mux server for sxs framework migration (#664) * added mux server for sxs framework migration * removed broken framework provider tests * updated provider type name --- go.mod | 4 +- go.sum | 4 + main.go | 40 ++++++++-- octopusdeploy_framework/config.go | 48 +++++++++++ octopusdeploy_framework/framework_provider.go | 79 +++++++++++++++++++ 5 files changed, 168 insertions(+), 7 deletions(-) create mode 100644 octopusdeploy_framework/config.go create mode 100644 octopusdeploy_framework/framework_provider.go diff --git a/go.mod b/go.mod index 816537f2c..0a274942b 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,10 @@ require ( github.com/gruntwork-io/terratest v0.41.11 github.com/hashicorp/go-cty v1.4.1-0.20200723130312-85980079f637 github.com/hashicorp/terraform-plugin-docs v0.13.0 + github.com/hashicorp/terraform-plugin-framework v1.9.0 + github.com/hashicorp/terraform-plugin-go v0.23.0 github.com/hashicorp/terraform-plugin-log v0.9.0 + github.com/hashicorp/terraform-plugin-mux v0.16.0 github.com/hashicorp/terraform-plugin-sdk/v2 v2.34.0 github.com/stretchr/testify v1.9.0 golang.org/x/exp v0.0.0-20230510235704-dd950f8aeaea @@ -83,7 +86,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-registry-address v0.2.3 // indirect github.com/hashicorp/terraform-svchost v0.1.1 // indirect github.com/hashicorp/yamux v0.1.1 // indirect diff --git a/go.sum b/go.sum index 795d2a3cf..f861232ab 100644 --- a/go.sum +++ b/go.sum @@ -254,10 +254,14 @@ 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.13.0 h1:6e+VIWsVGb6jYJewfzq2ok2smPzZrt1Wlm9koLeKazY= github.com/hashicorp/terraform-plugin-docs v0.13.0/go.mod h1:W0oCmHAjIlTHBbvtppWHe8fLfZ2BznQbuv8+UD8OucQ= +github.com/hashicorp/terraform-plugin-framework v1.9.0 h1:caLcDoxiRucNi2hk8+j3kJwkKfvHznubyFsJMWfZqKU= +github.com/hashicorp/terraform-plugin-framework v1.9.0/go.mod h1:qBXLDn69kM97NNVi/MQ9qgd1uWWsVftGSnygYG1tImM= 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-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-registry-address v0.2.3 h1:2TAiKJ1A3MAkZlH1YI/aTVcLZRu7JseiXNRHbOAyoTI= diff --git a/main.go b/main.go index 63a681dc9..c6d9ac72f 100644 --- a/main.go +++ b/main.go @@ -1,9 +1,17 @@ package main import ( + "context" "flag" + "github.com/OctopusDeploy/terraform-provider-octopusdeploy/octopusdeploy_framework" + "log" + "github.com/OctopusDeploy/terraform-provider-octopusdeploy/octopusdeploy" - "github.com/hashicorp/terraform-plugin-sdk/v2/plugin" + "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" ) //go:generate go run github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs @@ -13,14 +21,34 @@ func main() { flag.BoolVar(&debugMode, "debug", false, "set to true to run the provider with support for debuggers like delve") flag.Parse() - opts := &plugin.ServeOpts{ - ProviderFunc: octopusdeploy.Provider, + ctx := context.Background() + + upgradedSdkServer, err := tf5to6server.UpgradeServer( + ctx, + octopusdeploy.Provider().GRPCProvider) + if err != nil { + log.Fatal(err) + } + + providers := []func() tfprotov6.ProviderServer{ + providerserver.NewProtocol6(octopusdeploy_framework.NewOctopusDeployFrameworkProvider()), + func() tfprotov6.ProviderServer { + return upgradedSdkServer + }, } + muxServer, err := tf6muxserver.NewMuxServer(ctx, providers...) + + opts := []tf6server.ServeOpt{} + + var providerName = "registry.terraform.io/OctopusDeployLabs/octopusdeploy" if debugMode { - opts.Debug = true - opts.ProviderAddr = "octopus.com/com/octopusdeploy" + opts = append(opts, tf6server.WithManagedDebug()) + providerName = "octopus.com/com/octopusdeploy" } - plugin.Serve(opts) + err = tf6server.Serve(providerName, muxServer.ProviderServer, opts...) + if err != nil { + log.Fatal(err) + } } diff --git a/octopusdeploy_framework/config.go b/octopusdeploy_framework/config.go new file mode 100644 index 000000000..6ffb43729 --- /dev/null +++ b/octopusdeploy_framework/config.go @@ -0,0 +1,48 @@ +package octopusdeploy_framework + +import ( + "context" + "fmt" + "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/client" + "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/spaces" + "github.com/hashicorp/terraform-plugin-log/tflog" + "net/url" +) + +type Config struct { + Address string + ApiKey string + SpaceID string + Client *client.Client +} + +func (c *Config) GetClient(ctx context.Context) error { + tflog.Debug(ctx, "GetClient") + apiURL, err := url.Parse(c.Address) + if err != nil { + return err + } + + octopus, err := client.NewClient(nil, apiURL, c.ApiKey, "") + if err != nil { + return err + } + + if len(c.SpaceID) > 0 { + space, err := spaces.GetByID(octopus, c.SpaceID) + if err != nil { + return err + } + + octopus, err = client.NewClient(nil, apiURL, c.ApiKey, space.GetID()) + if err != nil { + return err + } + } + + c.Client = octopus + + createdClient := octopus != nil + tflog.Debug(ctx, fmt.Sprintf("GetClient completed: %t", createdClient)) + return nil +} diff --git a/octopusdeploy_framework/framework_provider.go b/octopusdeploy_framework/framework_provider.go new file mode 100644 index 000000000..d25bafe91 --- /dev/null +++ b/octopusdeploy_framework/framework_provider.go @@ -0,0 +1,79 @@ +package octopusdeploy_framework + +import ( + "context" + "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" +) + +type octopusDeployFrameworkProvider struct { + Address types.String `tfsdk:"address"` + ApiKey types.String `tfsdk:"api_key"` + SpaceID types.String `tfsdk:"space_id"` +} + +var _ provider.Provider = (*octopusDeployFrameworkProvider)(nil) +var _ provider.ProviderWithMetaSchema = (*octopusDeployFrameworkProvider)(nil) + +func NewOctopusDeployFrameworkProvider() *octopusDeployFrameworkProvider { + return &octopusDeployFrameworkProvider{} +} + +func (p *octopusDeployFrameworkProvider) Metadata(ctx context.Context, req provider.MetadataRequest, resp *provider.MetadataResponse) { + resp.TypeName = "octopusdeploy" +} + +func (p *octopusDeployFrameworkProvider) MetaSchema(ctx context.Context, request provider.MetaSchemaRequest, response *provider.MetaSchemaResponse) { + +} + +func (p *octopusDeployFrameworkProvider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) { + var providerData octopusDeployFrameworkProvider + resp.Diagnostics.Append(req.Config.Get(ctx, &providerData)...) + if resp.Diagnostics.HasError() { + return + } + + config := Config{} + config.ApiKey = providerData.ApiKey.ValueString() + config.Address = providerData.Address.ValueString() + config.SpaceID = providerData.SpaceID.ValueString() + if err := config.GetClient(ctx); err != nil { + resp.Diagnostics.AddError("failed to load client", err.Error()) + } + + resp.DataSourceData = &config + resp.ResourceData = &config +} + +func (p *octopusDeployFrameworkProvider) DataSources(ctx context.Context) []func() datasource.DataSource { + return []func() datasource.DataSource{} +} + +func (p *octopusDeployFrameworkProvider) Resources(ctx context.Context) []func() resource.Resource { + return []func() resource.Resource{} +} + +func (p *octopusDeployFrameworkProvider) Schema(ctx context.Context, req provider.SchemaRequest, resp *provider.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "address": schema.StringAttribute{ + Optional: false, + Required: true, + Description: "The endpoint of the Octopus REST API", + }, + "api_key": schema.StringAttribute{ + Optional: false, + Required: true, + Description: "The API key to use with the Octopus REST API", + }, + "space_id": schema.StringAttribute{ + Optional: true, + Description: "The space ID to target", + }, + }, + } +}