From 4615f7370b6ba77228883e94e550eb55af7c0660 Mon Sep 17 00:00:00 2001 From: Dmytro Onishchenko Date: Thu, 8 Sep 2022 15:22:10 +0200 Subject: [PATCH] Switched to a new provider from ec package --- .../deploymentdatasource/datasource.go | 2 +- .../deploymentresource/create.go | 0 .../deploymentresource/deployment_data.go | 0 .../deployment_resource.go | 35 ++- ec/internal/validators/urlvalidator.go | 7 +- ec/provider.go | 5 +- ec/provider_config.go | 9 +- ectpf/provider.go | 255 ------------------ ectpf/provider_config.go | 66 ----- 9 files changed, 31 insertions(+), 348 deletions(-) rename {ectpf/ecresource => ec/ecresource-tpf}/deploymentresource/create.go (100%) rename {ectpf/ecresource => ec/ecresource-tpf}/deploymentresource/deployment_data.go (100%) rename {ectpf => ec/ecresource-tpf/deploymentresource}/deployment_resource.go (91%) delete mode 100644 ectpf/provider.go delete mode 100644 ectpf/provider_config.go diff --git a/ec/ecdatasource/deploymentdatasource/datasource.go b/ec/ecdatasource/deploymentdatasource/datasource.go index 09dc6c2d4..2bde0b082 100644 --- a/ec/ecdatasource/deploymentdatasource/datasource.go +++ b/ec/ecdatasource/deploymentdatasource/datasource.go @@ -21,7 +21,6 @@ import ( "context" "fmt" - "github.com/elastic/terraform-provider-ec/ec/internal" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/provider" @@ -31,6 +30,7 @@ import ( "github.com/elastic/cloud-sdk-go/pkg/api/deploymentapi/deputil" "github.com/elastic/cloud-sdk-go/pkg/models" + "github.com/elastic/terraform-provider-ec/ec/internal" "github.com/elastic/terraform-provider-ec/ec/internal/util" ) diff --git a/ectpf/ecresource/deploymentresource/create.go b/ec/ecresource-tpf/deploymentresource/create.go similarity index 100% rename from ectpf/ecresource/deploymentresource/create.go rename to ec/ecresource-tpf/deploymentresource/create.go diff --git a/ectpf/ecresource/deploymentresource/deployment_data.go b/ec/ecresource-tpf/deploymentresource/deployment_data.go similarity index 100% rename from ectpf/ecresource/deploymentresource/deployment_data.go rename to ec/ecresource-tpf/deploymentresource/deployment_data.go diff --git a/ectpf/deployment_resource.go b/ec/ecresource-tpf/deploymentresource/deployment_resource.go similarity index 91% rename from ectpf/deployment_resource.go rename to ec/ecresource-tpf/deploymentresource/deployment_resource.go index 12e9e0dda..80976f380 100644 --- a/ectpf/deployment_resource.go +++ b/ec/ecresource-tpf/deploymentresource/deployment_resource.go @@ -15,30 +15,29 @@ // specific language governing permissions and limitations // under the License. -package ectpf +package deploymentresource import ( "context" + "github.com/elastic/terraform-provider-ec/ec/internal" "github.com/hashicorp/terraform-plugin-framework/diag" tpfprovider "github.com/hashicorp/terraform-plugin-framework/provider" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/tfsdk" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-log/tflog" - - "github.com/elastic/terraform-provider-ec/ectpf/ecresource/deploymentresource" ) // Ensure provider defined types fully satisfy framework interfaces -var _ tpfprovider.ResourceType = deploymentResourceType{} +var _ tpfprovider.ResourceType = DeploymentResourceType{} var _ resource.Resource = deploymentResource{} // var _ resource.ResourceWithImportState = deploymentResource{} -type deploymentResourceType struct{} +type DeploymentResourceType struct{} -func (t deploymentResourceType) GetSchema(ctx context.Context) (tfsdk.Schema, diag.Diagnostics) { +func (t DeploymentResourceType) GetSchema(ctx context.Context) (tfsdk.Schema, diag.Diagnostics) { return tfsdk.Schema{ // This description is used by the documentation generator and the language server. MarkdownDescription: "Elastic Cloud Deployment resource", @@ -158,20 +157,20 @@ func (t deploymentResourceType) GetSchema(ctx context.Context) (tfsdk.Schema, di }, nil } -func (t deploymentResourceType) NewResource(ctx context.Context, in tpfprovider.Provider) (resource.Resource, diag.Diagnostics) { - provider, diags := convertProviderType(in) +func (t DeploymentResourceType) NewResource(ctx context.Context, in tpfprovider.Provider) (resource.Resource, diag.Diagnostics) { + p, diags := internal.ConvertProviderType(in) - return deploymentResource{ - provider: provider, + return &deploymentResource{ + provider: p, }, diags } type deploymentResource struct { - provider scaffoldingProvider + provider internal.Provider } func (r deploymentResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { - if !r.provider.configured { + if r.provider.GetClient() == nil { resp.Diagnostics.AddError( "Provider not configured", "The provider hasn't been configured before apply, likely because it depends on an unknown value from another resource. This leads to weird stuff happening, so we'd prefer if you didn't do that. Thanks!", @@ -179,21 +178,21 @@ func (r deploymentResource) Create(ctx context.Context, req resource.CreateReque return } - var cfg deploymentresource.DeploymentData + var cfg DeploymentData diags := req.Config.Get(ctx, &cfg) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } - var plan deploymentresource.DeploymentData + var plan DeploymentData diags = req.Plan.Get(ctx, &plan) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } - deploymentResource, errors := deploymentresource.Create(ctx, r.provider.client, &cfg, &plan) + deploymentResource, errors := Create(ctx, r.provider.GetClient(), &cfg, &plan) if len(errors) > 0 { for _, err := range errors { @@ -227,7 +226,7 @@ func (r deploymentResource) Create(ctx context.Context, req resource.CreateReque } func (r deploymentResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { - var state deploymentresource.DeploymentData + var state DeploymentData diags := req.State.Get(ctx, &state) resp.Diagnostics.Append(diags...) @@ -250,7 +249,7 @@ func (r deploymentResource) Read(ctx context.Context, req resource.ReadRequest, } func (r deploymentResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { - var data deploymentresource.DeploymentData + var data DeploymentData diags := req.Plan.Get(ctx, &data) resp.Diagnostics.Append(diags...) @@ -272,7 +271,7 @@ func (r deploymentResource) Update(ctx context.Context, req resource.UpdateReque } func (r deploymentResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { - var data deploymentresource.DeploymentData + var data DeploymentData diags := req.State.Get(ctx, &data) resp.Diagnostics.Append(diags...) diff --git a/ec/internal/validators/urlvalidator.go b/ec/internal/validators/urlvalidator.go index 5dc7751ab..f620baef5 100644 --- a/ec/internal/validators/urlvalidator.go +++ b/ec/internal/validators/urlvalidator.go @@ -20,11 +20,12 @@ package validators import ( "context" "fmt" + "net/url" + "strings" + "github.com/hashicorp/terraform-plugin-framework/tfsdk" "github.com/hashicorp/terraform-plugin-framework/types" "golang.org/x/exp/slices" - "net/url" - "strings" ) type isURLWithSchemeValidator struct { @@ -96,5 +97,5 @@ func (v isURLWithSchemeValidator) Validate(ctx context.Context, req tfsdk.Valida } func IsURLWithSchemeValidator(validSchemes []string) tfsdk.AttributeValidator { - return isURLWithSchemeValidator{} + return isURLWithSchemeValidator{ValidSchemes: []string{"http", "https"}} } diff --git a/ec/provider.go b/ec/provider.go index 8564701c9..66614de22 100644 --- a/ec/provider.go +++ b/ec/provider.go @@ -25,6 +25,7 @@ import ( "github.com/elastic/terraform-provider-ec/ec/ecdatasource/deploymentdatasource" "github.com/elastic/terraform-provider-ec/ec/ecdatasource/deploymentsdatasource" "github.com/elastic/terraform-provider-ec/ec/ecdatasource/stackdatasource" + "github.com/elastic/terraform-provider-ec/ec/ecresource-tpf/deploymentresource" "github.com/elastic/terraform-provider-ec/ec/ecresource/elasticsearchkeystoreresource" "github.com/elastic/terraform-provider-ec/ec/ecresource/extensionresource" "github.com/elastic/terraform-provider-ec/ec/ecresource/trafficfilterassocresource" @@ -348,7 +349,9 @@ func (p *Provider) Configure(ctx context.Context, req provider.ConfigureRequest, } func (p *Provider) GetResources(_ context.Context) (map[string]provider.ResourceType, diag.Diagnostics) { - return map[string]provider.ResourceType{}, nil + return map[string]provider.ResourceType{ + "ec_deployment": deploymentresource.DeploymentResourceType{}, + }, nil } func (p *Provider) GetDataSources(_ context.Context) (map[string]provider.DataSourceType, diag.Diagnostics) { diff --git a/ec/provider_config.go b/ec/provider_config.go index acef22ef5..6e8969fd5 100644 --- a/ec/provider_config.go +++ b/ec/provider_config.go @@ -20,13 +20,14 @@ package ec import ( "context" "fmt" - "github.com/elastic/terraform-provider-ec/ec/internal/util" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "net/http" "os" "time" + "github.com/elastic/terraform-provider-ec/ec/internal/util" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/elastic/cloud-sdk-go/pkg/api" "github.com/elastic/cloud-sdk-go/pkg/auth" ) @@ -129,7 +130,7 @@ func verboseSettings(name string, verbose, redactAuth bool) (api.VerboseSettings } return api.VerboseSettings{ - Verbose: true, + Verbose: verbose, RedactAuth: redactAuth, Device: f, }, nil diff --git a/ectpf/provider.go b/ectpf/provider.go deleted file mode 100644 index 5247b4ed0..000000000 --- a/ectpf/provider.go +++ /dev/null @@ -1,255 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you under -// the Apache License, Version 2.0 (the "License"); you may -// not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -// New provider during the migration to Terraform Plugin Framework. -// It should host all data sources and resources that migrated to TPF, -// while non-migrated data sources and resouces should be handled by `ec.Provider()`. -// Once all data sources and resources are migrated, -// the provider shall become the only one provider in the repo. - -package ectpf - -import ( - "context" - "fmt" - "os" - - "github.com/hashicorp/terraform-plugin-framework/diag" - tpfprovider "github.com/hashicorp/terraform-plugin-framework/provider" - "github.com/hashicorp/terraform-plugin-framework/tfsdk" - "github.com/hashicorp/terraform-plugin-framework/types" - - "github.com/elastic/cloud-sdk-go/pkg/api" -) - -const ( - eceOnlyText = "Available only when targeting ECE Installations or Elasticsearch Service Private" - saasRequiredText = "The only valid authentication mechanism for the Elasticsearch Service" - - endpointDesc = "Endpoint where the terraform provider will point to. Defaults to \"%s\"." - insecureDesc = "Allow the provider to skip TLS validation on its outgoing HTTP calls." - timeoutDesc = "Timeout used for individual HTTP calls. Defaults to \"1m\"." - verboseDesc = "When set, a \"request.log\" file will be written with all outgoing HTTP requests. Defaults to \"false\"." - verboseCredsDesc = "When set with verbose, the contents of the Authorization header will not be redacted. Defaults to \"false\"." -) - -var ( - apikeyDesc = fmt.Sprint("API Key to use for API authentication. ", saasRequiredText, ".") - usernameDesc = fmt.Sprint("Username to use for API authentication. ", eceOnlyText, ".") - passwordDesc = fmt.Sprint("Password to use for API authentication. ", eceOnlyText, ".") -) - -// Ensure provider defined types fully satisfy framework interfaces -var _ tpfprovider.Provider = &scaffoldingProvider{} - -// provider satisfies the tfsdk.Provider interface and usually is included -// with all Resource and DataSource implementations. -type scaffoldingProvider struct { - // client can contain the upstream provider SDK or HTTP client used to - // communicate with the upstream service. Resource and DataSource - // implementations can then make calls using this client. - // - // TODO: If appropriate, implement upstream provider SDK or HTTP client. - // client vendorsdk.ExampleClient - - // configured is set to true at the end of the Configure method. - // This can be used in Resource and DataSource implementations to verify - // that the provider was previously configured. - configured bool - - // version is set to the provider version on release, "dev" when the - // provider is built and ran locally, and "test" when running acceptance - // testing. - version string - - client *api.API -} - -// providerData can be used to store data from the Terraform configuration. -type providerData struct { - Endpoint types.String `tfsdk:"endpoint"` - Apikey types.String `tfsdk:"apikey"` - Insecure types.Bool `tfsdk:"insecure"` - Timeout types.String `tfsdk:"timeout"` - Verbose types.Bool `tfsdk:"verbose"` -} - -func (p *scaffoldingProvider) Configure(ctx context.Context, req tpfprovider.ConfigureRequest, resp *tpfprovider.ConfigureResponse) { - var data providerData - diags := req.Config.Get(ctx, &data) - resp.Diagnostics.Append(diags...) - - if resp.Diagnostics.HasError() { - return - } - - cfg, err := newAPIConfig(&data) - if err != nil { - resp.Diagnostics.AddError( - "Cannot configure Elastic API", - err.Error(), - ) - return - } - - client, err := api.NewAPI(cfg) - if err != nil { - resp.Diagnostics.AddError( - "Cannot initialise Elastic API client from the configuration", - err.Error(), - ) - return - } - - p.client = client - - p.configured = true -} - -func (p *scaffoldingProvider) GetResources(ctx context.Context) (map[string]tpfprovider.ResourceType, diag.Diagnostics) { - return map[string]tpfprovider.ResourceType{ - "ec_deployment": deploymentResourceType{}, - }, nil -} - -func (p *scaffoldingProvider) GetDataSources(ctx context.Context) (map[string]tpfprovider.DataSourceType, diag.Diagnostics) { - return map[string]tpfprovider.DataSourceType{}, nil -} - -// type endpointPlanModifier struct{} - -// func (*endpointPlanModifier) Description(context.Context) string { -// return "" -// } - -// func (*endpointPlanModifier) MarkdownDescription(context.Context) string { -// return "" -// } - -// func (*endpointPlanModifier) Modify(ctx context.Context, req tfsdk.ModifyAttributePlanRequest, resp *tfsdk.ModifyAttributePlanResponse) { -// if req.AttributeConfig.IsNull() { -// v, err := MultiEnvDefaultFunc([]string{"EC_ENDPOINT", "EC_HOST"}, api.ESSEndpoint) -// if err != nil { -// resp.Diagnostics.AddError( -// `Cannot read endpoint from default environment variables "EC_ENDPOINT", "EC_HOST"`, -// err.Error(), -// ) -// return -// } -// resp.AttributePlan = types.String{Value: v} -// } -// } - -func MultiEnvDefaultFunc(ks []string, def string) (string, error) { - for _, k := range ks { - if v := os.Getenv(k); v != "" { - return v, nil - } - } - return def, nil -} - -func (p *scaffoldingProvider) GetSchema(ctx context.Context) (tfsdk.Schema, diag.Diagnostics) { - return tfsdk.Schema{ - Attributes: map[string]tfsdk.Attribute{ - "endpoint": { - Description: fmt.Sprintf(endpointDesc, api.ESSEndpoint), - Type: types.StringType, - Optional: true, - }, - "apikey": { - Description: apikeyDesc, - Type: types.StringType, - Optional: true, - Sensitive: true, - }, - "username": { - Description: usernameDesc, - Type: types.StringType, - Optional: true, - }, - "password": { - Description: passwordDesc, - Type: types.StringType, - Optional: true, - Sensitive: true, - }, - "insecure": { - Description: "Allow the provider to skip TLS validation on its outgoing HTTP calls.", - Type: types.BoolType, - Optional: true, - }, - "timeout": { - Description: timeoutDesc, - Type: types.StringType, - Optional: true, - }, - "verbose": { - Description: verboseDesc, - Type: types.BoolType, - Optional: true, - }, - "verbose_credentials": { - Description: verboseCredsDesc, - Type: types.BoolType, - Optional: true, - }, - "verbose_file": { - Description: timeoutDesc, - Type: types.StringType, - Optional: true, - }, - }, - }, nil -} - -func New(version string) func() tpfprovider.Provider { - return func() tpfprovider.Provider { - return &scaffoldingProvider{ - version: version, - } - } -} - -// convertProviderType is a helper function for NewResource and NewDataSource -// implementations to associate the concrete provider type. Alternatively, -// this helper can be skipped and the provider type can be directly type -// asserted (e.g. provider: in.(*provider)), however using this can prevent -// potential panics. -func convertProviderType(in tpfprovider.Provider) (scaffoldingProvider, diag.Diagnostics) { - var diags diag.Diagnostics - - p, ok := in.(*scaffoldingProvider) - - if !ok { - diags.AddError( - "Unexpected Provider Instance Type", - fmt.Sprintf("While creating the data source or resource, an unexpected provider type (%T) was received. This is always a bug in the provider code and should be reported to the provider developers.", p), - ) - return scaffoldingProvider{}, diags - } - - if p == nil { - diags.AddError( - "Unexpected Provider Instance Type", - "While creating the data source or resource, an unexpected empty provider instance was received. This is always a bug in the provider code and should be reported to the provider developers.", - ) - return scaffoldingProvider{}, diags - } - - return *p, diags -} diff --git a/ectpf/provider_config.go b/ectpf/provider_config.go deleted file mode 100644 index aad6e6aa2..000000000 --- a/ectpf/provider_config.go +++ /dev/null @@ -1,66 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you under -// the Apache License, Version 2.0 (the "License"); you may -// not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -package ectpf - -import ( - "fmt" - "net/http" - "os" - "time" - - "github.com/elastic/cloud-sdk-go/pkg/api" - "github.com/elastic/cloud-sdk-go/pkg/auth" -) - -var ( - // defaultTimeout used for all outgoing HTTP requests, keeping it low-ish - // since any requests which timeout due to network factors are retried - // automatically by the SDK 2 times. - defaultTimeout = 40 * time.Second -) - -func newAPIConfig(data *providerData) (api.Config, error) { - var cfg api.Config - - authWriter, err := auth.NewAuthWriter(auth.Config{ - APIKey: data.Apikey.Value, - }) - if err != nil { - return cfg, err - } - - return api.Config{ - ErrorDevice: os.Stdout, - Client: &http.Client{}, - VerboseSettings: api.VerboseSettings{ - Device: os.Stdout, - Verbose: data.Verbose.Value, - RedactAuth: false, - }, - AuthWriter: authWriter, - Host: data.Endpoint.Value, - SkipTLSVerify: data.Insecure.Value, - Timeout: defaultTimeout, - UserAgent: userAgent("0.0.1"), - Retries: 2, - }, nil -} - -func userAgent(v string) string { - return fmt.Sprintf("elastic-terraform-provider2/%s (%s)", v, api.DefaultUserAgent) -}