From d28317f54da317dff51180335732605f035c4e8b Mon Sep 17 00:00:00 2001 From: henryrecker-pingidentity <58565376+henryrecker-pingidentity@users.noreply.github.com> Date: Wed, 6 Nov 2024 15:47:53 -0600 Subject: [PATCH 1/2] Secret resource initial implementation --- docs/resources/secret.md | 53 +++ docs/resources/variable.md | 4 +- .../resources/identitycloud_secret/import.sh | 1 + .../identitycloud_secret/resource.tf | 6 + .../identitycloud_variable/resource.tf | 2 +- internal/provider/provider.go | 2 + .../resource/secrets/secret_resource_gen.go | 301 ++++++++++++++++++ .../secrets/secret_resource_gen_test.go | 156 +++++++++ .../variable/variable_resource_gen.go | 2 +- 9 files changed, 523 insertions(+), 4 deletions(-) create mode 100644 docs/resources/secret.md create mode 100644 examples/resources/identitycloud_secret/import.sh create mode 100644 examples/resources/identitycloud_secret/resource.tf create mode 100644 internal/resource/secrets/secret_resource_gen.go create mode 100644 internal/resource/secrets/secret_resource_gen_test.go diff --git a/docs/resources/secret.md b/docs/resources/secret.md new file mode 100644 index 0000000..2236456 --- /dev/null +++ b/docs/resources/secret.md @@ -0,0 +1,53 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "identitycloud_secret Resource - terraform-provider-identitycloud" +subcategory: "" +description: |- + Resource to create and manage a secret. +--- + +# identitycloud_secret (Resource) + +Resource to create and manage a secret. + +## Example Usage + +```terraform +resource "identitycloud_secret" "example" { + variable_id = "esv-mysecret1" + description = "My secret" + encoding = "generic" + value_base64 = base64encode("secretvalue") +} +``` + + +## Schema + +### Required + +- `encoding` (String) Type of base64 encoding used by the secret. Changing this value requires replacement of the resource. Supported values are `generic`, `pem`, `base64hmac`, `base64aes`. +- `secret_id` (String) ID of the secret. Must match the regex pattern `^esv-[a-z0-9_-]{1,124}$`. +- `use_in_placeholders` (Boolean) Whether the secret is used in placeholders. Changing this value requires replacement of the resource. +- `value_base64` (String) Base64 encoded value of the secret. Changing this value requires replacement of the resource. + +### Optional + +- `description` (String) Description of the secret. + +### Read-Only + +- `active_version` (String) Active version of the secret. +- `id` (String) ID of the secret. +- `last_change_date` (String) Date of the last change to the secret. +- `last_changed_by` (String) User who last changed the secret. +- `loaded` (Boolean) Whether the secret is loaded. +- `loaded_version` (String) Version of the secret that is loaded. + +## Import + +Import is supported using the following syntax: + +```shell +terraform import identitycloud_secret.example secret_id +``` diff --git a/docs/resources/variable.md b/docs/resources/variable.md index 8155202..6f3897c 100644 --- a/docs/resources/variable.md +++ b/docs/resources/variable.md @@ -17,7 +17,7 @@ resource "identitycloud_variable" "example" { variable_id = "esv-myvariable1" description = "My variable" expression_type = "list" - value_base64 = "ZGF0YQ==" + value_base64 = base64encode("[]") } ``` @@ -28,7 +28,7 @@ resource "identitycloud_variable" "example" { - `expression_type` (String) The type of variable expression. Supported values are `string`, `list`, `array`, `object`, `bool`, `int`, `number`, `base64encodedinlined`, `keyvaluelist`. - `value_base64` (String) Base64 encoded value of the variable. -- `variable_id` (String) ID of the variable +- `variable_id` (String) ID of the variable. Must match the regex `^esv-[a-z0-9_-]{1,124}$`. ### Optional diff --git a/examples/resources/identitycloud_secret/import.sh b/examples/resources/identitycloud_secret/import.sh new file mode 100644 index 0000000..3827da5 --- /dev/null +++ b/examples/resources/identitycloud_secret/import.sh @@ -0,0 +1 @@ +terraform import identitycloud_secret.example secret_id \ No newline at end of file diff --git a/examples/resources/identitycloud_secret/resource.tf b/examples/resources/identitycloud_secret/resource.tf new file mode 100644 index 0000000..8273aed --- /dev/null +++ b/examples/resources/identitycloud_secret/resource.tf @@ -0,0 +1,6 @@ +resource "identitycloud_secret" "example" { + variable_id = "esv-mysecret1" + description = "My secret" + encoding = "generic" + value_base64 = base64encode("secretvalue") +} \ No newline at end of file diff --git a/examples/resources/identitycloud_variable/resource.tf b/examples/resources/identitycloud_variable/resource.tf index 0a91253..f82959b 100644 --- a/examples/resources/identitycloud_variable/resource.tf +++ b/examples/resources/identitycloud_variable/resource.tf @@ -2,5 +2,5 @@ resource "identitycloud_variable" "example" { variable_id = "esv-myvariable1" description = "My variable" expression_type = "list" - value_base64 = "ZGF0YQ==" + value_base64 = base64encode("[]") } \ No newline at end of file diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 7e234cb..cd72dae 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -20,6 +20,7 @@ import ( "github.com/pingidentity/terraform-provider-identitycloud/internal/resource/cookiedomains" "github.com/pingidentity/terraform-provider-identitycloud/internal/resource/csrs" "github.com/pingidentity/terraform-provider-identitycloud/internal/resource/customdomains" + "github.com/pingidentity/terraform-provider-identitycloud/internal/resource/secrets" "github.com/pingidentity/terraform-provider-identitycloud/internal/resource/variable" internaltypes "github.com/pingidentity/terraform-provider-identitycloud/internal/types" "github.com/pingidentity/terraform-provider-identitycloud/internal/utils" @@ -179,6 +180,7 @@ func (p *identityCloudProvider) Resources(_ context.Context) []func() resource.R cookiedomains.CookieDomainsResource, csrs.CertificateSigningRequestResource, customdomains.CustomDomainsResource, + secrets.SecretResource, variable.VariableResource, } } diff --git a/internal/resource/secrets/secret_resource_gen.go b/internal/resource/secrets/secret_resource_gen.go new file mode 100644 index 0000000..14048ce --- /dev/null +++ b/internal/resource/secrets/secret_resource_gen.go @@ -0,0 +1,301 @@ +// Code generated by ping-terraform-plugin-framework-generator + +package secrets + +import ( + "context" + "regexp" + "time" + + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" + "github.com/hashicorp/terraform-plugin-framework/diag" + "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/boolplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" + client "github.com/pingidentity/identitycloud-go-client/identitycloud" + "github.com/pingidentity/terraform-provider-identitycloud/internal/auth" + "github.com/pingidentity/terraform-provider-identitycloud/internal/providererror" + internaltypes "github.com/pingidentity/terraform-provider-identitycloud/internal/types" +) + +var ( + _ resource.Resource = &secretResource{} + _ resource.ResourceWithConfigure = &secretResource{} + _ resource.ResourceWithImportState = &secretResource{} +) + +func SecretResource() resource.Resource { + return &secretResource{} +} + +type secretResource struct { + apiClient *client.APIClient + accessToken string +} + +func (r *secretResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_secret" +} + +func (r *secretResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { + if req.ProviderData == nil { + return + } + + resourceConfig, ok := req.ProviderData.(internaltypes.ResourceConfiguration) + if !ok { + resp.Diagnostics.AddError(providererror.InternalProviderError, "Invalid ProviderData when configuring resource. Please report this error in the provider's issue tracker.") + return + } + r.apiClient = resourceConfig.ApiClient + r.accessToken = resourceConfig.AccessToken +} + +type secretResourceModel struct { + ActiveVersion types.String `tfsdk:"active_version"` + Description types.String `tfsdk:"description"` + Encoding types.String `tfsdk:"encoding"` + Id types.String `tfsdk:"id"` + LastChangeDate types.String `tfsdk:"last_change_date"` + LastChangedBy types.String `tfsdk:"last_changed_by"` + Loaded types.Bool `tfsdk:"loaded"` + LoadedVersion types.String `tfsdk:"loaded_version"` + SecretId types.String `tfsdk:"secret_id"` + UseInPlaceholders types.Bool `tfsdk:"use_in_placeholders"` + ValueBase64 types.String `tfsdk:"value_base64"` +} + +func (r *secretResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Description: "Resource to create and manage a secret.", + Attributes: map[string]schema.Attribute{ + "active_version": schema.StringAttribute{ + Description: "Active version of the secret.", + Computed: true, + }, + "description": schema.StringAttribute{ + Description: "Description of the secret.", + Optional: true, + Computed: true, + Validators: []validator.String{ + stringvalidator.LengthAtMost(1000), + }, + Default: stringdefault.StaticString(""), + }, + "encoding": schema.StringAttribute{ + Required: true, + Description: "Type of base64 encoding used by the secret. Changing this value requires replacement of the resource. Supported values are `generic`, `pem`, `base64hmac`, `base64aes`.", + Validators: []validator.String{ + stringvalidator.OneOf( + "generic", + "pem", + "base64hmac", + "base64aes", + ), + }, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + }, + "id": schema.StringAttribute{ + Description: "ID of the secret.", + Computed: true, + }, + "last_change_date": schema.StringAttribute{ + Description: "Date of the last change to the secret.", + Computed: true, + }, + "last_changed_by": schema.StringAttribute{ + Description: "User who last changed the secret.", + Computed: true, + }, + "loaded": schema.BoolAttribute{ + Description: "Whether the secret is loaded.", + Computed: true, + }, + "loaded_version": schema.StringAttribute{ + Description: "Version of the secret that is loaded.", + Computed: true, + }, + "secret_id": schema.StringAttribute{ + Required: true, + Description: "ID of the secret. Must match the regex pattern `^esv-[a-z0-9_-]{1,124}$`.", + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + Validators: []validator.String{ + stringvalidator.RegexMatches(regexp.MustCompile("^esv-[a-z0-9_-]{1,124}$"), ""), + }, + }, + "use_in_placeholders": schema.BoolAttribute{ + Description: "Whether the secret is used in placeholders. Changing this value requires replacement of the resource.", + Required: true, + PlanModifiers: []planmodifier.Bool{ + boolplanmodifier.RequiresReplace(), + }, + }, + "value_base64": schema.StringAttribute{ + Description: "Base64 encoded value of the secret. Changing this value requires replacement of the resource.", + Required: true, + Validators: []validator.String{ + stringvalidator.RegexMatches(regexp.MustCompile("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"), ""), + }, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + }, + }, + } +} + +func (model *secretResourceModel) buildClientStruct() (*client.EsvSecretCreateRequest, diag.Diagnostics) { + result := &client.EsvSecretCreateRequest{} + // description + result.Description = model.Description.ValueStringPointer() + // encoding + result.Encoding = model.Encoding.ValueString() + // use_in_placeholders + result.UseInPlaceholders = model.UseInPlaceholders.ValueBool() + // value_base64 + result.ValueBase64 = model.ValueBase64.ValueString() + return result, nil +} + +func (model *secretResourceModel) buildUpdateClientStruct() (*client.EsvSetDescriptionRequest, diag.Diagnostics) { + result := &client.EsvSetDescriptionRequest{} + // description + result.Description = model.Description.ValueString() + return result, nil +} + +func (state *secretResourceModel) readClientResponse(response *client.EsvSecretResponse) diag.Diagnostics { + // active_version + state.ActiveVersion = types.StringValue(response.ActiveVersion) + // description + state.Description = types.StringValue(response.Description) + // encoding + state.Encoding = types.StringValue(response.Encoding) + // id + state.Id = types.StringValue(response.Id) + // last_change_date + state.LastChangeDate = types.StringValue(response.LastChangeDate.Format(time.RFC3339)) + // last_changed_by + state.LastChangedBy = types.StringValue(response.LastChangedBy) + // loaded + state.Loaded = types.BoolValue(response.Loaded) + // loaded_version + state.LoadedVersion = types.StringValue(response.LoadedVersion) + // use_in_placeholders + state.UseInPlaceholders = types.BoolValue(response.UseInPlaceholders) + return nil +} + +func (r *secretResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var data secretResourceModel + + // Read Terraform plan data into the model + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + + if resp.Diagnostics.HasError() { + return + } + + // Create API call logic + clientData, diags := data.buildClientStruct() + resp.Diagnostics.Append(diags...) + apiCreateRequest := r.apiClient.SecretsAPI.CreateSecret(auth.AuthContext(ctx, r.accessToken), data.SecretId.ValueString()) + apiCreateRequest = apiCreateRequest.Body(*clientData) + responseData, httpResp, err := r.apiClient.SecretsAPI.CreateSecretExecute(apiCreateRequest) + if err != nil { + providererror.ReportHttpError(ctx, &resp.Diagnostics, "An error occurred while creating the secret", err, httpResp) + return + } + + // Read response into the model + resp.Diagnostics.Append(data.readClientResponse(responseData)...) + + // Save data into Terraform state + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (r *secretResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var data secretResourceModel + + // Read Terraform prior state data into the model + resp.Diagnostics.Append(req.State.Get(ctx, &data)...) + + if resp.Diagnostics.HasError() { + return + } + + // Read API call logic + responseData, httpResp, err := r.apiClient.SecretsAPI.GetSecret(auth.AuthContext(ctx, r.accessToken), data.SecretId.ValueString()).Execute() + if err != nil { + if httpResp != nil && httpResp.StatusCode == 404 { + providererror.AddResourceNotFoundWarning(ctx, &resp.Diagnostics, "secret", httpResp) + resp.State.RemoveResource(ctx) + } else { + providererror.ReportHttpError(ctx, &resp.Diagnostics, "An error occurred while reading the secret", err, httpResp) + } + return + } + + // Read response into the model + resp.Diagnostics.Append(data.readClientResponse(responseData)...) + + // Save updated data into Terraform state + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (r *secretResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var data secretResourceModel + + // Read Terraform plan data into the model + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + + if resp.Diagnostics.HasError() { + return + } + + // Update API call logic + clientData, diags := data.buildUpdateClientStruct() + resp.Diagnostics.Append(diags...) + apiUpdateRequest := r.apiClient.SecretsAPI.ActionSecret(auth.AuthContext(ctx, r.accessToken), data.SecretId.ValueString()) + apiUpdateRequest = apiUpdateRequest.Body(*clientData) + httpResp, err := r.apiClient.SecretsAPI.ActionSecretExecute(apiUpdateRequest) + if err != nil { + providererror.ReportHttpError(ctx, &resp.Diagnostics, "An error occurred while updating the secret", err, httpResp) + return + } + + // Save updated data into Terraform state + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (r *secretResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var data secretResourceModel + + // Read Terraform prior state data into the model + resp.Diagnostics.Append(req.State.Get(ctx, &data)...) + + if resp.Diagnostics.HasError() { + return + } + + // Delete API call logic + httpResp, err := r.apiClient.CSRsAPI.DeleteCertificateSigningRequestById(auth.AuthContext(ctx, r.accessToken), data.SecretId.ValueString()).Execute() + if err != nil && (httpResp == nil || httpResp.StatusCode != 404) { + providererror.ReportHttpError(ctx, &resp.Diagnostics, "An error occurred while deleting the secret", err, httpResp) + } +} + +func (r *secretResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + // Retrieve import ID and save to secret_id attribute + resource.ImportStatePassthroughID(ctx, path.Root("secret_id"), req, resp) +} diff --git a/internal/resource/secrets/secret_resource_gen_test.go b/internal/resource/secrets/secret_resource_gen_test.go new file mode 100644 index 0000000..cdfcdde --- /dev/null +++ b/internal/resource/secrets/secret_resource_gen_test.go @@ -0,0 +1,156 @@ +// Code generated by ping-terraform-plugin-framework-generator + +package secrets_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-framework/providerserver" + "github.com/hashicorp/terraform-plugin-go/tfprotov6" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/pingidentity/terraform-provider-identitycloud/internal/acctest" + "github.com/pingidentity/terraform-provider-identitycloud/internal/provider" +) + +const secretSecretId = "secretSecretId" + +func TestAccSecret_RemovalDrift(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.ConfigurationPreCheck(t) }, + ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){ + "identitycloud": providerserver.NewProtocol6WithError(provider.NewTestProvider()), + }, + CheckDestroy: secret_CheckDestroy, + Steps: []resource.TestStep{ + { + // Create the resource with a minimal model + Config: secret_MinimalHCL(), + }, + { + // Delete the resource on the service, outside of terraform, verify that a non-empty plan is generated + PreConfig: func() { + secret_Delete(t) + }, + RefreshState: true, + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func TestAccSecret_MinimalMaximal(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.ConfigurationPreCheck(t) }, + ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){ + "identitycloud": providerserver.NewProtocol6WithError(provider.NewTestProvider()), + }, + CheckDestroy: secret_CheckDestroy, + Steps: []resource.TestStep{ + { + // Create the resource with a minimal model + Config: secret_MinimalHCL(), + Check: secret_CheckComputedValuesMinimal(), + }, + { + // Delete the minimal model + Config: secret_MinimalHCL(), + Destroy: true, + }, + { + // Re-create with a complete model + Config: secret_CompleteHCL(), + Check: secret_CheckComputedValuesComplete(), + }, + { + // Back to minimal model + Config: secret_MinimalHCL(), + Check: secret_CheckComputedValuesMinimal(), + }, + { + // Back to complete model + Config: secret_CompleteHCL(), + Check: secret_CheckComputedValuesComplete(), + }, + { + // Test importing the resource + Config: secret_CompleteHCL(), + ResourceName: "identitycloud_secret.example", + ImportStateId: secretSecretId, + ImportStateVerifyIdentifierAttribute: "secret_id", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +// Minimal HCL with only required values set +func secret_MinimalHCL() string { + return fmt.Sprintf(` +resource "identitycloud_secret" "example" { + secret_id = "%s" + encoding = "generic" + use_in_placeholders = false + value_base64 = base64encode("examplesecret") +} +`, secretSecretId) +} + +// Maximal HCL with all values set where possible +func secret_CompleteHCL() string { + return fmt.Sprintf(` +resource "identitycloud_secret" "example" { + secret_id = "%s" + description = "my example secret" + encoding = "generic" + use_in_placeholders = false + value_base64 = base64encode("examplesecretupdated") +} +`, secretSecretId) +} + +// Validate any computed values when applying minimal HCL +func secret_CheckComputedValuesMinimal() resource.TestCheckFunc { + return resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("identitycloud_secret.example", "active_version", "expected_value"), + resource.TestCheckResourceAttr("identitycloud_secret.example", "description", ""), + resource.TestCheckResourceAttr("identitycloud_secret.example", "id", secretSecretId), + resource.TestCheckResourceAttrSet("identitycloud_secret.example", "last_change_date"), + resource.TestCheckResourceAttr("identitycloud_secret.example", "last_changed_by", "tf-provider-testing"), + resource.TestCheckResourceAttr("identitycloud_secret.example", "loaded", "false"), + resource.TestCheckResourceAttr("identitycloud_secret.example", "loaded_version", "expected_value"), + ) +} + +// Validate any computed values when applying complete HCL +func secret_CheckComputedValuesComplete() resource.TestCheckFunc { + return resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("identitycloud_secret.example", "active_version", "expected_value"), + resource.TestCheckResourceAttr("identitycloud_secret.example", "id", secretSecretId), + resource.TestCheckResourceAttrSet("identitycloud_secret.example", "last_change_date"), + resource.TestCheckResourceAttr("identitycloud_secret.example", "last_changed_by", "tf-provider-testing"), + resource.TestCheckResourceAttr("identitycloud_secret.example", "loaded", "false"), + resource.TestCheckResourceAttr("identitycloud_secret.example", "loaded_version", "expected_value"), + ) +} + +// Delete the resource +func secret_Delete(t *testing.T) { + testClient := acctest.Client(nil) + _, err := testClient.CSRsAPI.DeleteCertificateSigningRequestById(acctest.AuthContext(), secretSecretId).Execute() + if err != nil { + t.Fatalf("Failed to delete config: %v", err) + } +} + +// Test that any objects created by the test are destroyed +func secret_CheckDestroy(s *terraform.State) error { + testClient := acctest.Client(nil) + _, err := testClient.CSRsAPI.DeleteCertificateSigningRequestById(acctest.AuthContext(), secretSecretId).Execute() + if err == nil { + return fmt.Errorf("secret still exists after tests. Expected it to be destroyed") + } + return nil +} diff --git a/internal/resource/variable/variable_resource_gen.go b/internal/resource/variable/variable_resource_gen.go index 6f52329..5a9e3db 100644 --- a/internal/resource/variable/variable_resource_gen.go +++ b/internal/resource/variable/variable_resource_gen.go @@ -122,7 +122,7 @@ func (r *variableResource) Schema(ctx context.Context, req resource.SchemaReques }, "variable_id": schema.StringAttribute{ Required: true, - Description: "ID of the variable", + Description: "ID of the variable. Must match the regex `^esv-[a-z0-9_-]{1,124}$`.", Validators: []validator.String{ stringvalidator.RegexMatches(regexp.MustCompile("^esv-[a-z0-9_-]{1,124}$"), ""), }, From fee261fc4c1a7d52bd4fde886cb0aed1e94b06b5 Mon Sep 17 00:00:00 2001 From: henryrecker-pingidentity <58565376+henryrecker-pingidentity@users.noreply.github.com> Date: Wed, 6 Nov 2024 16:10:16 -0600 Subject: [PATCH 2/2] Fix test and delete logic --- .../resource/secrets/secret_resource_gen.go | 2 +- .../secrets/secret_resource_gen_test.go | 20 ++++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/internal/resource/secrets/secret_resource_gen.go b/internal/resource/secrets/secret_resource_gen.go index 14048ce..4b2d416 100644 --- a/internal/resource/secrets/secret_resource_gen.go +++ b/internal/resource/secrets/secret_resource_gen.go @@ -289,7 +289,7 @@ func (r *secretResource) Delete(ctx context.Context, req resource.DeleteRequest, } // Delete API call logic - httpResp, err := r.apiClient.CSRsAPI.DeleteCertificateSigningRequestById(auth.AuthContext(ctx, r.accessToken), data.SecretId.ValueString()).Execute() + _, httpResp, err := r.apiClient.SecretsAPI.DeleteSecret(auth.AuthContext(ctx, r.accessToken), data.SecretId.ValueString()).Execute() if err != nil && (httpResp == nil || httpResp.StatusCode != 404) { providererror.ReportHttpError(ctx, &resp.Diagnostics, "An error occurred while deleting the secret", err, httpResp) } diff --git a/internal/resource/secrets/secret_resource_gen_test.go b/internal/resource/secrets/secret_resource_gen_test.go index cdfcdde..ad03ca6 100644 --- a/internal/resource/secrets/secret_resource_gen_test.go +++ b/internal/resource/secrets/secret_resource_gen_test.go @@ -14,7 +14,7 @@ import ( "github.com/pingidentity/terraform-provider-identitycloud/internal/provider" ) -const secretSecretId = "secretSecretId" +const secretSecretId = "esv-testsecret" func TestAccSecret_RemovalDrift(t *testing.T) { resource.Test(t, resource.TestCase{ @@ -81,6 +81,8 @@ func TestAccSecret_MinimalMaximal(t *testing.T) { ImportStateVerifyIdentifierAttribute: "secret_id", ImportState: true, ImportStateVerify: true, + // The value of the secret is not returned by the API + ImportStateVerifyIgnore: []string{"value_base64"}, }, }, }) @@ -114,32 +116,32 @@ resource "identitycloud_secret" "example" { // Validate any computed values when applying minimal HCL func secret_CheckComputedValuesMinimal() resource.TestCheckFunc { return resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("identitycloud_secret.example", "active_version", "expected_value"), + resource.TestCheckResourceAttr("identitycloud_secret.example", "active_version", "1"), resource.TestCheckResourceAttr("identitycloud_secret.example", "description", ""), resource.TestCheckResourceAttr("identitycloud_secret.example", "id", secretSecretId), resource.TestCheckResourceAttrSet("identitycloud_secret.example", "last_change_date"), resource.TestCheckResourceAttr("identitycloud_secret.example", "last_changed_by", "tf-provider-testing"), - resource.TestCheckResourceAttr("identitycloud_secret.example", "loaded", "false"), - resource.TestCheckResourceAttr("identitycloud_secret.example", "loaded_version", "expected_value"), + resource.TestCheckResourceAttr("identitycloud_secret.example", "loaded", "true"), + resource.TestCheckResourceAttr("identitycloud_secret.example", "loaded_version", "1"), ) } // Validate any computed values when applying complete HCL func secret_CheckComputedValuesComplete() resource.TestCheckFunc { return resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("identitycloud_secret.example", "active_version", "expected_value"), + resource.TestCheckResourceAttr("identitycloud_secret.example", "active_version", "1"), resource.TestCheckResourceAttr("identitycloud_secret.example", "id", secretSecretId), resource.TestCheckResourceAttrSet("identitycloud_secret.example", "last_change_date"), resource.TestCheckResourceAttr("identitycloud_secret.example", "last_changed_by", "tf-provider-testing"), - resource.TestCheckResourceAttr("identitycloud_secret.example", "loaded", "false"), - resource.TestCheckResourceAttr("identitycloud_secret.example", "loaded_version", "expected_value"), + resource.TestCheckResourceAttr("identitycloud_secret.example", "loaded", "true"), + resource.TestCheckResourceAttr("identitycloud_secret.example", "loaded_version", "1"), ) } // Delete the resource func secret_Delete(t *testing.T) { testClient := acctest.Client(nil) - _, err := testClient.CSRsAPI.DeleteCertificateSigningRequestById(acctest.AuthContext(), secretSecretId).Execute() + _, _, err := testClient.SecretsAPI.DeleteSecret(acctest.AuthContext(), secretSecretId).Execute() if err != nil { t.Fatalf("Failed to delete config: %v", err) } @@ -148,7 +150,7 @@ func secret_Delete(t *testing.T) { // Test that any objects created by the test are destroyed func secret_CheckDestroy(s *terraform.State) error { testClient := acctest.Client(nil) - _, err := testClient.CSRsAPI.DeleteCertificateSigningRequestById(acctest.AuthContext(), secretSecretId).Execute() + _, _, err := testClient.SecretsAPI.DeleteSecret(acctest.AuthContext(), secretSecretId).Execute() if err == nil { return fmt.Errorf("secret still exists after tests. Expected it to be destroyed") }