-
Notifications
You must be signed in to change notification settings - Fork 548
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Phase 1] Multiplex provider - minimal TF Plugin Framework provider i…
…mplementation (#2067) * implement the framework provider * setup provider server factory * setup framework provider schema * handle defaults in configure * [Phase 2] Complete the provider configuration setup (#2090) * setup framework provider schema * handle defaults in configure * WIP: handle auth login methods * [Phase 2] Include Auth Login blocks in multiplexed Provider configuration (#2097) make updates to all auth logins and fix build run go mod tidy register all auth logins to test build add all auth login blocks and match schema implementations set default for azure scope address todos - remove commented code; neither are read from env vars - add validators * remove set_namespace_from_token field * add custom path validator * configure namespace for vault client * review comments * add muxed provider acc tests * use consts, set required fields and update tests * add tests for multi envs and fix bug * fix bug with overriding config val * add custom URI validator for OIDC auth * fix a few default mount types * add comments and migration state example acc test * remove dupe default entries; add validators * remove client_auth docs * add kerbos token and file path validators * don't use double pointer and remove redundant return --------- Co-authored-by: vinay-gopalan <[email protected]> --------- Co-authored-by: vinay-gopalan <[email protected]>
- Loading branch information
1 parent
6125fee
commit 3ddd03e
Showing
57 changed files
with
2,616 additions
and
288 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package base | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/hashicorp/terraform-plugin-framework/resource/schema" | ||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" | ||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" | ||
"github.com/hashicorp/terraform-plugin-framework/schema/validator" | ||
"github.com/hashicorp/terraform-plugin-framework/types" | ||
"github.com/hashicorp/terraform-provider-vault/internal/consts" | ||
"github.com/hashicorp/terraform-provider-vault/internal/framework/validators" | ||
) | ||
|
||
// BaseModel describes common fields for all of the Terraform resource data models | ||
type BaseModel struct { | ||
Namespace types.String `tfsdk:"namespace"` | ||
} | ||
|
||
func baseSchema() map[string]schema.Attribute { | ||
return map[string]schema.Attribute{ | ||
consts.FieldNamespace: schema.StringAttribute{ | ||
Optional: true, | ||
PlanModifiers: []planmodifier.String{ | ||
stringplanmodifier.RequiresReplace(), | ||
}, | ||
MarkdownDescription: "Target namespace. (requires Enterprise)", | ||
Validators: []validator.String{ | ||
validators.PathValidator(), | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func MustAddBaseSchema(s *schema.Schema) { | ||
for k, v := range baseSchema() { | ||
if _, ok := s.Attributes[k]; ok { | ||
panic(fmt.Sprintf("cannot add schema field %q, already exists in the Schema map", k)) | ||
} | ||
|
||
s.Attributes[k] = v | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package client | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"os" | ||
|
||
"github.com/hashicorp/terraform-plugin-log/tflog" | ||
"github.com/hashicorp/terraform-provider-vault/internal/consts" | ||
"github.com/hashicorp/terraform-provider-vault/internal/provider" | ||
"github.com/hashicorp/vault/api" | ||
) | ||
|
||
func GetClient(ctx context.Context, meta interface{}, namespace string) (*api.Client, error) { | ||
var p *provider.ProviderMeta | ||
|
||
switch v := meta.(type) { | ||
case *provider.ProviderMeta: | ||
p = v | ||
default: | ||
return nil, fmt.Errorf("meta argument must be a %T, not %T", p, meta) | ||
} | ||
|
||
ns := namespace | ||
if namespace == "" { | ||
// in order to import namespaced resources the user must provide | ||
// the namespace from an environment variable. | ||
ns = os.Getenv(consts.EnvVarVaultNamespaceImport) | ||
if ns != "" { | ||
tflog.Debug(ctx, fmt.Sprintf("Value for %q set from environment", consts.FieldNamespace)) | ||
} | ||
} | ||
|
||
if ns != "" { | ||
return p.GetNSClient(ns) | ||
} | ||
|
||
return p.GetClient() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Terraform Plugin Framework Validators | ||
|
||
This package contains custom Terraform Plugin Framework [validators](https://developer.hashicorp.com/terraform/plugin/framework/validation). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
// Copyright (c) HashiCorp, Inc. | ||
// SPDX-License-Identifier: MPL-2.0 | ||
|
||
package validators | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"os" | ||
|
||
"github.com/hashicorp/terraform-plugin-framework/schema/validator" | ||
"github.com/mitchellh/go-homedir" | ||
) | ||
|
||
var _ validator.String = fileExists{} | ||
|
||
// fileExists validates that a given token is a valid initialization token | ||
type fileExists struct{} | ||
|
||
// Description describes the validation in plain text formatting. | ||
func (v fileExists) Description(_ context.Context) string { | ||
return "value must be a valid path to an existing file" | ||
} | ||
|
||
// MarkdownDescription describes the validation in Markdown formatting. | ||
func (v fileExists) MarkdownDescription(ctx context.Context) string { | ||
return v.Description(ctx) | ||
} | ||
|
||
// ValidateString performs the validation. | ||
func (v fileExists) ValidateString(ctx context.Context, request validator.StringRequest, response *validator.StringResponse) { | ||
if request.ConfigValue.IsNull() || request.ConfigValue.IsUnknown() { | ||
return | ||
} | ||
|
||
value := request.ConfigValue.ValueString() | ||
if value == "" { | ||
response.Diagnostics.AddError("invalid file", "value cannot be empty") | ||
return | ||
} | ||
|
||
filename, err := homedir.Expand(value) | ||
if err != nil { | ||
response.Diagnostics.AddError("invalid file", err.Error()) | ||
return | ||
} | ||
|
||
st, err := os.Stat(filename) | ||
if err != nil { | ||
response.Diagnostics.AddError("invalid file", fmt.Sprintf("failed to stat path %q, err=%s", filename, err)) | ||
return | ||
} | ||
|
||
if st.IsDir() { | ||
response.Diagnostics.AddError("invalid file", fmt.Sprintf("path %q is not a file", filename)) | ||
return | ||
} | ||
} | ||
|
||
func FileExistsValidator() validator.String { | ||
return fileExists{} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
// Copyright (c) HashiCorp, Inc. | ||
// SPDX-License-Identifier: MPL-2.0 | ||
|
||
package validators | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
|
||
"github.com/hashicorp/terraform-plugin-framework/diag" | ||
"github.com/hashicorp/terraform-plugin-framework/schema/validator" | ||
"github.com/hashicorp/terraform-plugin-framework/types" | ||
) | ||
|
||
const testFilePath = "./testdata/fake_account.json" | ||
|
||
func TestFrameworkProvider_FileExistsValidator(t *testing.T) { | ||
cases := map[string]struct { | ||
configValue func(t *testing.T) types.String | ||
expectedErrorCount int | ||
}{ | ||
"file-is-valid": { | ||
configValue: func(t *testing.T) types.String { | ||
return types.StringValue(testFilePath) // Path to a test fixture | ||
}, | ||
}, | ||
"non-existant-file-is-not-valid": { | ||
configValue: func(t *testing.T) types.String { | ||
return types.StringValue("./this/path/doesnt/exist.json") // Doesn't exist | ||
}, | ||
expectedErrorCount: 1, | ||
}, | ||
"empty-string-is-not-valid": { | ||
configValue: func(t *testing.T) types.String { | ||
return types.StringValue("") | ||
}, | ||
expectedErrorCount: 1, | ||
}, | ||
"unconfigured-is-valid": { | ||
configValue: func(t *testing.T) types.String { | ||
return types.StringNull() | ||
}, | ||
}, | ||
} | ||
|
||
for tn, tc := range cases { | ||
t.Run(tn, func(t *testing.T) { | ||
// Arrange | ||
req := validator.StringRequest{ | ||
ConfigValue: tc.configValue(t), | ||
} | ||
|
||
resp := validator.StringResponse{ | ||
Diagnostics: diag.Diagnostics{}, | ||
} | ||
|
||
f := FileExistsValidator() | ||
|
||
// Act | ||
f.ValidateString(context.Background(), req, &resp) | ||
|
||
// Assert | ||
if resp.Diagnostics.ErrorsCount() != tc.expectedErrorCount { | ||
t.Errorf("Expected %d errors, got %d", tc.expectedErrorCount, resp.Diagnostics.ErrorsCount()) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// Copyright (c) HashiCorp, Inc. | ||
// SPDX-License-Identifier: MPL-2.0 | ||
|
||
package validators | ||
|
||
import ( | ||
"context" | ||
"os" | ||
|
||
"github.com/hashicorp/terraform-plugin-framework/schema/validator" | ||
googleoauth "golang.org/x/oauth2/google" | ||
) | ||
|
||
// Credentials Validator | ||
var _ validator.String = credentialsValidator{} | ||
|
||
// credentialsValidator validates that a string Attribute's is valid JSON credentials. | ||
type credentialsValidator struct{} | ||
|
||
// Description describes the validation in plain text formatting. | ||
func (v credentialsValidator) Description(_ context.Context) string { | ||
return "value must be a path to valid JSON credentials or valid, raw, JSON credentials" | ||
} | ||
|
||
// MarkdownDescription describes the validation in Markdown formatting. | ||
func (v credentialsValidator) MarkdownDescription(ctx context.Context) string { | ||
return v.Description(ctx) | ||
} | ||
|
||
// ValidateString performs the validation. | ||
func (v credentialsValidator) ValidateString(ctx context.Context, request validator.StringRequest, response *validator.StringResponse) { | ||
if request.ConfigValue.IsNull() || request.ConfigValue.IsUnknown() { | ||
return | ||
} | ||
|
||
value := request.ConfigValue.ValueString() | ||
|
||
// if this is a path and we can stat it, assume it's ok | ||
if _, err := os.Stat(value); err == nil { | ||
return | ||
} | ||
if _, err := googleoauth.CredentialsFromJSON(context.Background(), []byte(value)); err != nil { | ||
response.Diagnostics.AddError("JSON credentials are not valid", err.Error()) | ||
} | ||
} | ||
|
||
func GCPCredentialsValidator() validator.String { | ||
return credentialsValidator{} | ||
} |
Oops, something went wrong.