From 2a3d27f7bbbf96a9d7b75d4c1a090970c3d62474 Mon Sep 17 00:00:00 2001 From: Vitaly Antonenko Date: Wed, 17 Apr 2024 12:59:46 +0300 Subject: [PATCH] Fix comments and add noname secret test --- internal/juju/models.go | 2 +- internal/juju/secrets.go | 3 +- internal/provider/resource_secret.go | 27 ++++++++--- internal/provider/resource_secret_test.go | 59 +++++++++++++++++++++-- 4 files changed, 79 insertions(+), 12 deletions(-) diff --git a/internal/juju/models.go b/internal/juju/models.go index 1ece0329..cebeb916 100644 --- a/internal/juju/models.go +++ b/internal/juju/models.go @@ -175,7 +175,7 @@ func (c *modelsClient) CreateModel(input CreateModelInput) (CreateModelResponse, resp.Type = modelInfo.Type.String() resp.UUID = modelInfo.UUID - // Create the model to the client cache of jujuModel + // Add a model object on the client internal to the provider c.AddModel(modelInfo.Name, modelInfo.UUID, modelInfo.Type) // set constraints when required diff --git a/internal/juju/secrets.go b/internal/juju/secrets.go index 4b19c00c..533fb13f 100644 --- a/internal/juju/secrets.go +++ b/internal/juju/secrets.go @@ -8,6 +8,7 @@ import ( "errors" "fmt" + jujuerrors "github.com/juju/errors" "github.com/juju/juju/api" apisecrets "github.com/juju/juju/api/client/secrets" coresecrets "github.com/juju/juju/core/secrets" @@ -231,7 +232,7 @@ func (c *secretsClient) DeleteSecret(input *DeleteSecretInput) error { } // TODO: think about removing concrete revision. err = secretAPIClient.RemoveSecret(secretURI, "", nil) - if err != nil { + if !errors.Is(err, jujuerrors.NotFound) { return typedError(err) } diff --git a/internal/provider/resource_secret.go b/internal/provider/resource_secret.go index dab0a718..710cb6cf 100644 --- a/internal/provider/resource_secret.go +++ b/internal/provider/resource_secret.go @@ -6,12 +6,12 @@ package provider import ( "context" "fmt" - "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" - "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" "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/types" "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/juju/terraform-provider-juju/internal/juju" @@ -88,6 +88,7 @@ func (s *secretResource) Schema(_ context.Context, req resource.SchemaRequest, r } } +// Configure sets up the Juju client for the secret resource. func (s *secretResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { // Prevent panic if the provider has not been configured. if req.ProviderData == nil { @@ -107,6 +108,7 @@ func (s *secretResource) Configure(ctx context.Context, req resource.ConfigureRe s.subCtx = tflog.NewSubsystem(ctx, LogResourceSecret) } +// Create creates a new secret in the Juju model. func (s *secretResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { // Prevent panic if the provider has not been configured. if s.client == nil { @@ -122,6 +124,8 @@ func (s *secretResource) Create(ctx context.Context, req resource.CreateRequest, return } + s.trace(fmt.Sprintf("creating secret resource %q", plan.Name.ValueString())) + secretValue := make(map[string]string) resp.Diagnostics.Append(plan.Value.ElementsAs(ctx, &secretValue, false)...) @@ -141,9 +145,10 @@ func (s *secretResource) Create(ctx context.Context, req resource.CreateRequest, // Save plan into Terraform state resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) - s.trace(fmt.Sprintf("create secret resource %q", plan.SecretId)) + s.trace(fmt.Sprintf("created secret resource %q", plan.SecretId)) } +// Read reads the details of a secret in the Juju model. func (s *secretResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { // Prevent panic if the provider has not been configured. if s.client == nil { @@ -159,6 +164,8 @@ func (s *secretResource) Read(ctx context.Context, req resource.ReadRequest, res return } + s.trace(fmt.Sprintf("reading secret resource %q", state.SecretId)) + readSecretOutput, err := s.client.Secrets.ReadSecret(&juju.ReadSecretInput{ SecretId: state.SecretId.ValueString(), ModelName: state.Model.ValueString(), @@ -191,6 +198,7 @@ func (s *secretResource) Read(ctx context.Context, req resource.ReadRequest, res s.trace(fmt.Sprintf("read secret resource %q", state.SecretId)) } +// Update updates the details of a secret in the Juju model. func (s *secretResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { // Prevent panic if the provider has not been configured. if s.client == nil { @@ -207,6 +215,10 @@ func (s *secretResource) Update(ctx context.Context, req resource.UpdateRequest, return } + s.trace(fmt.Sprintf("updating secret resource %q", state.SecretId)) + s.trace(fmt.Sprintf("Update - current state: %v", state)) + s.trace(fmt.Sprintf("Update - proposed plan: %v", plan)) + var err error noChange := true @@ -255,9 +267,10 @@ func (s *secretResource) Update(ctx context.Context, req resource.UpdateRequest, // Save updated data into Terraform state resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) - s.trace(fmt.Sprintf("update secret resource %q", state.SecretId)) + s.trace(fmt.Sprintf("updated secret resource %q", state.SecretId)) } +// Delete removes a secret from the Juju model. func (s *secretResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { // Prevent panic if the provider has not been configured. if s.client == nil { @@ -273,9 +286,7 @@ func (s *secretResource) Delete(ctx context.Context, req resource.DeleteRequest, return } - s.trace("Deleting", map[string]interface{}{ - "ID": state.SecretId.ValueString(), - }) + s.trace(fmt.Sprintf("deleting secret resource %q", state.SecretId)) err := s.client.Secrets.DeleteSecret(&juju.DeleteSecretInput{ ModelName: state.Model.ValueString(), @@ -285,6 +296,8 @@ func (s *secretResource) Delete(ctx context.Context, req resource.DeleteRequest, resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to delete secret, got error: %s", err)) return } + + s.trace(fmt.Sprintf("deleted secret resource %q", state.SecretId)) } func (s *secretResource) trace(msg string, additionalFields ...map[string]interface{}) { diff --git a/internal/provider/resource_secret_test.go b/internal/provider/resource_secret_test.go index 93f751c0..6e660d7f 100644 --- a/internal/provider/resource_secret_test.go +++ b/internal/provider/resource_secret_test.go @@ -12,8 +12,37 @@ import ( internaltesting "github.com/juju/terraform-provider-juju/internal/testing" ) +func TestAcc_ResourceSecret_CreateWithoutName(t *testing.T) { + if os.Getenv("JUJU_AGENT_VERSION") == "" || internaltesting.CompareVersions(os.Getenv("JUJU_AGENT_VERSION"), "3.3.0") < 0 { + t.Skip("JUJU_AGENT_VERSION is not set or is below 3.3.0") + } + + modelName := acctest.RandomWithPrefix("tf-test-model") + secretInfo := "test-info" + secretValue := map[string]string{ + "key1": "value1", + "key2": "value2", + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: frameworkProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccResourceSecretWithoutName(modelName, secretValue, secretInfo), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("juju_secret.noname", "model", modelName), + resource.TestCheckResourceAttr("juju_secret.noname", "info", secretInfo), + resource.TestCheckResourceAttr("juju_secret.noname", "value.key1", "value1"), + resource.TestCheckResourceAttr("juju_secret.noname", "value.key2", "value2"), + ), + }, + }, + }) + +} + func TestAcc_ResourceSecret_CreateWithInfo(t *testing.T) { - // Check env var JUJU_AGENT_VERSION is above 3.1.0 if os.Getenv("JUJU_AGENT_VERSION") == "" || internaltesting.CompareVersions(os.Getenv("JUJU_AGENT_VERSION"), "3.3.0") < 0 { t.Skip("JUJU_AGENT_VERSION is not set or is below 3.3.0") } @@ -45,7 +74,6 @@ func TestAcc_ResourceSecret_CreateWithInfo(t *testing.T) { } func TestAcc_ResourceSecret_CreateWithNoInfo(t *testing.T) { - // Check env var JUJU_AGENT_VERSION is above 3.1.0 if os.Getenv("JUJU_AGENT_VERSION") == "" || internaltesting.CompareVersions(os.Getenv("JUJU_AGENT_VERSION"), "3.3.0") < 0 { t.Skip("JUJU_AGENT_VERSION is not set or is below 3.3.0") } @@ -75,7 +103,6 @@ func TestAcc_ResourceSecret_CreateWithNoInfo(t *testing.T) { } func TestAcc_ResourceSecret_Update(t *testing.T) { - // Check env var JUJU_AGENT_VERSION is above 3.1.0 if os.Getenv("JUJU_AGENT_VERSION") == "" || internaltesting.CompareVersions(os.Getenv("JUJU_AGENT_VERSION"), "3.3.0") < 0 { t.Skip("JUJU_AGENT_VERSION is not set or is below 3.3.0") } @@ -153,3 +180,29 @@ resource "juju_secret" "{{.SecretName}}" { "SecretInfo": secretInfo, }) } + +func testAccResourceSecretWithoutName(modelName string, secretValue map[string]string, secretInfo string) string { + return internaltesting.GetStringFromTemplateWithData( + "testAccResourceSecret", + ` +resource "juju_model" "{{.ModelName}}" { + name = "{{.ModelName}}" +} + +resource "juju_secret" "noname" { + model = juju_model.{{.ModelName}}.name + value = { + {{- range $key, $value := .SecretValue }} + "{{$key}}" = "{{$value}}" + {{- end }} + } + {{- if ne .SecretInfo "" }} + info = "{{.SecretInfo}}" + {{- end }} +} +`, internaltesting.TemplateData{ + "ModelName": modelName, + "SecretValue": secretValue, + "SecretInfo": secretInfo, + }) +}