From 6387e7906e0b43ac90e492bcdf17072aa77ecd5f Mon Sep 17 00:00:00 2001 From: David Debeau Date: Mon, 9 Sep 2024 13:56:23 -0500 Subject: [PATCH] Move provider validation from ValidateConfig to Configure so we can use data sources in the provider config --- internal/provider/provider.go | 140 +++++++++++------------------ internal/provider/provider_test.go | 27 +++++- 2 files changed, 76 insertions(+), 91 deletions(-) diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 0705ca7..67097f8 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -80,96 +80,6 @@ func (p *quayProvider) Configure(ctx context.Context, req provider.ConfigureRequ return } - url := os.Getenv("QUAY_URL") - token := os.Getenv("QUAY_TOKEN") - oauth2Username := os.Getenv("QUAY_OAUTH2_USERNAME") - oauth2Password := os.Getenv("QUAY_OAUTH2_PASSWORD") - oauth2ClientID := os.Getenv("QUAY_OAUTH2_CLIENT_ID") - oauth2TokenURL := os.Getenv("QUAY_OAUTH2_TOKEN_URL") - - if !config.Url.IsNull() { - url = config.Url.ValueString() - } - - if !config.Token.IsNull() { - token = config.Token.ValueString() - } - - if !config.OAuth2Username.IsNull() { - oauth2Username = config.OAuth2Username.ValueString() - } - - if !config.OAuth2Password.IsNull() { - oauth2Password = config.OAuth2Password.ValueString() - } - - if !config.OAuth2ClientID.IsNull() { - oauth2ClientID = config.OAuth2ClientID.ValueString() - } - - if !config.OAuth2TokenURL.IsNull() { - oauth2TokenURL = config.OAuth2TokenURL.ValueString() - } - - ctx = tflog.SetField(ctx, "url", url) - ctx = tflog.SetField(ctx, "token", token) - ctx = tflog.SetField(ctx, "oauth2_username", oauth2Username) - ctx = tflog.SetField(ctx, "oauth2_password", oauth2Password) - ctx = tflog.SetField(ctx, "oauth2_client_id", oauth2ClientID) - ctx = tflog.SetField(ctx, "oauth2_token_url", oauth2TokenURL) - ctx = tflog.MaskFieldValuesWithFieldKeys(ctx, "token") - ctx = tflog.MaskFieldValuesWithFieldKeys(ctx, "oauth2_password") - - tflog.Debug(ctx, "Creating Quay client") - - configuration := &quay_api.Configuration{ - DefaultHeader: make(map[string]string), - UserAgent: "OpenAPI-Generator/1.0.0/go", - Debug: false, - Servers: quay_api.ServerConfigurations{ - { - URL: url, - Description: "No description provided", - }, - }, - OperationServers: map[string]quay_api.ServerConfigurations{}, - } - - if token == "" { - oauth2Config := &oauth2.Config{ - ClientID: oauth2ClientID, - Endpoint: oauth2.Endpoint{ - TokenURL: oauth2TokenURL, - }, - } - - oauth2Token, err := oauth2Config.PasswordCredentialsToken(ctx, oauth2Username, oauth2Password) - if err != nil { - resp.Diagnostics.AddError("Error retrieving OAuth2 access token", - "Error retrieving OAuth2 access token: "+err.Error()) - return - } - - token = oauth2Token.AccessToken - } - - configuration.AddDefaultHeader("Authorization", "Bearer "+token) - client := quay_api.NewAPIClient(configuration) - - resp.DataSourceData = client - resp.ResourceData = client - - tflog.Info(ctx, "Configured Quay client", map[string]any{"success": true}) -} - -func (p *quayProvider) ValidateConfig(ctx context.Context, req provider.ValidateConfigRequest, resp *provider.ValidateConfigResponse) { - var config quayProviderModel - diags := req.Config.Get(ctx, &config) - resp.Diagnostics.Append(diags...) - if resp.Diagnostics.HasError() { - return - } - if config.Url.IsUnknown() || config.Token.IsUnknown() || config.OAuth2Username.IsUnknown() || config.OAuth2Password.IsUnknown() || config.OAuth2ClientID.IsUnknown() || config.OAuth2TokenURL.IsUnknown() { resp.Diagnostics.AddError( @@ -284,6 +194,56 @@ func (p *quayProvider) ValidateConfig(ctx context.Context, req provider.Validate ) return } + + ctx = tflog.SetField(ctx, "url", url) + ctx = tflog.SetField(ctx, "token", token) + ctx = tflog.SetField(ctx, "oauth2_username", oauth2Username) + ctx = tflog.SetField(ctx, "oauth2_password", oauth2Password) + ctx = tflog.SetField(ctx, "oauth2_client_id", oauth2ClientID) + ctx = tflog.SetField(ctx, "oauth2_token_url", oauth2TokenURL) + ctx = tflog.MaskFieldValuesWithFieldKeys(ctx, "token") + ctx = tflog.MaskFieldValuesWithFieldKeys(ctx, "oauth2_password") + + tflog.Debug(ctx, "Creating Quay client") + + configuration := &quay_api.Configuration{ + DefaultHeader: make(map[string]string), + UserAgent: "OpenAPI-Generator/1.0.0/go", + Debug: false, + Servers: quay_api.ServerConfigurations{ + { + URL: url, + Description: "No description provided", + }, + }, + OperationServers: map[string]quay_api.ServerConfigurations{}, + } + + if token == "" { + oauth2Config := &oauth2.Config{ + ClientID: oauth2ClientID, + Endpoint: oauth2.Endpoint{ + TokenURL: oauth2TokenURL, + }, + } + + oauth2Token, err := oauth2Config.PasswordCredentialsToken(ctx, oauth2Username, oauth2Password) + if err != nil { + resp.Diagnostics.AddError("Error retrieving OAuth2 access token", + "Error retrieving OAuth2 access token: "+err.Error()) + return + } + + token = oauth2Token.AccessToken + } + + configuration.AddDefaultHeader("Authorization", "Bearer "+token) + client := quay_api.NewAPIClient(configuration) + + resp.DataSourceData = client + resp.ResourceData = client + + tflog.Info(ctx, "Configured Quay client", map[string]any{"success": true}) } func (p *quayProvider) Metadata(_ context.Context, _ provider.MetadataRequest, resp *provider.MetadataResponse) { diff --git a/internal/provider/provider_test.go b/internal/provider/provider_test.go index 1d944c4..a33a296 100644 --- a/internal/provider/provider_test.go +++ b/internal/provider/provider_test.go @@ -36,6 +36,10 @@ func TestAccProviderValidationWithoutENV(t *testing.T) { Source: "hashicorp/random", VersionConstraint: "~> 3.6", }, + "null": { + Source: "hashicorp/null", + VersionConstraint: "~> 3.2", + }, }, ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, Steps: []resource.TestStep{ @@ -48,7 +52,7 @@ resource "random_string" "this" { } provider "quay" { - url = "https://quay-${random_string.this}.example.com" + url = "https://quay-${random_string.this.result}.example.com" } data "quay_organization" "provider_test" { @@ -57,6 +61,27 @@ data "quay_organization" "provider_test" { `, ExpectError: regexp.MustCompile(".*Error: Unknown configuration values"), }, + // Config value from data source + { + PlanOnly: true, + Config: ` +data "null_data_source" "token" { + inputs = { + token = "test" + } +} + +provider "quay" { + url = "https://quay.example.com" + token = data.null_data_source.token.outputs["token"] +} + +data "quay_organization" "provider_test" { + name = "provider_test" +} +`, + ExpectError: regexp.MustCompile(".*Error: Error reading Quay org"), + }, // Token and OAuth2 credentials { PlanOnly: true,