From 5e2ec0df86ef84eeded619fcde4d61391b024e21 Mon Sep 17 00:00:00 2001 From: Noah-Jerome Lotzer Date: Sun, 25 Jun 2023 04:40:15 +0200 Subject: [PATCH 01/14] verifiedpermissions: add policy store (#32204) --- .changelog/32204.txt | 3 + .../verifiedpermissions/policy_store.go | 379 ++++++++++++++++++ .../verifiedpermissions/policy_store_test.go | 193 +++++++++ .../service_package_gen.go | 8 +- ...fiedpermissions_policy_store.html.markdown | 68 ++++ 5 files changed, 650 insertions(+), 1 deletion(-) create mode 100644 .changelog/32204.txt create mode 100644 internal/service/verifiedpermissions/policy_store.go create mode 100644 internal/service/verifiedpermissions/policy_store_test.go create mode 100644 website/docs/r/verifiedpermissions_policy_store.html.markdown diff --git a/.changelog/32204.txt b/.changelog/32204.txt new file mode 100644 index 00000000000..2a8bf12d8d1 --- /dev/null +++ b/.changelog/32204.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +aws_verifiedpermissions_policy_store +``` \ No newline at end of file diff --git a/internal/service/verifiedpermissions/policy_store.go b/internal/service/verifiedpermissions/policy_store.go new file mode 100644 index 00000000000..351d750c3a6 --- /dev/null +++ b/internal/service/verifiedpermissions/policy_store.go @@ -0,0 +1,379 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package verifiedpermissions + +import ( + "context" + "errors" + "log" + "time" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions" + "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions/types" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/enum" + "github.com/hashicorp/terraform-provider-aws/internal/errs" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/internal/verify" + "github.com/hashicorp/terraform-provider-aws/names" +) + +// @SDKResource("aws_verifiedpermissions_policy_store", name="Policy Store") +func ResourcePolicyStore() *schema.Resource { + return &schema.Resource{ + CreateWithoutTimeout: resourcePolicyStoreCreate, + ReadWithoutTimeout: resourcePolicyStoreRead, + UpdateWithoutTimeout: resourcePolicyStoreUpdate, + DeleteWithoutTimeout: resourcePolicyStoreDelete, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + Schema: map[string]*schema.Schema{ + "policy_store_id": { + Type: schema.TypeString, + Computed: true, + }, + "arn": { + Type: schema.TypeString, + Computed: true, + }, + "created_date": { + Type: schema.TypeString, + Computed: true, + }, + "last_updated_date": { + Type: schema.TypeString, + Computed: true, + }, + "validation_settings": { + Type: schema.TypeList, + Required: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "mode": { + Type: schema.TypeString, + ValidateDiagFunc: enum.Validate[types.ValidationMode](), + Required: true, + }, + }, + }, + }, + "schema": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "cedar_json": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringIsJSON, + StateFunc: func(v interface{}) string { + json, _ := structure.NormalizeJsonString(v) + return json + }, + DiffSuppressFunc: verify.SuppressEquivalentJSONDiffs, + }, + }, + }, + }, + "schema_created_date": { + Type: schema.TypeString, + Computed: true, + }, + "schema_last_updated_date": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +const ( + ResNamePolicyStore = "Policy Store" + ResNamePolicyStoreSchema = "Policy Store Schema" +) + +func resourcePolicyStoreCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics + + conn := meta.(*conns.AWSClient).VerifiedPermissionsClient(ctx) + + in := &verifiedpermissions.CreatePolicyStoreInput{ + ClientToken: aws.String(id.UniqueId()), + ValidationSettings: expandValidationSettingsSlice(d.Get("validation_settings").([]interface{})), + } + + out, err := conn.CreatePolicyStore(ctx, in) + if err != nil { + return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionCreating, ResNamePolicyStore, "", err)...) + } + + if out == nil || out.PolicyStoreId == nil { + return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionCreating, ResNamePolicyStore, "", errors.New("empty output"))...) + } + + policyStoreId := aws.ToString(out.PolicyStoreId) + d.SetId(policyStoreId) + + cedarJson := expandDefinitions(d.Get("schema").([]interface{})) + inSchema := &verifiedpermissions.PutSchemaInput{ + Definition: cedarJson, + PolicyStoreId: &policyStoreId, + } + + _, err = conn.PutSchema(ctx, inSchema) + if err != nil { + return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionCreating, ResNamePolicyStoreSchema, "", err)...) + } + + return append(diags, resourcePolicyStoreRead(ctx, d, meta)...) +} + +func resourcePolicyStoreRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics + + conn := meta.(*conns.AWSClient).VerifiedPermissionsClient(ctx) + + out, err := findPolicyStoreByID(ctx, conn, d.Id()) + if !d.IsNewResource() && tfresource.NotFound(err) { + log.Printf("[WARN] VerifiedPermissions PolicyStore (%s) not found, removing from state", d.Id()) + d.SetId("") + return diags + } + + if err != nil { + return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionReading, ResNamePolicyStore, d.Id(), err)...) + } + + d.Set("arn", out.Arn) + d.Set("policy_store_id", out.PolicyStoreId) + d.Set("created_date", out.CreatedDate.Format(time.RFC3339)) + d.Set("last_updated_date", out.LastUpdatedDate.Format(time.RFC3339)) + + if err := d.Set("validation_settings", flattenValidationSettingsSlice(out.ValidationSettings)); err != nil { + return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionSetting, ResNamePolicyStore, d.Id(), err)...) + } + + inSchema := &verifiedpermissions.GetSchemaInput{ + PolicyStoreId: out.PolicyStoreId, + } + outSchema, err := conn.GetSchema(ctx, inSchema) + if err != nil { + return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionReading, ResNamePolicyStoreSchema, *out.PolicyStoreId, err)...) + } + + d.Set("schema", flattenSchemaDefinitionSlice(outSchema.Schema)) + d.Set("schema_created_date", outSchema.CreatedDate.Format(time.RFC3339)) + d.Set("schema_last_updated_date", outSchema.LastUpdatedDate.Format(time.RFC3339)) + + return diags +} + +func resourcePolicyStoreUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics + + conn := meta.(*conns.AWSClient).VerifiedPermissionsClient(ctx) + + policyStoreID := aws.String(d.Id()) + update := false + + policyStoreIn := &verifiedpermissions.UpdatePolicyStoreInput{ + PolicyStoreId: policyStoreID, + } + + if d.HasChanges("validation_settings") { + policyStoreIn.ValidationSettings = expandValidationSettingsSlice(d.Get("validation_settings").([]interface{})) + update = true + } + + if update { + log.Printf("[DEBUG] Updating VerifiedPermissions PolicyStore (%s): %#v", d.Id(), policyStoreIn) + _, err := conn.UpdatePolicyStore(ctx, policyStoreIn) + if err != nil { + return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionUpdating, ResNamePolicyStore, d.Id(), err)...) + } + } + + var updateSchema bool + schemaIn := &verifiedpermissions.PutSchemaInput{ + PolicyStoreId: policyStoreID, + } + if d.HasChanges("schema") { + schemaIn.Definition = expandDefinitions(d.Get("schema").([]interface{})) + updateSchema = true + } + + if updateSchema { + log.Printf("[DEBUG] Updating VerifiedPermissions PolicyStore Schema (%s): %#v", d.Id(), policyStoreIn) + _, err := conn.PutSchema(ctx, schemaIn) + if err != nil { + return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionUpdating, ResNamePolicyStoreSchema, d.Id(), err)...) + } + } + + return append(diags, resourcePolicyStoreRead(ctx, d, meta)...) +} + +func resourcePolicyStoreDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics + + conn := meta.(*conns.AWSClient).VerifiedPermissionsClient(ctx) + + log.Printf("[INFO] Deleting VerifiedPermissions PolicyStore %s", d.Id()) + + _, err := conn.DeletePolicyStore(ctx, &verifiedpermissions.DeletePolicyStoreInput{ + PolicyStoreId: aws.String(d.Id()), + }) + + if errs.IsA[*types.ResourceNotFoundException](err) { + return diags + } + if err != nil { + return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionDeleting, ResNamePolicyStore, d.Id(), err)...) + } + + return diags +} + +func findPolicyStoreByID(ctx context.Context, conn *verifiedpermissions.Client, id string) (*verifiedpermissions.GetPolicyStoreOutput, error) { + in := &verifiedpermissions.GetPolicyStoreInput{ + PolicyStoreId: aws.String(id), + } + out, err := conn.GetPolicyStore(ctx, in) + if errs.IsA[*types.ResourceNotFoundException](err) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: in, + } + } + if err != nil { + return nil, err + } + + if out == nil || out.Arn == nil { + return nil, tfresource.NewEmptyResultError(in) + } + + return out, nil +} + +func flattenValidationSettings(apiObject *types.ValidationSettings) map[string]interface{} { + if apiObject == nil { + return nil + } + + m := make(map[string]interface{}) + + if v := apiObject.Mode; v != "" { + m["mode"] = string(v) + } + + return m +} + +func flattenValidationSettingsSlice(apiObject *types.ValidationSettings) []interface{} { + if apiObject == nil { + return nil + } + + return []interface{}{ + flattenValidationSettings(apiObject), + } +} + +func expandValidationSettingsSlice(list []interface{}) *types.ValidationSettings { + if len(list) == 0 { + return nil + } + tfMap := list[0].(map[string]interface{}) + + return expandValidationSettings(tfMap) +} + +func expandValidationSettings(tfMap map[string]interface{}) *types.ValidationSettings { + if tfMap == nil { + return nil + } + + var out types.ValidationSettings + + mode, ok := tfMap["mode"].(string) + if ok { + out.Mode = types.ValidationMode(mode) + } + + return &out +} + +func expandDefinition(tfMap map[string]interface{}) *types.SchemaDefinitionMemberCedarJson { + a := &types.SchemaDefinitionMemberCedarJson{ + Value: "{}", + } + + if v, ok := tfMap["cedar_json"].(string); ok && v != "" { + var err error + a.Value, err = structure.NormalizeJsonString(v) + if err != nil { + return a + } + } + + return a +} + +func expandDefinitions(tfList []interface{}) *types.SchemaDefinitionMemberCedarJson { + if len(tfList) == 0 { + return &types.SchemaDefinitionMemberCedarJson{ + Value: "{}", + } + } + + tfMap := tfList[0] + if tfMap == nil { + return &types.SchemaDefinitionMemberCedarJson{ + Value: "{}", + } + } + + return expandDefinition(tfMap.(map[string]interface{})) +} + +func flattenSchemaDefinitionSlice(definition *string) []interface{} { + def := flattenSchemaDefinition(definition) + if def == nil { + return nil + } + + return []interface{}{def} +} + +func flattenSchemaDefinition(definition *string) map[string]interface{} { + if definition == nil || aws.ToString(definition) == "{}" { + return nil + } + + specificationToSet, err := structure.NormalizeJsonString(aws.ToString(definition)) + if err != nil { + return nil + } + + return map[string]interface{}{ + "cedar_json": specificationToSet, + } +} diff --git a/internal/service/verifiedpermissions/policy_store_test.go b/internal/service/verifiedpermissions/policy_store_test.go new file mode 100644 index 00000000000..410caad3de7 --- /dev/null +++ b/internal/service/verifiedpermissions/policy_store_test.go @@ -0,0 +1,193 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package verifiedpermissions_test + +import ( + "context" + "errors" + "fmt" + "regexp" + "testing" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions" + "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions/types" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/errs" + tfverifiedpermissions "github.com/hashicorp/terraform-provider-aws/internal/service/verifiedpermissions" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func TestAccVerifiedPermissionsPolicyStore_basic(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var policystore verifiedpermissions.GetPolicyStoreOutput + resourceName := "aws_verifiedpermissions_policy_store.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.VerifiedPermissions) + testAccPolicyStoresPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.VerifiedPermissions), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckPolicyStoreDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccPolicyStoreConfig_basic("OFF"), + Check: resource.ComposeTestCheckFunc( + testAccCheckPolicyStoreExists(ctx, resourceName, &policystore), + resource.TestCheckResourceAttr(resourceName, "validation_settings.0.mode", "OFF"), + acctest.MatchResourceAttrGlobalARN(resourceName, "arn", "verifiedpermissions", regexp.MustCompile(`policy-store/+.`)), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccPolicyStoreConfig_basicWithSchema("STRICT", "{\"CHANGED\":{\"actions\":{},\"entityTypes\":{}}}"), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "validation_settings.0.mode", "STRICT"), + resource.TestCheckResourceAttr(resourceName, "schema.0.cedar_json", "{\"CHANGED\":{\"actions\":{},\"entityTypes\":{}}}"), + ), + }, + { + Config: testAccPolicyStoreConfig_basic("OFF"), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "validation_settings.0.mode", "OFF"), + resource.TestCheckNoResourceAttr(resourceName, "schema.0.cedar_json"), + ), + }, + }, + }) +} + +func TestAccVerifiedPermissionsPolicyStore_disappears(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var policystore verifiedpermissions.GetPolicyStoreOutput + resourceName := "aws_verifiedpermissions_policy_store.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.VerifiedPermissions) + testAccPolicyStoresPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.VerifiedPermissions), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckPolicyStoreDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccPolicyStoreConfig_basic("OFF"), + Check: resource.ComposeTestCheckFunc( + testAccCheckPolicyStoreExists(ctx, resourceName, &policystore), + acctest.CheckResourceDisappears(ctx, acctest.Provider, tfverifiedpermissions.ResourcePolicyStore(), resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccCheckPolicyStoreDestroy(ctx context.Context) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).VerifiedPermissionsClient(ctx) + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_verifiedpermissions_policy_store" { + continue + } + + input := &verifiedpermissions.GetPolicyStoreInput{ + PolicyStoreId: aws.String(rs.Primary.ID), + } + _, err := conn.GetPolicyStore(ctx, input) + if errs.IsA[*types.ResourceNotFoundException](err) { + return nil + } + if err != nil { + return err + } + + return create.Error(names.VerifiedPermissions, create.ErrActionCheckingDestroyed, tfverifiedpermissions.ResNamePolicyStore, rs.Primary.ID, errors.New("not destroyed")) + } + + return nil + } +} + +func testAccCheckPolicyStoreExists(ctx context.Context, name string, policystore *verifiedpermissions.GetPolicyStoreOutput) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[name] + if !ok { + return create.Error(names.VerifiedPermissions, create.ErrActionCheckingExistence, tfverifiedpermissions.ResNamePolicyStore, name, errors.New("not found")) + } + + if rs.Primary.ID == "" { + return create.Error(names.VerifiedPermissions, create.ErrActionCheckingExistence, tfverifiedpermissions.ResNamePolicyStore, name, errors.New("not set")) + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).VerifiedPermissionsClient(ctx) + resp, err := conn.GetPolicyStore(ctx, &verifiedpermissions.GetPolicyStoreInput{ + PolicyStoreId: aws.String(rs.Primary.ID), + }) + + if err != nil { + return create.Error(names.VerifiedPermissions, create.ErrActionCheckingExistence, tfverifiedpermissions.ResNamePolicyStore, rs.Primary.ID, err) + } + + *policystore = *resp + + return nil + } +} + +func testAccPolicyStoresPreCheck(ctx context.Context, t *testing.T) { + conn := acctest.Provider.Meta().(*conns.AWSClient).VerifiedPermissionsClient(ctx) + + input := &verifiedpermissions.ListPolicyStoresInput{} + _, err := conn.ListPolicyStores(ctx, input) + + if acctest.PreCheckSkipError(err) { + t.Skipf("skipping acceptance testing: %s", err) + } + if err != nil { + t.Fatalf("unexpected PreCheck error: %s", err) + } +} + +func testAccPolicyStoreConfig_basic(mode string) string { + return fmt.Sprintf(` +resource "aws_verifiedpermissions_policy_store" "test" { + validation_settings { + mode = %[1]q + } +}`, mode) +} + +func testAccPolicyStoreConfig_basicWithSchema(mode, schema string) string { + return fmt.Sprintf(` +resource "aws_verifiedpermissions_policy_store" "test" { + validation_settings { + mode = %[1]q + } + schema { + cedar_json = %[2]q + } +}`, mode, schema) +} diff --git a/internal/service/verifiedpermissions/service_package_gen.go b/internal/service/verifiedpermissions/service_package_gen.go index 7cd0659dfcf..8515063768b 100644 --- a/internal/service/verifiedpermissions/service_package_gen.go +++ b/internal/service/verifiedpermissions/service_package_gen.go @@ -27,7 +27,13 @@ func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePac } func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePackageSDKResource { - return []*types.ServicePackageSDKResource{} + return []*types.ServicePackageSDKResource{ + { + Factory: ResourcePolicyStore, + TypeName: "aws_verifiedpermissions_policy_store", + Name: "Policy Store", + }, + } } func (p *servicePackage) ServicePackageName() string { diff --git a/website/docs/r/verifiedpermissions_policy_store.html.markdown b/website/docs/r/verifiedpermissions_policy_store.html.markdown new file mode 100644 index 00000000000..2f3acab69f5 --- /dev/null +++ b/website/docs/r/verifiedpermissions_policy_store.html.markdown @@ -0,0 +1,68 @@ +--- +subcategory: "Verified Permissions" +layout: "aws" +page_title: "AWS: aws_verifiedpermissions_policy_store" +description: |- + This is a Terraform resource for managing an AWS Verified Permissions Policy Store. +--- + +# Resource: aws_verifiedpermissions_policy_store + +This is a Terraform resource for managing an AWS Verified Permissions Policy Store. + +## Example Usage + +### Basic Usage + +```terraform +resource "aws_verifiedpermissions_policy_store" "example" { + validation_settings { + mode = "STRICT" + } + + schema { + cedar_json = jsonencode({ + "Namespace" : { + "entityTypes" : {}, + "actions" : {} + } + }) + } +} +``` + +## Argument Reference + +The following arguments are required: + +* `validation_settings` - (Required) Validation settings for the policy store. + * `mode` - (Required) The mode for the validation settings. Valid values: `OFF`, `STRICT`. +* `schema` - (Required) Schema for the policy store. + * `cedar_json` - (Required) The cedar json schema. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `policy_store_id` - The ID of the Policy Store. +* `arn` - The ARN of the Policy Store. +* `created_date` - The date the Policy Store was created. +* `last_updated_date` - The date the Policy Store was last updated. +* `schema_created_date` - The date the Policy Store Schema was created. +* `schema_last_updated_date` - The date the Policy Store Schema was last updated. + +## Timeouts + +[Configuration options](https://developer.hashicorp.com/terraform/language/resources/syntax#operation-timeouts): + +* `create` - (Default `30m`) +* `update` - (Default `30m`) +* `delete` - (Default `30m`) + +## Import + +Verified Permissions Policy Store can be imported using the policy_store_id, e.g., + +``` +$ terraform import aws_verifiedpermissions_policy_store.example DxQg2j8xvXJQ1tQCYNWj9T +``` From 17dc532e4709c4057738ad9775afe70e33c17d94 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Thu, 4 Jan 2024 17:07:14 -0600 Subject: [PATCH 02/14] aws_verifiedpermissions_policy_store: SDKv2 -> Framework --- .../verifiedpermissions/exports_test.go | 11 + .../verifiedpermissions/policy_store.go | 720 +++++++++--------- .../verifiedpermissions/policy_store_fw.go | 305 ++++++++ .../verifiedpermissions/policy_store_test.go | 69 +- .../service_package_gen.go | 15 +- 5 files changed, 707 insertions(+), 413 deletions(-) create mode 100644 internal/service/verifiedpermissions/exports_test.go create mode 100644 internal/service/verifiedpermissions/policy_store_fw.go diff --git a/internal/service/verifiedpermissions/exports_test.go b/internal/service/verifiedpermissions/exports_test.go new file mode 100644 index 00000000000..9a722e6e9f2 --- /dev/null +++ b/internal/service/verifiedpermissions/exports_test.go @@ -0,0 +1,11 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package verifiedpermissions + +// Exports for use in tests only. +var ( + ResourcePolicyStore = newResourcePolicyStore + + FindPolicyStoreByID = findPolicyStoreByID +) diff --git a/internal/service/verifiedpermissions/policy_store.go b/internal/service/verifiedpermissions/policy_store.go index 351d750c3a6..b06aee6d581 100644 --- a/internal/service/verifiedpermissions/policy_store.go +++ b/internal/service/verifiedpermissions/policy_store.go @@ -3,377 +3,349 @@ package verifiedpermissions -import ( - "context" - "errors" - "log" - "time" - - "github.com/aws/aws-sdk-go-v2/aws" - "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions" - "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions/types" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" - "github.com/hashicorp/terraform-provider-aws/internal/conns" - "github.com/hashicorp/terraform-provider-aws/internal/create" - "github.com/hashicorp/terraform-provider-aws/internal/enum" - "github.com/hashicorp/terraform-provider-aws/internal/errs" - "github.com/hashicorp/terraform-provider-aws/internal/tfresource" - "github.com/hashicorp/terraform-provider-aws/internal/verify" - "github.com/hashicorp/terraform-provider-aws/names" -) - -// @SDKResource("aws_verifiedpermissions_policy_store", name="Policy Store") -func ResourcePolicyStore() *schema.Resource { - return &schema.Resource{ - CreateWithoutTimeout: resourcePolicyStoreCreate, - ReadWithoutTimeout: resourcePolicyStoreRead, - UpdateWithoutTimeout: resourcePolicyStoreUpdate, - DeleteWithoutTimeout: resourcePolicyStoreDelete, - Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(30 * time.Minute), - Update: schema.DefaultTimeout(30 * time.Minute), - Delete: schema.DefaultTimeout(30 * time.Minute), - }, - Importer: &schema.ResourceImporter{ - StateContext: schema.ImportStatePassthroughContext, - }, - Schema: map[string]*schema.Schema{ - "policy_store_id": { - Type: schema.TypeString, - Computed: true, - }, - "arn": { - Type: schema.TypeString, - Computed: true, - }, - "created_date": { - Type: schema.TypeString, - Computed: true, - }, - "last_updated_date": { - Type: schema.TypeString, - Computed: true, - }, - "validation_settings": { - Type: schema.TypeList, - Required: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "mode": { - Type: schema.TypeString, - ValidateDiagFunc: enum.Validate[types.ValidationMode](), - Required: true, - }, - }, - }, - }, - "schema": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "cedar_json": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringIsJSON, - StateFunc: func(v interface{}) string { - json, _ := structure.NormalizeJsonString(v) - return json - }, - DiffSuppressFunc: verify.SuppressEquivalentJSONDiffs, - }, - }, - }, - }, - "schema_created_date": { - Type: schema.TypeString, - Computed: true, - }, - "schema_last_updated_date": { - Type: schema.TypeString, - Computed: true, - }, - }, - } -} - -const ( - ResNamePolicyStore = "Policy Store" - ResNamePolicyStoreSchema = "Policy Store Schema" -) - -func resourcePolicyStoreCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - var diags diag.Diagnostics - - conn := meta.(*conns.AWSClient).VerifiedPermissionsClient(ctx) - - in := &verifiedpermissions.CreatePolicyStoreInput{ - ClientToken: aws.String(id.UniqueId()), - ValidationSettings: expandValidationSettingsSlice(d.Get("validation_settings").([]interface{})), - } - - out, err := conn.CreatePolicyStore(ctx, in) - if err != nil { - return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionCreating, ResNamePolicyStore, "", err)...) - } - - if out == nil || out.PolicyStoreId == nil { - return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionCreating, ResNamePolicyStore, "", errors.New("empty output"))...) - } - - policyStoreId := aws.ToString(out.PolicyStoreId) - d.SetId(policyStoreId) - - cedarJson := expandDefinitions(d.Get("schema").([]interface{})) - inSchema := &verifiedpermissions.PutSchemaInput{ - Definition: cedarJson, - PolicyStoreId: &policyStoreId, - } - - _, err = conn.PutSchema(ctx, inSchema) - if err != nil { - return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionCreating, ResNamePolicyStoreSchema, "", err)...) - } - - return append(diags, resourcePolicyStoreRead(ctx, d, meta)...) -} - -func resourcePolicyStoreRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - var diags diag.Diagnostics - - conn := meta.(*conns.AWSClient).VerifiedPermissionsClient(ctx) - - out, err := findPolicyStoreByID(ctx, conn, d.Id()) - if !d.IsNewResource() && tfresource.NotFound(err) { - log.Printf("[WARN] VerifiedPermissions PolicyStore (%s) not found, removing from state", d.Id()) - d.SetId("") - return diags - } - - if err != nil { - return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionReading, ResNamePolicyStore, d.Id(), err)...) - } - - d.Set("arn", out.Arn) - d.Set("policy_store_id", out.PolicyStoreId) - d.Set("created_date", out.CreatedDate.Format(time.RFC3339)) - d.Set("last_updated_date", out.LastUpdatedDate.Format(time.RFC3339)) - - if err := d.Set("validation_settings", flattenValidationSettingsSlice(out.ValidationSettings)); err != nil { - return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionSetting, ResNamePolicyStore, d.Id(), err)...) - } - - inSchema := &verifiedpermissions.GetSchemaInput{ - PolicyStoreId: out.PolicyStoreId, - } - outSchema, err := conn.GetSchema(ctx, inSchema) - if err != nil { - return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionReading, ResNamePolicyStoreSchema, *out.PolicyStoreId, err)...) - } - - d.Set("schema", flattenSchemaDefinitionSlice(outSchema.Schema)) - d.Set("schema_created_date", outSchema.CreatedDate.Format(time.RFC3339)) - d.Set("schema_last_updated_date", outSchema.LastUpdatedDate.Format(time.RFC3339)) - - return diags -} - -func resourcePolicyStoreUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - var diags diag.Diagnostics - - conn := meta.(*conns.AWSClient).VerifiedPermissionsClient(ctx) - - policyStoreID := aws.String(d.Id()) - update := false - - policyStoreIn := &verifiedpermissions.UpdatePolicyStoreInput{ - PolicyStoreId: policyStoreID, - } - - if d.HasChanges("validation_settings") { - policyStoreIn.ValidationSettings = expandValidationSettingsSlice(d.Get("validation_settings").([]interface{})) - update = true - } - - if update { - log.Printf("[DEBUG] Updating VerifiedPermissions PolicyStore (%s): %#v", d.Id(), policyStoreIn) - _, err := conn.UpdatePolicyStore(ctx, policyStoreIn) - if err != nil { - return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionUpdating, ResNamePolicyStore, d.Id(), err)...) - } - } - - var updateSchema bool - schemaIn := &verifiedpermissions.PutSchemaInput{ - PolicyStoreId: policyStoreID, - } - if d.HasChanges("schema") { - schemaIn.Definition = expandDefinitions(d.Get("schema").([]interface{})) - updateSchema = true - } - - if updateSchema { - log.Printf("[DEBUG] Updating VerifiedPermissions PolicyStore Schema (%s): %#v", d.Id(), policyStoreIn) - _, err := conn.PutSchema(ctx, schemaIn) - if err != nil { - return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionUpdating, ResNamePolicyStoreSchema, d.Id(), err)...) - } - } - - return append(diags, resourcePolicyStoreRead(ctx, d, meta)...) -} - -func resourcePolicyStoreDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - var diags diag.Diagnostics - - conn := meta.(*conns.AWSClient).VerifiedPermissionsClient(ctx) - - log.Printf("[INFO] Deleting VerifiedPermissions PolicyStore %s", d.Id()) - - _, err := conn.DeletePolicyStore(ctx, &verifiedpermissions.DeletePolicyStoreInput{ - PolicyStoreId: aws.String(d.Id()), - }) - - if errs.IsA[*types.ResourceNotFoundException](err) { - return diags - } - if err != nil { - return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionDeleting, ResNamePolicyStore, d.Id(), err)...) - } - - return diags -} - -func findPolicyStoreByID(ctx context.Context, conn *verifiedpermissions.Client, id string) (*verifiedpermissions.GetPolicyStoreOutput, error) { - in := &verifiedpermissions.GetPolicyStoreInput{ - PolicyStoreId: aws.String(id), - } - out, err := conn.GetPolicyStore(ctx, in) - if errs.IsA[*types.ResourceNotFoundException](err) { - return nil, &retry.NotFoundError{ - LastError: err, - LastRequest: in, - } - } - if err != nil { - return nil, err - } - - if out == nil || out.Arn == nil { - return nil, tfresource.NewEmptyResultError(in) - } - - return out, nil -} - -func flattenValidationSettings(apiObject *types.ValidationSettings) map[string]interface{} { - if apiObject == nil { - return nil - } - - m := make(map[string]interface{}) - - if v := apiObject.Mode; v != "" { - m["mode"] = string(v) - } - - return m -} - -func flattenValidationSettingsSlice(apiObject *types.ValidationSettings) []interface{} { - if apiObject == nil { - return nil - } - - return []interface{}{ - flattenValidationSettings(apiObject), - } -} - -func expandValidationSettingsSlice(list []interface{}) *types.ValidationSettings { - if len(list) == 0 { - return nil - } - tfMap := list[0].(map[string]interface{}) - - return expandValidationSettings(tfMap) -} - -func expandValidationSettings(tfMap map[string]interface{}) *types.ValidationSettings { - if tfMap == nil { - return nil - } - - var out types.ValidationSettings - - mode, ok := tfMap["mode"].(string) - if ok { - out.Mode = types.ValidationMode(mode) - } - - return &out -} - -func expandDefinition(tfMap map[string]interface{}) *types.SchemaDefinitionMemberCedarJson { - a := &types.SchemaDefinitionMemberCedarJson{ - Value: "{}", - } - - if v, ok := tfMap["cedar_json"].(string); ok && v != "" { - var err error - a.Value, err = structure.NormalizeJsonString(v) - if err != nil { - return a - } - } - - return a -} - -func expandDefinitions(tfList []interface{}) *types.SchemaDefinitionMemberCedarJson { - if len(tfList) == 0 { - return &types.SchemaDefinitionMemberCedarJson{ - Value: "{}", - } - } - - tfMap := tfList[0] - if tfMap == nil { - return &types.SchemaDefinitionMemberCedarJson{ - Value: "{}", - } - } - - return expandDefinition(tfMap.(map[string]interface{})) -} - -func flattenSchemaDefinitionSlice(definition *string) []interface{} { - def := flattenSchemaDefinition(definition) - if def == nil { - return nil - } - - return []interface{}{def} -} - -func flattenSchemaDefinition(definition *string) map[string]interface{} { - if definition == nil || aws.ToString(definition) == "{}" { - return nil - } - - specificationToSet, err := structure.NormalizeJsonString(aws.ToString(definition)) - if err != nil { - return nil - } - - return map[string]interface{}{ - "cedar_json": specificationToSet, - } -} +//import ( +// "context" +// "errors" +// "log" +// "time" +// +// "github.com/aws/aws-sdk-go-v2/aws" +// "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions" +// "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions/types" +// "github.com/hashicorp/terraform-plugin-sdk/v2/diag" +// "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" +// "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +// "github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure" +// "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +// "github.com/hashicorp/terraform-provider-aws/internal/conns" +// "github.com/hashicorp/terraform-provider-aws/internal/create" +// "github.com/hashicorp/terraform-provider-aws/internal/enum" +// "github.com/hashicorp/terraform-provider-aws/internal/errs" +// "github.com/hashicorp/terraform-provider-aws/internal/tfresource" +// "github.com/hashicorp/terraform-provider-aws/internal/verify" +// "github.com/hashicorp/terraform-provider-aws/names" +//) +// +//// @SDKResource("aws_verifiedpermissions_policy_store", name="Policy Store") +//func ResourcePolicyStore() *schema.Resource { +// return &schema.Resource{ +// CreateWithoutTimeout: resourcePolicyStoreCreate, +// ReadWithoutTimeout: resourcePolicyStoreRead, +// UpdateWithoutTimeout: resourcePolicyStoreUpdate, +// DeleteWithoutTimeout: resourcePolicyStoreDelete, +// Timeouts: &schema.ResourceTimeout{ +// Create: schema.DefaultTimeout(30 * time.Minute), +// Update: schema.DefaultTimeout(30 * time.Minute), +// Delete: schema.DefaultTimeout(30 * time.Minute), +// }, +// Importer: &schema.ResourceImporter{ +// StateContext: schema.ImportStatePassthroughContext, +// }, +// Schema: map[string]*schema.Schema{ +// "policy_store_id": { +// Type: schema.TypeString, +// Computed: true, +// }, +// "arn": { +// Type: schema.TypeString, +// Computed: true, +// }, +// "created_date": { +// Type: schema.TypeString, +// Computed: true, +// }, +// "last_updated_date": { +// Type: schema.TypeString, +// Computed: true, +// }, +// "validation_settings": { +// Type: schema.TypeList, +// Required: true, +// MaxItems: 1, +// Elem: &schema.Resource{ +// Schema: map[string]*schema.Schema{ +// "mode": { +// Type: schema.TypeString, +// ValidateDiagFunc: enum.Validate[types.ValidationMode](), +// Required: true, +// }, +// }, +// }, +// }, +// "schema": { +// Type: schema.TypeList, +// Optional: true, +// MaxItems: 1, +// Elem: &schema.Resource{ +// Schema: map[string]*schema.Schema{ +// "cedar_json": { +// Type: schema.TypeString, +// Required: true, +// ValidateFunc: validation.StringIsJSON, +// StateFunc: func(v interface{}) string { +// json, _ := structure.NormalizeJsonString(v) +// return json +// }, +// DiffSuppressFunc: verify.SuppressEquivalentJSONDiffs, +// }, +// }, +// }, +// }, +// "schema_created_date": { +// Type: schema.TypeString, +// Computed: true, +// }, +// "schema_last_updated_date": { +// Type: schema.TypeString, +// Computed: true, +// }, +// }, +// } +//} +// +//func resourcePolicyStoreCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { +// var diags diag.Diagnostics +// +// conn := meta.(*conns.AWSClient).VerifiedPermissionsClient(ctx) +// +// in := &verifiedpermissions.CreatePolicyStoreInput{ +// ClientToken: aws.String(id.UniqueId()), +// ValidationSettings: expandValidationSettingsSlice(d.Get("validation_settings").([]interface{})), +// } +// +// out, err := conn.CreatePolicyStore(ctx, in) +// if err != nil { +// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionCreating, ResNamePolicyStore, "", err)...) +// } +// +// if out == nil || out.PolicyStoreId == nil { +// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionCreating, ResNamePolicyStore, "", errors.New("empty output"))...) +// } +// +// policyStoreId := aws.ToString(out.PolicyStoreId) +// d.SetId(policyStoreId) +// +// cedarJson := expandDefinitions(d.Get("schema").([]interface{})) +// inSchema := &verifiedpermissions.PutSchemaInput{ +// Definition: cedarJson, +// PolicyStoreId: &policyStoreId, +// } +// +// _, err = conn.PutSchema(ctx, inSchema) +// if err != nil { +// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionCreating, ResNamePolicyStoreSchema, "", err)...) +// } +// +// return append(diags, resourcePolicyStoreRead(ctx, d, meta)...) +//} +// +//func resourcePolicyStoreRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { +// var diags diag.Diagnostics +// +// conn := meta.(*conns.AWSClient).VerifiedPermissionsClient(ctx) +// +// out, err := findPolicyStoreByID(ctx, conn, d.Id()) +// if !d.IsNewResource() && tfresource.NotFound(err) { +// log.Printf("[WARN] VerifiedPermissions PolicyStore (%s) not found, removing from state", d.Id()) +// d.SetId("") +// return diags +// } +// +// if err != nil { +// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionReading, ResNamePolicyStore, d.Id(), err)...) +// } +// +// d.Set("arn", out.Arn) +// d.Set("policy_store_id", out.PolicyStoreId) +// d.Set("created_date", out.CreatedDate.Format(time.RFC3339)) +// d.Set("last_updated_date", out.LastUpdatedDate.Format(time.RFC3339)) +// +// if err := d.Set("validation_settings", flattenValidationSettingsSlice(out.ValidationSettings)); err != nil { +// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionSetting, ResNamePolicyStore, d.Id(), err)...) +// } +// +// inSchema := &verifiedpermissions.GetSchemaInput{ +// PolicyStoreId: out.PolicyStoreId, +// } +// outSchema, err := conn.GetSchema(ctx, inSchema) +// if err != nil { +// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionReading, ResNamePolicyStoreSchema, *out.PolicyStoreId, err)...) +// } +// +// d.Set("schema", flattenSchemaDefinitionSlice(outSchema.Schema)) +// d.Set("schema_created_date", outSchema.CreatedDate.Format(time.RFC3339)) +// d.Set("schema_last_updated_date", outSchema.LastUpdatedDate.Format(time.RFC3339)) +// +// return diags +//} +// +//func resourcePolicyStoreUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { +// var diags diag.Diagnostics +// +// conn := meta.(*conns.AWSClient).VerifiedPermissionsClient(ctx) +// +// policyStoreID := aws.String(d.Id()) +// update := false +// +// policyStoreIn := &verifiedpermissions.UpdatePolicyStoreInput{ +// PolicyStoreId: policyStoreID, +// } +// +// if d.HasChanges("validation_settings") { +// policyStoreIn.ValidationSettings = expandValidationSettingsSlice(d.Get("validation_settings").([]interface{})) +// update = true +// } +// +// if update { +// log.Printf("[DEBUG] Updating VerifiedPermissions PolicyStore (%s): %#v", d.Id(), policyStoreIn) +// _, err := conn.UpdatePolicyStore(ctx, policyStoreIn) +// if err != nil { +// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionUpdating, ResNamePolicyStore, d.Id(), err)...) +// } +// } +// +// var updateSchema bool +// schemaIn := &verifiedpermissions.PutSchemaInput{ +// PolicyStoreId: policyStoreID, +// } +// if d.HasChanges("schema") { +// schemaIn.Definition = expandDefinitions(d.Get("schema").([]interface{})) +// updateSchema = true +// } +// +// if updateSchema { +// log.Printf("[DEBUG] Updating VerifiedPermissions PolicyStore Schema (%s): %#v", d.Id(), policyStoreIn) +// _, err := conn.PutSchema(ctx, schemaIn) +// if err != nil { +// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionUpdating, ResNamePolicyStoreSchema, d.Id(), err)...) +// } +// } +// +// return append(diags, resourcePolicyStoreRead(ctx, d, meta)...) +//} +// +//func resourcePolicyStoreDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { +// var diags diag.Diagnostics +// +// conn := meta.(*conns.AWSClient).VerifiedPermissionsClient(ctx) +// +// log.Printf("[INFO] Deleting VerifiedPermissions PolicyStore %s", d.Id()) +// +// _, err := conn.DeletePolicyStore(ctx, &verifiedpermissions.DeletePolicyStoreInput{ +// PolicyStoreId: aws.String(d.Id()), +// }) +// +// if errs.IsA[*types.ResourceNotFoundException](err) { +// return diags +// } +// if err != nil { +// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionDeleting, ResNamePolicyStore, d.Id(), err)...) +// } +// +// return diags +//} +// +//func flattenValidationSettings(apiObject *types.ValidationSettings) map[string]interface{} { +// if apiObject == nil { +// return nil +// } +// +// m := make(map[string]interface{}) +// +// if v := apiObject.Mode; v != "" { +// m["mode"] = string(v) +// } +// +// return m +//} +// +//func flattenValidationSettingsSlice(apiObject *types.ValidationSettings) []interface{} { +// if apiObject == nil { +// return nil +// } +// +// return []interface{}{ +// flattenValidationSettings(apiObject), +// } +//} +// +//func expandValidationSettingsSlice(list []interface{}) *types.ValidationSettings { +// if len(list) == 0 { +// return nil +// } +// tfMap := list[0].(map[string]interface{}) +// +// return expandValidationSettings(tfMap) +//} +// +//func expandValidationSettings(tfMap map[string]interface{}) *types.ValidationSettings { +// if tfMap == nil { +// return nil +// } +// +// var out types.ValidationSettings +// +// mode, ok := tfMap["mode"].(string) +// if ok { +// out.Mode = types.ValidationMode(mode) +// } +// +// return &out +//} +// +//func expandDefinition(tfMap map[string]interface{}) *types.SchemaDefinitionMemberCedarJson { +// a := &types.SchemaDefinitionMemberCedarJson{ +// Value: "{}", +// } +// +// if v, ok := tfMap["cedar_json"].(string); ok && v != "" { +// var err error +// a.Value, err = structure.NormalizeJsonString(v) +// if err != nil { +// return a +// } +// } +// +// return a +//} +// +//func expandDefinitions(tfList []interface{}) *types.SchemaDefinitionMemberCedarJson { +// if len(tfList) == 0 { +// return &types.SchemaDefinitionMemberCedarJson{ +// Value: "{}", +// } +// } +// +// tfMap := tfList[0] +// if tfMap == nil { +// return &types.SchemaDefinitionMemberCedarJson{ +// Value: "{}", +// } +// } +// +// return expandDefinition(tfMap.(map[string]interface{})) +//} +// +//func flattenSchemaDefinitionSlice(definition *string) []interface{} { +// def := flattenSchemaDefinition(definition) +// if def == nil { +// return nil +// } +// +// return []interface{}{def} +//} +// +//func flattenSchemaDefinition(definition *string) map[string]interface{} { +// if definition == nil || aws.ToString(definition) == "{}" { +// return nil +// } +// +// specificationToSet, err := structure.NormalizeJsonString(aws.ToString(definition)) +// if err != nil { +// return nil +// } +// +// return map[string]interface{}{ +// "cedar_json": specificationToSet, +// } +//} diff --git a/internal/service/verifiedpermissions/policy_store_fw.go b/internal/service/verifiedpermissions/policy_store_fw.go new file mode 100644 index 00000000000..2dee84d8e83 --- /dev/null +++ b/internal/service/verifiedpermissions/policy_store_fw.go @@ -0,0 +1,305 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package verifiedpermissions + +import ( + "context" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions" + awstypes "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions/types" + "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" + "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/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" + "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/errs" + "github.com/hashicorp/terraform-provider-aws/internal/framework" + "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" + fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" +) + +// @FrameworkResource(name="Policy Store") +func newResourcePolicyStore(context.Context) (resource.ResourceWithConfigure, error) { + r := &resourcePolicyStore{} + //r.SetDefaultCreateTimeout(30 * time.Minute) + //r.SetDefaultUpdateTimeout(30 * time.Minute) + //r.SetDefaultDeleteTimeout(30 * time.Minute) + + return r, nil +} + +const ( + ResNamePolicyStore = "Policy Store" + ResNamePolicyStoreSchema = "Policy Store Schema" +) + +type resourcePolicyStore struct { + framework.ResourceWithConfigure + // framework.WithTimeouts +} + +func (r *resourcePolicyStore) Metadata(_ context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) { + response.TypeName = "aws_verifiedpermissions_policy_store" +} + +// Schema returns the schema for this resource. +func (r *resourcePolicyStore) Schema(ctx context.Context, request resource.SchemaRequest, response *resource.SchemaResponse) { + s := schema.Schema{ + Attributes: map[string]schema.Attribute{ + "arn": framework.ARNAttributeComputedOnly(), + "description": schema.StringAttribute{ + Optional: true, + }, + "id": framework.IDAttribute(), + "policy_store_id": schema.StringAttribute{ + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, + }, + Blocks: map[string]schema.Block{ + //"schema": schema.ListNestedBlock{ + // CustomType: fwtypes.NewListNestedObjectTypeOf[schemaData](ctx), + // Validators: []validator.List{ + // listvalidator.SizeAtMost(1), + // }, + // NestedObject: schema.NestedBlockObject{ + // Attributes: map[string]schema.Attribute{ + // "cedar_json": schema.StringAttribute{ + // Required: true, + // Validators: []validator.String{ + // fwvalidators.JSON(), + // }, + // }, + // }, + // }, + //}, + "validation_settings": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[validationSettings](ctx), + Validators: []validator.List{ + listvalidator.IsRequired(), + listvalidator.SizeAtMost(1), + }, + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "mode": schema.StringAttribute{ + CustomType: fwtypes.StringEnumType[awstypes.ValidationMode](), + Required: true, + }, + }, + }, + }, + }, + } + + //if s.Blocks == nil { + // s.Blocks = make(map[string]schema.Block) + //} + //s.Blocks["timeouts"] = timeouts.Block(ctx, timeouts.Opts{ + // Create: true, + // Update: true, + // Delete: true, + //}) + + response.Schema = s +} + +func (r *resourcePolicyStore) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) { + conn := r.Meta().VerifiedPermissionsClient(ctx) + var plan resourcePolicyStoreData + + response.Diagnostics.Append(request.Plan.Get(ctx, &plan)...) + + if response.Diagnostics.HasError() { + return + } + + input := &verifiedpermissions.CreatePolicyStoreInput{} + response.Diagnostics.Append(flex.Expand(ctx, plan, input)...) + + if response.Diagnostics.HasError() { + return + } + + clientToken := id.UniqueId() + input.ClientToken = aws.String(clientToken) + + output, err := conn.CreatePolicyStore(ctx, input) + + if err != nil { + response.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionCreating, ResNamePolicyStore, clientToken, err), + err.Error(), + ) + return + } + + state := plan + state.ID = flex.StringToFramework(ctx, output.PolicyStoreId) + + response.Diagnostics.Append(flex.Flatten(ctx, output, &state)...) + + if response.Diagnostics.HasError() { + return + } + + response.Diagnostics.Append(response.State.Set(ctx, &state)...) +} + +func (r *resourcePolicyStore) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) { + conn := r.Meta().VerifiedPermissionsClient(ctx) + var state resourcePolicyStoreData + + response.Diagnostics.Append(request.State.Get(ctx, &state)...) + + if response.Diagnostics.HasError() { + return + } + + output, err := findPolicyStoreByID(ctx, conn, state.ID.ValueString()) + + if tfresource.NotFound(err) { + response.State.RemoveResource(ctx) + return + } + + if err != nil { + response.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionReading, ResNamePolicyStore, state.PolicyStoreID.ValueString(), err), + err.Error(), + ) + return + } + + response.Diagnostics.Append(flex.Flatten(ctx, output, &state)...) + + if response.Diagnostics.HasError() { + return + } + + response.Diagnostics.Append(response.State.Set(ctx, &state)...) +} + +func (r *resourcePolicyStore) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) { + conn := r.Meta().VerifiedPermissionsClient(ctx) + var state, plan resourcePolicyStoreData + + response.Diagnostics.Append(request.State.Get(ctx, &state)...) + + if response.Diagnostics.HasError() { + return + } + + response.Diagnostics.Append(request.Plan.Get(ctx, &plan)...) + + if response.Diagnostics.HasError() { + return + } + + if !plan.Description.Equal(state.Description) || !plan.ValidationSettings.Equal(state.ValidationSettings) { + input := &verifiedpermissions.UpdatePolicyStoreInput{} + response.Diagnostics.Append(flex.Expand(ctx, plan, input)...) + + if response.Diagnostics.HasError() { + return + } + + output, err := conn.UpdatePolicyStore(ctx, input) + + if err != nil { + response.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionUpdating, ResNamePolicyStore, state.PolicyStoreID.ValueString(), err), + err.Error(), + ) + return + } + + response.Diagnostics.Append(flex.Flatten(ctx, output, &plan)...) + } + + response.Diagnostics.Append(response.State.Set(ctx, &plan)...) +} + +func (r *resourcePolicyStore) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) { + conn := r.Meta().VerifiedPermissionsClient(ctx) + var state resourcePolicyStoreData + + response.Diagnostics.Append(request.State.Get(ctx, &state)...) + + if response.Diagnostics.HasError() { + return + } + + tflog.Debug(ctx, "deleting TODO", map[string]interface{}{ + "id": state.ID.ValueString(), + }) + + input := &verifiedpermissions.DeletePolicyStoreInput{ + PolicyStoreId: flex.StringFromFramework(ctx, state.ID), + } + + _, err := conn.DeletePolicyStore(ctx, input) + + if errs.IsA[*awstypes.ResourceNotFoundException](err) { + return + } + + if err != nil { + response.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionDeleting, ResNamePolicyStore, state.PolicyStoreID.ValueString(), err), + err.Error(), + ) + return + } +} + +func (r *resourcePolicyStore) ImportState(ctx context.Context, request resource.ImportStateRequest, response *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("id"), request, response) +} + +type resourcePolicyStoreData struct { + ARN types.String `tfsdk:"arn"` + Description types.String `tfsdk:"description"` + ID types.String `tfsdk:"id"` + PolicyStoreID types.String `tfsdk:"policy_store_id"` + ValidationSettings fwtypes.ListNestedObjectValueOf[validationSettings] `tfsdk:"validation_settings"` +} + +type validationSettings struct { + Mode fwtypes.StringEnum[awstypes.ValidationMode] `tfsdk:"mode"` +} + +func findPolicyStoreByID(ctx context.Context, conn *verifiedpermissions.Client, id string) (*verifiedpermissions.GetPolicyStoreOutput, error) { + in := &verifiedpermissions.GetPolicyStoreInput{ + PolicyStoreId: aws.String(id), + } + + out, err := conn.GetPolicyStore(ctx, in) + if errs.IsA[*awstypes.ResourceNotFoundException](err) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: in, + } + } + if err != nil { + return nil, err + } + + if out == nil || out.Arn == nil { + return nil, tfresource.NewEmptyResultError(in) + } + + return out, nil +} diff --git a/internal/service/verifiedpermissions/policy_store_test.go b/internal/service/verifiedpermissions/policy_store_test.go index 410caad3de7..110a8894219 100644 --- a/internal/service/verifiedpermissions/policy_store_test.go +++ b/internal/service/verifiedpermissions/policy_store_test.go @@ -10,16 +10,14 @@ import ( "regexp" "testing" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions" - "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions/types" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" "github.com/hashicorp/terraform-provider-aws/internal/acctest" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/create" - "github.com/hashicorp/terraform-provider-aws/internal/errs" tfverifiedpermissions "github.com/hashicorp/terraform-provider-aws/internal/service/verifiedpermissions" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/names" ) @@ -47,6 +45,7 @@ func TestAccVerifiedPermissionsPolicyStore_basic(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckPolicyStoreExists(ctx, resourceName, &policystore), resource.TestCheckResourceAttr(resourceName, "validation_settings.0.mode", "OFF"), + resource.TestCheckResourceAttr(resourceName, "description", "Terraform acceptance test"), acctest.MatchResourceAttrGlobalARN(resourceName, "arn", "verifiedpermissions", regexp.MustCompile(`policy-store/+.`)), ), }, @@ -55,18 +54,40 @@ func TestAccVerifiedPermissionsPolicyStore_basic(t *testing.T) { ImportState: true, ImportStateVerify: true, }, + }, + }) +} + +func TestAccVerifiedPermissionsPolicyStore_update(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var policystore verifiedpermissions.GetPolicyStoreOutput + resourceName := "aws_verifiedpermissions_policy_store.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.VerifiedPermissions) + testAccPolicyStoresPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.VerifiedPermissions), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckPolicyStoreDestroy(ctx), + Steps: []resource.TestStep{ { - Config: testAccPolicyStoreConfig_basicWithSchema("STRICT", "{\"CHANGED\":{\"actions\":{},\"entityTypes\":{}}}"), + Config: testAccPolicyStoreConfig_basic("OFF"), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "validation_settings.0.mode", "STRICT"), - resource.TestCheckResourceAttr(resourceName, "schema.0.cedar_json", "{\"CHANGED\":{\"actions\":{},\"entityTypes\":{}}}"), + testAccCheckPolicyStoreExists(ctx, resourceName, &policystore), + resource.TestCheckResourceAttr(resourceName, "validation_settings.0.mode", "OFF"), ), }, { - Config: testAccPolicyStoreConfig_basic("OFF"), + Config: testAccPolicyStoreConfig_basic("STRICT"), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "validation_settings.0.mode", "OFF"), - resource.TestCheckNoResourceAttr(resourceName, "schema.0.cedar_json"), + resource.TestCheckResourceAttr(resourceName, "validation_settings.0.mode", "STRICT"), ), }, }, @@ -96,7 +117,7 @@ func TestAccVerifiedPermissionsPolicyStore_disappears(t *testing.T) { Config: testAccPolicyStoreConfig_basic("OFF"), Check: resource.ComposeTestCheckFunc( testAccCheckPolicyStoreExists(ctx, resourceName, &policystore), - acctest.CheckResourceDisappears(ctx, acctest.Provider, tfverifiedpermissions.ResourcePolicyStore(), resourceName), + acctest.CheckFrameworkResourceDisappears(ctx, acctest.Provider, tfverifiedpermissions.ResourcePolicyStore, resourceName), ), ExpectNonEmptyPlan: true, }, @@ -113,13 +134,12 @@ func testAccCheckPolicyStoreDestroy(ctx context.Context) resource.TestCheckFunc continue } - input := &verifiedpermissions.GetPolicyStoreInput{ - PolicyStoreId: aws.String(rs.Primary.ID), - } - _, err := conn.GetPolicyStore(ctx, input) - if errs.IsA[*types.ResourceNotFoundException](err) { - return nil + _, err := tfverifiedpermissions.FindPolicyStoreByID(ctx, conn, rs.Primary.ID) + + if tfresource.NotFound(err) { + continue } + if err != nil { return err } @@ -143,9 +163,7 @@ func testAccCheckPolicyStoreExists(ctx context.Context, name string, policystore } conn := acctest.Provider.Meta().(*conns.AWSClient).VerifiedPermissionsClient(ctx) - resp, err := conn.GetPolicyStore(ctx, &verifiedpermissions.GetPolicyStoreInput{ - PolicyStoreId: aws.String(rs.Primary.ID), - }) + resp, err := tfverifiedpermissions.FindPolicyStoreByID(ctx, conn, rs.Primary.ID) if err != nil { return create.Error(names.VerifiedPermissions, create.ErrActionCheckingExistence, tfverifiedpermissions.ResNamePolicyStore, rs.Primary.ID, err) @@ -174,20 +192,9 @@ func testAccPolicyStoresPreCheck(ctx context.Context, t *testing.T) { func testAccPolicyStoreConfig_basic(mode string) string { return fmt.Sprintf(` resource "aws_verifiedpermissions_policy_store" "test" { + description = "Terraform acceptance test" validation_settings { mode = %[1]q } }`, mode) } - -func testAccPolicyStoreConfig_basicWithSchema(mode, schema string) string { - return fmt.Sprintf(` -resource "aws_verifiedpermissions_policy_store" "test" { - validation_settings { - mode = %[1]q - } - schema { - cedar_json = %[2]q - } -}`, mode, schema) -} diff --git a/internal/service/verifiedpermissions/service_package_gen.go b/internal/service/verifiedpermissions/service_package_gen.go index 6defce4a0cc..82e90c1f4f2 100644 --- a/internal/service/verifiedpermissions/service_package_gen.go +++ b/internal/service/verifiedpermissions/service_package_gen.go @@ -19,7 +19,12 @@ func (p *servicePackage) FrameworkDataSources(ctx context.Context) []*types.Serv } func (p *servicePackage) FrameworkResources(ctx context.Context) []*types.ServicePackageFrameworkResource { - return []*types.ServicePackageFrameworkResource{} + return []*types.ServicePackageFrameworkResource{ + { + Factory: newResourcePolicyStore, + Name: "Policy Store", + }, + } } func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePackageSDKDataSource { @@ -27,13 +32,7 @@ func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePac } func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePackageSDKResource { - return []*types.ServicePackageSDKResource{ - { - Factory: ResourcePolicyStore, - TypeName: "aws_verifiedpermissions_policy_store", - Name: "Policy Store", - }, - } + return []*types.ServicePackageSDKResource{} } func (p *servicePackage) ServicePackageName() string { From e3532588ea2f2a1ff9d8962f44cf6a0bc12f2b0b Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Thu, 4 Jan 2024 17:38:56 -0600 Subject: [PATCH 03/14] aws_verifiedpermissions_policy_store: add datasource --- .../policy_store_data_source.go | 102 ++++++++++++++++++ .../policy_store_data_source_test.go | 64 +++++++++++ .../verifiedpermissions/policy_store_fw.go | 16 --- .../verifiedpermissions/policy_store_test.go | 12 +-- .../service_package_gen.go | 7 +- names/names.go | 1 + ...fiedpermissions_policy_store.html.markdown | 37 +++++++ 7 files changed, 216 insertions(+), 23 deletions(-) create mode 100644 internal/service/verifiedpermissions/policy_store_data_source.go create mode 100644 internal/service/verifiedpermissions/policy_store_data_source_test.go create mode 100644 website/docs/d/verifiedpermissions_policy_store.html.markdown diff --git a/internal/service/verifiedpermissions/policy_store_data_source.go b/internal/service/verifiedpermissions/policy_store_data_source.go new file mode 100644 index 00000000000..ed019f502e5 --- /dev/null +++ b/internal/service/verifiedpermissions/policy_store_data_source.go @@ -0,0 +1,102 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package verifiedpermissions + +import ( + "context" + + awstypes "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions/types" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/framework" + "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" + fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" + "github.com/hashicorp/terraform-provider-aws/names" +) + +// @FrameworkDataSource(name="Policy Store") +func newDataSourcePolicyStore(context.Context) (datasource.DataSourceWithConfigure, error) { + return &dataSourcePolicyStore{}, nil +} + +const ( + DSNamePolicyStore = "Policy Store Data Source" +) + +type dataSourcePolicyStore struct { + framework.DataSourceWithConfigure +} + +func (d *dataSourcePolicyStore) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { // nosemgrep:ci.meta-in-func-name + resp.TypeName = "aws_verifiedpermissions_policy_store" +} + +func (d *dataSourcePolicyStore) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "arn": framework.ARNAttributeComputedOnly(), + "created_date": schema.StringAttribute{ + CustomType: fwtypes.TimestampType, + Computed: true, + }, + "description": schema.StringAttribute{ + Computed: true, + }, + "id": schema.StringAttribute{ + Required: true, + }, + "last_updated_date": schema.StringAttribute{ + CustomType: fwtypes.TimestampType, + Computed: true, + }, + "validation_settings": schema.ListAttribute{ + CustomType: fwtypes.NewListNestedObjectTypeOf[validationSettingsDataSource](ctx), + ElementType: fwtypes.NewObjectTypeOf[validationSettingsDataSource](ctx), + Computed: true, + }, + }, + } +} +func (d *dataSourcePolicyStore) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + conn := d.Meta().VerifiedPermissionsClient(ctx) + + var data dataSourcePolicyStoreData + resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + out, err := findPolicyStoreByID(ctx, conn, data.ID.ValueString()) + + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionReading, DSNamePolicyStore, data.ID.ValueString(), err), + err.Error(), + ) + return + } + + resp.Diagnostics.Append(flex.Flatten(ctx, out, &data)...) + + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +type dataSourcePolicyStoreData struct { + ARN types.String `tfsdk:"arn"` + CreatedDate fwtypes.Timestamp `tfsdk:"created_date"` + Description types.String `tfsdk:"description"` + ID types.String `tfsdk:"id"` + LastUpdatedDate fwtypes.Timestamp `tfsdk:"last_updated_date"` + ValidationSettings fwtypes.ListNestedObjectValueOf[validationSettingsDataSource] `tfsdk:"validation_settings"` +} + +type validationSettingsDataSource struct { + Mode fwtypes.StringEnum[awstypes.ValidationMode] `tfsdk:"mode"` +} diff --git a/internal/service/verifiedpermissions/policy_store_data_source_test.go b/internal/service/verifiedpermissions/policy_store_data_source_test.go new file mode 100644 index 00000000000..ed400172636 --- /dev/null +++ b/internal/service/verifiedpermissions/policy_store_data_source_test.go @@ -0,0 +1,64 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package verifiedpermissions_test + +import ( + "fmt" + "testing" + + "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func TestAccVerifiedPermissionsPolicyStoreDataSource_basic(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var policystore verifiedpermissions.GetPolicyStoreOutput + dataSourceName := "data.aws_verifiedpermissions_policy_store.test" + resourceName := "aws_verifiedpermissions_policy_store.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.VerifiedPermissionsEndpointID) + testAccPolicyStoresPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.VerifiedPermissionsEndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckPolicyStoreDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccPolicyStoreDataSourceConfig_basic("OFF"), + Check: resource.ComposeTestCheckFunc( + testAccCheckPolicyStoreExists(ctx, dataSourceName, &policystore), + resource.TestCheckResourceAttrPair(resourceName, "validation_settings.0.mode", dataSourceName, "validation_settings.0.mode"), + resource.TestCheckResourceAttrPair(resourceName, "description", dataSourceName, "description"), + resource.TestCheckResourceAttrPair(resourceName, "arn", dataSourceName, "arn"), + resource.TestCheckResourceAttrSet(dataSourceName, "created_date"), + resource.TestCheckResourceAttrSet(dataSourceName, "last_updated_date"), + ), + }, + }, + }) +} + +func testAccPolicyStoreDataSourceConfig_basic(mode string) string { + return fmt.Sprintf(` +resource "aws_verifiedpermissions_policy_store" "test" { + description = "Terraform acceptance test" + validation_settings { + mode = %[1]q + } +} + +data "aws_verifiedpermissions_policy_store" "test" { + id = aws_verifiedpermissions_policy_store.test.id +} +`, mode) +} diff --git a/internal/service/verifiedpermissions/policy_store_fw.go b/internal/service/verifiedpermissions/policy_store_fw.go index 2dee84d8e83..dfbdd1f9c50 100644 --- a/internal/service/verifiedpermissions/policy_store_fw.go +++ b/internal/service/verifiedpermissions/policy_store_fw.go @@ -70,22 +70,6 @@ func (r *resourcePolicyStore) Schema(ctx context.Context, request resource.Schem }, }, Blocks: map[string]schema.Block{ - //"schema": schema.ListNestedBlock{ - // CustomType: fwtypes.NewListNestedObjectTypeOf[schemaData](ctx), - // Validators: []validator.List{ - // listvalidator.SizeAtMost(1), - // }, - // NestedObject: schema.NestedBlockObject{ - // Attributes: map[string]schema.Attribute{ - // "cedar_json": schema.StringAttribute{ - // Required: true, - // Validators: []validator.String{ - // fwvalidators.JSON(), - // }, - // }, - // }, - // }, - //}, "validation_settings": schema.ListNestedBlock{ CustomType: fwtypes.NewListNestedObjectTypeOf[validationSettings](ctx), Validators: []validator.List{ diff --git a/internal/service/verifiedpermissions/policy_store_test.go b/internal/service/verifiedpermissions/policy_store_test.go index 110a8894219..1e18a778cbd 100644 --- a/internal/service/verifiedpermissions/policy_store_test.go +++ b/internal/service/verifiedpermissions/policy_store_test.go @@ -33,10 +33,10 @@ func TestAccVerifiedPermissionsPolicyStore_basic(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) - acctest.PreCheckPartitionHasService(t, names.VerifiedPermissions) + acctest.PreCheckPartitionHasService(t, names.VerifiedPermissionsEndpointID) testAccPolicyStoresPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, names.VerifiedPermissions), + ErrorCheck: acctest.ErrorCheck(t, names.VerifiedPermissionsEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckPolicyStoreDestroy(ctx), Steps: []resource.TestStep{ @@ -70,10 +70,10 @@ func TestAccVerifiedPermissionsPolicyStore_update(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) - acctest.PreCheckPartitionHasService(t, names.VerifiedPermissions) + acctest.PreCheckPartitionHasService(t, names.VerifiedPermissionsEndpointID) testAccPolicyStoresPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, names.VerifiedPermissions), + ErrorCheck: acctest.ErrorCheck(t, names.VerifiedPermissionsEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckPolicyStoreDestroy(ctx), Steps: []resource.TestStep{ @@ -106,10 +106,10 @@ func TestAccVerifiedPermissionsPolicyStore_disappears(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) - acctest.PreCheckPartitionHasService(t, names.VerifiedPermissions) + acctest.PreCheckPartitionHasService(t, names.VerifiedPermissionsEndpointID) testAccPolicyStoresPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, names.VerifiedPermissions), + ErrorCheck: acctest.ErrorCheck(t, names.VerifiedPermissionsEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckPolicyStoreDestroy(ctx), Steps: []resource.TestStep{ diff --git a/internal/service/verifiedpermissions/service_package_gen.go b/internal/service/verifiedpermissions/service_package_gen.go index 82e90c1f4f2..eaa110b012f 100644 --- a/internal/service/verifiedpermissions/service_package_gen.go +++ b/internal/service/verifiedpermissions/service_package_gen.go @@ -15,7 +15,12 @@ import ( type servicePackage struct{} func (p *servicePackage) FrameworkDataSources(ctx context.Context) []*types.ServicePackageFrameworkDataSource { - return []*types.ServicePackageFrameworkDataSource{} + return []*types.ServicePackageFrameworkDataSource{ + { + Factory: newDataSourcePolicyStore, + Name: "Policy Store", + }, + } } func (p *servicePackage) FrameworkResources(ctx context.Context) []*types.ServicePackageFrameworkResource { diff --git a/names/names.go b/names/names.go index 7e662128ae2..ca113a0aa02 100644 --- a/names/names.go +++ b/names/names.go @@ -93,6 +93,7 @@ const ( SWFEndpointID = "swf" TimestreamWriteEndpointID = "ingest.timestream" TranscribeEndpointID = "transcribe" + VerifiedPermissionsEndpointID = "verifiedpermissions" VPCLatticeEndpointID = "vpc-lattice" XRayEndpointID = "xray" ) diff --git a/website/docs/d/verifiedpermissions_policy_store.html.markdown b/website/docs/d/verifiedpermissions_policy_store.html.markdown new file mode 100644 index 00000000000..0e82f394427 --- /dev/null +++ b/website/docs/d/verifiedpermissions_policy_store.html.markdown @@ -0,0 +1,37 @@ +--- +subcategory: "Verified Permissions" +layout: "aws" +page_title: "AWS: aws_verifiedpermissions_policy_store" +description: |- + Terraform data source for managing an AWS Verified Permissions Policy Store. +--- + +# Data Source: aws_verifiedpermissions_policy_store + +Terraform data source for managing an AWS Verified Permissions Policy Store. + +## Example Usage + +### Basic Usage + +```terraform +data "aws_verifiedpermissions_policy_store" "example" { + id = "example" +} +``` + +## Argument Reference + +The following arguments are required: + +* `id` - (Required) The ID of the Policy Store. + +## Attribute Reference + +This data source exports the following attributes in addition to the arguments above: + +* `arn` - The ARN of the Policy Store. +* `created_date` - The date the Policy Store was created. +* `last_updated_date` - The date the Policy Store was last updated. +* `validation_settings` - Validation settings for the policy store. + From 74ba1dc4dc126cea3a63f15705b5f921968ee7aa Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Thu, 4 Jan 2024 17:43:26 -0600 Subject: [PATCH 04/14] aws_verifiedpermissions_policy_store: update docs --- .../service/verifiedpermissions/policy_store_fw.go | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/internal/service/verifiedpermissions/policy_store_fw.go b/internal/service/verifiedpermissions/policy_store_fw.go index dfbdd1f9c50..de6037824c7 100644 --- a/internal/service/verifiedpermissions/policy_store_fw.go +++ b/internal/service/verifiedpermissions/policy_store_fw.go @@ -32,9 +32,6 @@ import ( // @FrameworkResource(name="Policy Store") func newResourcePolicyStore(context.Context) (resource.ResourceWithConfigure, error) { r := &resourcePolicyStore{} - //r.SetDefaultCreateTimeout(30 * time.Minute) - //r.SetDefaultUpdateTimeout(30 * time.Minute) - //r.SetDefaultDeleteTimeout(30 * time.Minute) return r, nil } @@ -46,14 +43,12 @@ const ( type resourcePolicyStore struct { framework.ResourceWithConfigure - // framework.WithTimeouts } func (r *resourcePolicyStore) Metadata(_ context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) { response.TypeName = "aws_verifiedpermissions_policy_store" } -// Schema returns the schema for this resource. func (r *resourcePolicyStore) Schema(ctx context.Context, request resource.SchemaRequest, response *resource.SchemaResponse) { s := schema.Schema{ Attributes: map[string]schema.Attribute{ @@ -88,15 +83,6 @@ func (r *resourcePolicyStore) Schema(ctx context.Context, request resource.Schem }, } - //if s.Blocks == nil { - // s.Blocks = make(map[string]schema.Block) - //} - //s.Blocks["timeouts"] = timeouts.Block(ctx, timeouts.Opts{ - // Create: true, - // Update: true, - // Delete: true, - //}) - response.Schema = s } From 75513b28cdc2ff5028ef639ab779192f487c0f6b Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Thu, 4 Jan 2024 18:48:42 -0600 Subject: [PATCH 05/14] aws_verifiedpermissions_schema: --- .../verifiedpermissions/policy_store_fw.go | 5 +- .../service/verifiedpermissions/schema.go | 289 ++++++++++++++++++ .../service_package_gen.go | 4 + 3 files changed, 295 insertions(+), 3 deletions(-) create mode 100644 internal/service/verifiedpermissions/schema.go diff --git a/internal/service/verifiedpermissions/policy_store_fw.go b/internal/service/verifiedpermissions/policy_store_fw.go index de6037824c7..4a01f3f2bdc 100644 --- a/internal/service/verifiedpermissions/policy_store_fw.go +++ b/internal/service/verifiedpermissions/policy_store_fw.go @@ -37,8 +37,7 @@ func newResourcePolicyStore(context.Context) (resource.ResourceWithConfigure, er } const ( - ResNamePolicyStore = "Policy Store" - ResNamePolicyStoreSchema = "Policy Store Schema" + ResNamePolicyStore = "Policy Store" ) type resourcePolicyStore struct { @@ -212,7 +211,7 @@ func (r *resourcePolicyStore) Delete(ctx context.Context, request resource.Delet return } - tflog.Debug(ctx, "deleting TODO", map[string]interface{}{ + tflog.Debug(ctx, "deleting Verified Permissions Policy Store", map[string]interface{}{ "id": state.ID.ValueString(), }) diff --git a/internal/service/verifiedpermissions/schema.go b/internal/service/verifiedpermissions/schema.go new file mode 100644 index 00000000000..6e5e993f16e --- /dev/null +++ b/internal/service/verifiedpermissions/schema.go @@ -0,0 +1,289 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package verifiedpermissions + +import ( + "context" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions" + awstypes "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions/types" + "github.com/hashicorp/terraform-plugin-framework-validators/objectvalidator" + "github.com/hashicorp/terraform-plugin-framework/attr" + "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/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-framework/types/basetypes" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" + "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/errs" + "github.com/hashicorp/terraform-provider-aws/internal/framework" + "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" + fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" + fwvalidators "github.com/hashicorp/terraform-provider-aws/internal/framework/validators" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" +) + +// @FrameworkResource(name="Schema") +func newResourceSchema(context.Context) (resource.ResourceWithConfigure, error) { + r := &resourceSchema{} + + return r, nil +} + +const ( + ResNamePolicyStoreSchema = "Schema" +) + +type resourceSchema struct { + framework.ResourceWithConfigure +} + +func (r *resourceSchema) Metadata(_ context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) { + response.TypeName = "aws_verifiedpermissions_schema" +} + +func (r *resourceSchema) Schema(ctx context.Context, request resource.SchemaRequest, response *resource.SchemaResponse) { + s := schema.Schema{ + Attributes: map[string]schema.Attribute{ + "id": framework.IDAttribute(), + "namespaces": schema.ListAttribute{ + ElementType: types.StringType, + Computed: true, + }, + "policy_store_id": schema.StringAttribute{ + Required: true, + }, + }, + Blocks: map[string]schema.Block{ + "definition": schema.SingleNestedBlock{ + Validators: []validator.Object{ + objectvalidator.IsRequired(), + }, + Attributes: map[string]schema.Attribute{ + "value": schema.StringAttribute{ + Required: true, + Validators: []validator.String{ + fwvalidators.JSON(), + }, + }, + }, + }, + }, + } + + response.Schema = s +} + +func (r *resourceSchema) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) { + conn := r.Meta().VerifiedPermissionsClient(ctx) + var plan resourceSchemaData + + response.Diagnostics.Append(request.Plan.Get(ctx, &plan)...) + + if response.Diagnostics.HasError() { + return + } + + input := &verifiedpermissions.PutSchemaInput{ + PolicyStoreId: flex.StringFromFramework(ctx, plan.PolicyStoreID), + Definition: expandDefinition(ctx, plan.Definition, &response.Diagnostics), + } + + if response.Diagnostics.HasError() { + return + } + + output, err := conn.PutSchema(ctx, input) + + if err != nil { + response.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionCreating, ResNamePolicyStoreSchema, plan.PolicyStoreID.ValueString(), err), + err.Error(), + ) + return + } + + state := plan + state.ID = flex.StringToFramework(ctx, output.PolicyStoreId) + + state.Namespaces = flex.FlattenFrameworkStringValueList(ctx, output.Namespaces) + + response.Diagnostics.Append(response.State.Set(ctx, &state)...) +} + +func (r *resourceSchema) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) { + conn := r.Meta().VerifiedPermissionsClient(ctx) + var state resourceSchemaData + + response.Diagnostics.Append(request.State.Get(ctx, &state)...) + + if response.Diagnostics.HasError() { + return + } + + output, err := findSchemaByPolicyStoreID(ctx, conn, state.ID.ValueString()) + + if tfresource.NotFound(err) { + response.State.RemoveResource(ctx) + return + } + + if err != nil { + response.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionReading, ResNamePolicyStoreSchema, state.PolicyStoreID.ValueString(), err), + err.Error(), + ) + return + } + + state.PolicyStoreID = flex.StringToFramework(ctx, output.PolicyStoreId) + state.Namespaces = flex.FlattenFrameworkStringValueList(ctx, output.Namespaces) + state.Definition = flattenDefinition(ctx, output) + + response.Diagnostics.Append(response.State.Set(ctx, &state)...) +} + +func (r *resourceSchema) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) { + conn := r.Meta().VerifiedPermissionsClient(ctx) + var state, plan resourceSchemaData + + response.Diagnostics.Append(request.State.Get(ctx, &state)...) + + if response.Diagnostics.HasError() { + return + } + + response.Diagnostics.Append(request.Plan.Get(ctx, &plan)...) + + if response.Diagnostics.HasError() { + return + } + + if !plan.Definition.Equal(state.Definition) { + input := &verifiedpermissions.PutSchemaInput{ + PolicyStoreId: flex.StringFromFramework(ctx, state.ID), + Definition: expandDefinition(ctx, plan.Definition, &response.Diagnostics), + } + + if response.Diagnostics.HasError() { + return + } + + output, err := conn.PutSchema(ctx, input) + + if err != nil { + response.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionUpdating, ResNamePolicyStoreSchema, state.PolicyStoreID.ValueString(), err), + err.Error(), + ) + return + } + + plan.Namespaces = flex.FlattenFrameworkStringValueList(ctx, output.Namespaces) + } + + response.Diagnostics.Append(response.State.Set(ctx, &plan)...) +} + +func (r *resourceSchema) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) { + conn := r.Meta().VerifiedPermissionsClient(ctx) + var state resourceSchemaData + + response.Diagnostics.Append(request.State.Get(ctx, &state)...) + + if response.Diagnostics.HasError() { + return + } + + tflog.Debug(ctx, "deleting Verified Permissions Policy Store Schema", map[string]interface{}{ + "id": state.ID.ValueString(), + }) + + input := &verifiedpermissions.PutSchemaInput{ + PolicyStoreId: flex.StringFromFramework(ctx, state.ID), + Definition: &awstypes.SchemaDefinitionMemberCedarJson{ + Value: "{}", + }, + } + + _, err := conn.PutSchema(ctx, input) + + if err != nil { + response.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionDeleting, ResNamePolicyStoreSchema, state.PolicyStoreID.ValueString(), err), + err.Error(), + ) + return + } +} + +func (r *resourceSchema) ImportState(ctx context.Context, request resource.ImportStateRequest, response *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("id"), request, response) +} + +type resourceSchemaData struct { + ID types.String `tfsdk:"id"` + Definition types.Object `tfsdk:"definition"` + Namespaces types.List `tfsdk:"namespaces"` + PolicyStoreID types.String `tfsdk:"policy_store_id"` +} + +type definition struct { + Value types.String `tfsdk:"value"` +} + +func findSchemaByPolicyStoreID(ctx context.Context, conn *verifiedpermissions.Client, id string) (*verifiedpermissions.GetSchemaOutput, error) { + in := &verifiedpermissions.GetSchemaInput{ + PolicyStoreId: aws.String(id), + } + + out, err := conn.GetSchema(ctx, in) + if errs.IsA[*awstypes.ResourceNotFoundException](err) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: in, + } + } + if err != nil { + return nil, err + } + + if out == nil || out.Schema == nil { + return nil, tfresource.NewEmptyResultError(in) + } + + return out, nil +} + +func expandDefinition(ctx context.Context, object types.Object, diags *diag.Diagnostics) *awstypes.SchemaDefinitionMemberCedarJson { + var de definition + diags.Append(object.As(ctx, &de, basetypes.ObjectAsOptions{})...) + if diags.HasError() { + return nil + } + + out := &awstypes.SchemaDefinitionMemberCedarJson{ + Value: de.Value.ValueString(), + } + + return out +} + +func flattenDefinition(ctx context.Context, input *verifiedpermissions.GetSchemaOutput) types.Object { + if input == nil { + return fwtypes.NewObjectValueOfNull[definition](ctx).ObjectValue + } + + attributeTypes := fwtypes.AttributeTypesMust[definition](ctx) + attrs := map[string]attr.Value{} + attrs["value"] = flex.StringToFramework(ctx, input.Schema) + + return types.ObjectValueMust(attributeTypes, attrs) +} diff --git a/internal/service/verifiedpermissions/service_package_gen.go b/internal/service/verifiedpermissions/service_package_gen.go index eaa110b012f..38544b542f4 100644 --- a/internal/service/verifiedpermissions/service_package_gen.go +++ b/internal/service/verifiedpermissions/service_package_gen.go @@ -29,6 +29,10 @@ func (p *servicePackage) FrameworkResources(ctx context.Context) []*types.Servic Factory: newResourcePolicyStore, Name: "Policy Store", }, + { + Factory: newResourceSchema, + Name: "Schema", + }, } } From 92014a2b17db35eceb385adac168a593281724f4 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Thu, 4 Jan 2024 18:51:15 -0600 Subject: [PATCH 06/14] rename file --- .../verifiedpermissions/policy_store.go | 615 ++++++++---------- .../verifiedpermissions/policy_store_fw.go | 274 -------- 2 files changed, 269 insertions(+), 620 deletions(-) delete mode 100644 internal/service/verifiedpermissions/policy_store_fw.go diff --git a/internal/service/verifiedpermissions/policy_store.go b/internal/service/verifiedpermissions/policy_store.go index b06aee6d581..4a01f3f2bdc 100644 --- a/internal/service/verifiedpermissions/policy_store.go +++ b/internal/service/verifiedpermissions/policy_store.go @@ -3,349 +3,272 @@ package verifiedpermissions -//import ( -// "context" -// "errors" -// "log" -// "time" -// -// "github.com/aws/aws-sdk-go-v2/aws" -// "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions" -// "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions/types" -// "github.com/hashicorp/terraform-plugin-sdk/v2/diag" -// "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" -// "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" -// "github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure" -// "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" -// "github.com/hashicorp/terraform-provider-aws/internal/conns" -// "github.com/hashicorp/terraform-provider-aws/internal/create" -// "github.com/hashicorp/terraform-provider-aws/internal/enum" -// "github.com/hashicorp/terraform-provider-aws/internal/errs" -// "github.com/hashicorp/terraform-provider-aws/internal/tfresource" -// "github.com/hashicorp/terraform-provider-aws/internal/verify" -// "github.com/hashicorp/terraform-provider-aws/names" -//) -// -//// @SDKResource("aws_verifiedpermissions_policy_store", name="Policy Store") -//func ResourcePolicyStore() *schema.Resource { -// return &schema.Resource{ -// CreateWithoutTimeout: resourcePolicyStoreCreate, -// ReadWithoutTimeout: resourcePolicyStoreRead, -// UpdateWithoutTimeout: resourcePolicyStoreUpdate, -// DeleteWithoutTimeout: resourcePolicyStoreDelete, -// Timeouts: &schema.ResourceTimeout{ -// Create: schema.DefaultTimeout(30 * time.Minute), -// Update: schema.DefaultTimeout(30 * time.Minute), -// Delete: schema.DefaultTimeout(30 * time.Minute), -// }, -// Importer: &schema.ResourceImporter{ -// StateContext: schema.ImportStatePassthroughContext, -// }, -// Schema: map[string]*schema.Schema{ -// "policy_store_id": { -// Type: schema.TypeString, -// Computed: true, -// }, -// "arn": { -// Type: schema.TypeString, -// Computed: true, -// }, -// "created_date": { -// Type: schema.TypeString, -// Computed: true, -// }, -// "last_updated_date": { -// Type: schema.TypeString, -// Computed: true, -// }, -// "validation_settings": { -// Type: schema.TypeList, -// Required: true, -// MaxItems: 1, -// Elem: &schema.Resource{ -// Schema: map[string]*schema.Schema{ -// "mode": { -// Type: schema.TypeString, -// ValidateDiagFunc: enum.Validate[types.ValidationMode](), -// Required: true, -// }, -// }, -// }, -// }, -// "schema": { -// Type: schema.TypeList, -// Optional: true, -// MaxItems: 1, -// Elem: &schema.Resource{ -// Schema: map[string]*schema.Schema{ -// "cedar_json": { -// Type: schema.TypeString, -// Required: true, -// ValidateFunc: validation.StringIsJSON, -// StateFunc: func(v interface{}) string { -// json, _ := structure.NormalizeJsonString(v) -// return json -// }, -// DiffSuppressFunc: verify.SuppressEquivalentJSONDiffs, -// }, -// }, -// }, -// }, -// "schema_created_date": { -// Type: schema.TypeString, -// Computed: true, -// }, -// "schema_last_updated_date": { -// Type: schema.TypeString, -// Computed: true, -// }, -// }, -// } -//} -// -//func resourcePolicyStoreCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { -// var diags diag.Diagnostics -// -// conn := meta.(*conns.AWSClient).VerifiedPermissionsClient(ctx) -// -// in := &verifiedpermissions.CreatePolicyStoreInput{ -// ClientToken: aws.String(id.UniqueId()), -// ValidationSettings: expandValidationSettingsSlice(d.Get("validation_settings").([]interface{})), -// } -// -// out, err := conn.CreatePolicyStore(ctx, in) -// if err != nil { -// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionCreating, ResNamePolicyStore, "", err)...) -// } -// -// if out == nil || out.PolicyStoreId == nil { -// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionCreating, ResNamePolicyStore, "", errors.New("empty output"))...) -// } -// -// policyStoreId := aws.ToString(out.PolicyStoreId) -// d.SetId(policyStoreId) -// -// cedarJson := expandDefinitions(d.Get("schema").([]interface{})) -// inSchema := &verifiedpermissions.PutSchemaInput{ -// Definition: cedarJson, -// PolicyStoreId: &policyStoreId, -// } -// -// _, err = conn.PutSchema(ctx, inSchema) -// if err != nil { -// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionCreating, ResNamePolicyStoreSchema, "", err)...) -// } -// -// return append(diags, resourcePolicyStoreRead(ctx, d, meta)...) -//} -// -//func resourcePolicyStoreRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { -// var diags diag.Diagnostics -// -// conn := meta.(*conns.AWSClient).VerifiedPermissionsClient(ctx) -// -// out, err := findPolicyStoreByID(ctx, conn, d.Id()) -// if !d.IsNewResource() && tfresource.NotFound(err) { -// log.Printf("[WARN] VerifiedPermissions PolicyStore (%s) not found, removing from state", d.Id()) -// d.SetId("") -// return diags -// } -// -// if err != nil { -// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionReading, ResNamePolicyStore, d.Id(), err)...) -// } -// -// d.Set("arn", out.Arn) -// d.Set("policy_store_id", out.PolicyStoreId) -// d.Set("created_date", out.CreatedDate.Format(time.RFC3339)) -// d.Set("last_updated_date", out.LastUpdatedDate.Format(time.RFC3339)) -// -// if err := d.Set("validation_settings", flattenValidationSettingsSlice(out.ValidationSettings)); err != nil { -// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionSetting, ResNamePolicyStore, d.Id(), err)...) -// } -// -// inSchema := &verifiedpermissions.GetSchemaInput{ -// PolicyStoreId: out.PolicyStoreId, -// } -// outSchema, err := conn.GetSchema(ctx, inSchema) -// if err != nil { -// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionReading, ResNamePolicyStoreSchema, *out.PolicyStoreId, err)...) -// } -// -// d.Set("schema", flattenSchemaDefinitionSlice(outSchema.Schema)) -// d.Set("schema_created_date", outSchema.CreatedDate.Format(time.RFC3339)) -// d.Set("schema_last_updated_date", outSchema.LastUpdatedDate.Format(time.RFC3339)) -// -// return diags -//} -// -//func resourcePolicyStoreUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { -// var diags diag.Diagnostics -// -// conn := meta.(*conns.AWSClient).VerifiedPermissionsClient(ctx) -// -// policyStoreID := aws.String(d.Id()) -// update := false -// -// policyStoreIn := &verifiedpermissions.UpdatePolicyStoreInput{ -// PolicyStoreId: policyStoreID, -// } -// -// if d.HasChanges("validation_settings") { -// policyStoreIn.ValidationSettings = expandValidationSettingsSlice(d.Get("validation_settings").([]interface{})) -// update = true -// } -// -// if update { -// log.Printf("[DEBUG] Updating VerifiedPermissions PolicyStore (%s): %#v", d.Id(), policyStoreIn) -// _, err := conn.UpdatePolicyStore(ctx, policyStoreIn) -// if err != nil { -// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionUpdating, ResNamePolicyStore, d.Id(), err)...) -// } -// } -// -// var updateSchema bool -// schemaIn := &verifiedpermissions.PutSchemaInput{ -// PolicyStoreId: policyStoreID, -// } -// if d.HasChanges("schema") { -// schemaIn.Definition = expandDefinitions(d.Get("schema").([]interface{})) -// updateSchema = true -// } -// -// if updateSchema { -// log.Printf("[DEBUG] Updating VerifiedPermissions PolicyStore Schema (%s): %#v", d.Id(), policyStoreIn) -// _, err := conn.PutSchema(ctx, schemaIn) -// if err != nil { -// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionUpdating, ResNamePolicyStoreSchema, d.Id(), err)...) -// } -// } -// -// return append(diags, resourcePolicyStoreRead(ctx, d, meta)...) -//} -// -//func resourcePolicyStoreDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { -// var diags diag.Diagnostics -// -// conn := meta.(*conns.AWSClient).VerifiedPermissionsClient(ctx) -// -// log.Printf("[INFO] Deleting VerifiedPermissions PolicyStore %s", d.Id()) -// -// _, err := conn.DeletePolicyStore(ctx, &verifiedpermissions.DeletePolicyStoreInput{ -// PolicyStoreId: aws.String(d.Id()), -// }) -// -// if errs.IsA[*types.ResourceNotFoundException](err) { -// return diags -// } -// if err != nil { -// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionDeleting, ResNamePolicyStore, d.Id(), err)...) -// } -// -// return diags -//} -// -//func flattenValidationSettings(apiObject *types.ValidationSettings) map[string]interface{} { -// if apiObject == nil { -// return nil -// } -// -// m := make(map[string]interface{}) -// -// if v := apiObject.Mode; v != "" { -// m["mode"] = string(v) -// } -// -// return m -//} -// -//func flattenValidationSettingsSlice(apiObject *types.ValidationSettings) []interface{} { -// if apiObject == nil { -// return nil -// } -// -// return []interface{}{ -// flattenValidationSettings(apiObject), -// } -//} -// -//func expandValidationSettingsSlice(list []interface{}) *types.ValidationSettings { -// if len(list) == 0 { -// return nil -// } -// tfMap := list[0].(map[string]interface{}) -// -// return expandValidationSettings(tfMap) -//} -// -//func expandValidationSettings(tfMap map[string]interface{}) *types.ValidationSettings { -// if tfMap == nil { -// return nil -// } -// -// var out types.ValidationSettings -// -// mode, ok := tfMap["mode"].(string) -// if ok { -// out.Mode = types.ValidationMode(mode) -// } -// -// return &out -//} -// -//func expandDefinition(tfMap map[string]interface{}) *types.SchemaDefinitionMemberCedarJson { -// a := &types.SchemaDefinitionMemberCedarJson{ -// Value: "{}", -// } -// -// if v, ok := tfMap["cedar_json"].(string); ok && v != "" { -// var err error -// a.Value, err = structure.NormalizeJsonString(v) -// if err != nil { -// return a -// } -// } -// -// return a -//} -// -//func expandDefinitions(tfList []interface{}) *types.SchemaDefinitionMemberCedarJson { -// if len(tfList) == 0 { -// return &types.SchemaDefinitionMemberCedarJson{ -// Value: "{}", -// } -// } -// -// tfMap := tfList[0] -// if tfMap == nil { -// return &types.SchemaDefinitionMemberCedarJson{ -// Value: "{}", -// } -// } -// -// return expandDefinition(tfMap.(map[string]interface{})) -//} -// -//func flattenSchemaDefinitionSlice(definition *string) []interface{} { -// def := flattenSchemaDefinition(definition) -// if def == nil { -// return nil -// } -// -// return []interface{}{def} -//} -// -//func flattenSchemaDefinition(definition *string) map[string]interface{} { -// if definition == nil || aws.ToString(definition) == "{}" { -// return nil -// } -// -// specificationToSet, err := structure.NormalizeJsonString(aws.ToString(definition)) -// if err != nil { -// return nil -// } -// -// return map[string]interface{}{ -// "cedar_json": specificationToSet, -// } -//} +import ( + "context" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions" + awstypes "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions/types" + "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" + "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/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" + "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/errs" + "github.com/hashicorp/terraform-provider-aws/internal/framework" + "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" + fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" +) + +// @FrameworkResource(name="Policy Store") +func newResourcePolicyStore(context.Context) (resource.ResourceWithConfigure, error) { + r := &resourcePolicyStore{} + + return r, nil +} + +const ( + ResNamePolicyStore = "Policy Store" +) + +type resourcePolicyStore struct { + framework.ResourceWithConfigure +} + +func (r *resourcePolicyStore) Metadata(_ context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) { + response.TypeName = "aws_verifiedpermissions_policy_store" +} + +func (r *resourcePolicyStore) Schema(ctx context.Context, request resource.SchemaRequest, response *resource.SchemaResponse) { + s := schema.Schema{ + Attributes: map[string]schema.Attribute{ + "arn": framework.ARNAttributeComputedOnly(), + "description": schema.StringAttribute{ + Optional: true, + }, + "id": framework.IDAttribute(), + "policy_store_id": schema.StringAttribute{ + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, + }, + Blocks: map[string]schema.Block{ + "validation_settings": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[validationSettings](ctx), + Validators: []validator.List{ + listvalidator.IsRequired(), + listvalidator.SizeAtMost(1), + }, + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "mode": schema.StringAttribute{ + CustomType: fwtypes.StringEnumType[awstypes.ValidationMode](), + Required: true, + }, + }, + }, + }, + }, + } + + response.Schema = s +} + +func (r *resourcePolicyStore) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) { + conn := r.Meta().VerifiedPermissionsClient(ctx) + var plan resourcePolicyStoreData + + response.Diagnostics.Append(request.Plan.Get(ctx, &plan)...) + + if response.Diagnostics.HasError() { + return + } + + input := &verifiedpermissions.CreatePolicyStoreInput{} + response.Diagnostics.Append(flex.Expand(ctx, plan, input)...) + + if response.Diagnostics.HasError() { + return + } + + clientToken := id.UniqueId() + input.ClientToken = aws.String(clientToken) + + output, err := conn.CreatePolicyStore(ctx, input) + + if err != nil { + response.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionCreating, ResNamePolicyStore, clientToken, err), + err.Error(), + ) + return + } + + state := plan + state.ID = flex.StringToFramework(ctx, output.PolicyStoreId) + + response.Diagnostics.Append(flex.Flatten(ctx, output, &state)...) + + if response.Diagnostics.HasError() { + return + } + + response.Diagnostics.Append(response.State.Set(ctx, &state)...) +} + +func (r *resourcePolicyStore) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) { + conn := r.Meta().VerifiedPermissionsClient(ctx) + var state resourcePolicyStoreData + + response.Diagnostics.Append(request.State.Get(ctx, &state)...) + + if response.Diagnostics.HasError() { + return + } + + output, err := findPolicyStoreByID(ctx, conn, state.ID.ValueString()) + + if tfresource.NotFound(err) { + response.State.RemoveResource(ctx) + return + } + + if err != nil { + response.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionReading, ResNamePolicyStore, state.PolicyStoreID.ValueString(), err), + err.Error(), + ) + return + } + + response.Diagnostics.Append(flex.Flatten(ctx, output, &state)...) + + if response.Diagnostics.HasError() { + return + } + + response.Diagnostics.Append(response.State.Set(ctx, &state)...) +} + +func (r *resourcePolicyStore) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) { + conn := r.Meta().VerifiedPermissionsClient(ctx) + var state, plan resourcePolicyStoreData + + response.Diagnostics.Append(request.State.Get(ctx, &state)...) + + if response.Diagnostics.HasError() { + return + } + + response.Diagnostics.Append(request.Plan.Get(ctx, &plan)...) + + if response.Diagnostics.HasError() { + return + } + + if !plan.Description.Equal(state.Description) || !plan.ValidationSettings.Equal(state.ValidationSettings) { + input := &verifiedpermissions.UpdatePolicyStoreInput{} + response.Diagnostics.Append(flex.Expand(ctx, plan, input)...) + + if response.Diagnostics.HasError() { + return + } + + output, err := conn.UpdatePolicyStore(ctx, input) + + if err != nil { + response.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionUpdating, ResNamePolicyStore, state.PolicyStoreID.ValueString(), err), + err.Error(), + ) + return + } + + response.Diagnostics.Append(flex.Flatten(ctx, output, &plan)...) + } + + response.Diagnostics.Append(response.State.Set(ctx, &plan)...) +} + +func (r *resourcePolicyStore) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) { + conn := r.Meta().VerifiedPermissionsClient(ctx) + var state resourcePolicyStoreData + + response.Diagnostics.Append(request.State.Get(ctx, &state)...) + + if response.Diagnostics.HasError() { + return + } + + tflog.Debug(ctx, "deleting Verified Permissions Policy Store", map[string]interface{}{ + "id": state.ID.ValueString(), + }) + + input := &verifiedpermissions.DeletePolicyStoreInput{ + PolicyStoreId: flex.StringFromFramework(ctx, state.ID), + } + + _, err := conn.DeletePolicyStore(ctx, input) + + if errs.IsA[*awstypes.ResourceNotFoundException](err) { + return + } + + if err != nil { + response.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionDeleting, ResNamePolicyStore, state.PolicyStoreID.ValueString(), err), + err.Error(), + ) + return + } +} + +func (r *resourcePolicyStore) ImportState(ctx context.Context, request resource.ImportStateRequest, response *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("id"), request, response) +} + +type resourcePolicyStoreData struct { + ARN types.String `tfsdk:"arn"` + Description types.String `tfsdk:"description"` + ID types.String `tfsdk:"id"` + PolicyStoreID types.String `tfsdk:"policy_store_id"` + ValidationSettings fwtypes.ListNestedObjectValueOf[validationSettings] `tfsdk:"validation_settings"` +} + +type validationSettings struct { + Mode fwtypes.StringEnum[awstypes.ValidationMode] `tfsdk:"mode"` +} + +func findPolicyStoreByID(ctx context.Context, conn *verifiedpermissions.Client, id string) (*verifiedpermissions.GetPolicyStoreOutput, error) { + in := &verifiedpermissions.GetPolicyStoreInput{ + PolicyStoreId: aws.String(id), + } + + out, err := conn.GetPolicyStore(ctx, in) + if errs.IsA[*awstypes.ResourceNotFoundException](err) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: in, + } + } + if err != nil { + return nil, err + } + + if out == nil || out.Arn == nil { + return nil, tfresource.NewEmptyResultError(in) + } + + return out, nil +} diff --git a/internal/service/verifiedpermissions/policy_store_fw.go b/internal/service/verifiedpermissions/policy_store_fw.go deleted file mode 100644 index 4a01f3f2bdc..00000000000 --- a/internal/service/verifiedpermissions/policy_store_fw.go +++ /dev/null @@ -1,274 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package verifiedpermissions - -import ( - "context" - - "github.com/aws/aws-sdk-go-v2/aws" - "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions" - awstypes "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions/types" - "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" - "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/schema/validator" - "github.com/hashicorp/terraform-plugin-framework/types" - "github.com/hashicorp/terraform-plugin-log/tflog" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" - "github.com/hashicorp/terraform-provider-aws/internal/create" - "github.com/hashicorp/terraform-provider-aws/internal/errs" - "github.com/hashicorp/terraform-provider-aws/internal/framework" - "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" - fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" - "github.com/hashicorp/terraform-provider-aws/internal/tfresource" - "github.com/hashicorp/terraform-provider-aws/names" -) - -// @FrameworkResource(name="Policy Store") -func newResourcePolicyStore(context.Context) (resource.ResourceWithConfigure, error) { - r := &resourcePolicyStore{} - - return r, nil -} - -const ( - ResNamePolicyStore = "Policy Store" -) - -type resourcePolicyStore struct { - framework.ResourceWithConfigure -} - -func (r *resourcePolicyStore) Metadata(_ context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) { - response.TypeName = "aws_verifiedpermissions_policy_store" -} - -func (r *resourcePolicyStore) Schema(ctx context.Context, request resource.SchemaRequest, response *resource.SchemaResponse) { - s := schema.Schema{ - Attributes: map[string]schema.Attribute{ - "arn": framework.ARNAttributeComputedOnly(), - "description": schema.StringAttribute{ - Optional: true, - }, - "id": framework.IDAttribute(), - "policy_store_id": schema.StringAttribute{ - Computed: true, - PlanModifiers: []planmodifier.String{ - stringplanmodifier.UseStateForUnknown(), - }, - }, - }, - Blocks: map[string]schema.Block{ - "validation_settings": schema.ListNestedBlock{ - CustomType: fwtypes.NewListNestedObjectTypeOf[validationSettings](ctx), - Validators: []validator.List{ - listvalidator.IsRequired(), - listvalidator.SizeAtMost(1), - }, - NestedObject: schema.NestedBlockObject{ - Attributes: map[string]schema.Attribute{ - "mode": schema.StringAttribute{ - CustomType: fwtypes.StringEnumType[awstypes.ValidationMode](), - Required: true, - }, - }, - }, - }, - }, - } - - response.Schema = s -} - -func (r *resourcePolicyStore) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) { - conn := r.Meta().VerifiedPermissionsClient(ctx) - var plan resourcePolicyStoreData - - response.Diagnostics.Append(request.Plan.Get(ctx, &plan)...) - - if response.Diagnostics.HasError() { - return - } - - input := &verifiedpermissions.CreatePolicyStoreInput{} - response.Diagnostics.Append(flex.Expand(ctx, plan, input)...) - - if response.Diagnostics.HasError() { - return - } - - clientToken := id.UniqueId() - input.ClientToken = aws.String(clientToken) - - output, err := conn.CreatePolicyStore(ctx, input) - - if err != nil { - response.Diagnostics.AddError( - create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionCreating, ResNamePolicyStore, clientToken, err), - err.Error(), - ) - return - } - - state := plan - state.ID = flex.StringToFramework(ctx, output.PolicyStoreId) - - response.Diagnostics.Append(flex.Flatten(ctx, output, &state)...) - - if response.Diagnostics.HasError() { - return - } - - response.Diagnostics.Append(response.State.Set(ctx, &state)...) -} - -func (r *resourcePolicyStore) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) { - conn := r.Meta().VerifiedPermissionsClient(ctx) - var state resourcePolicyStoreData - - response.Diagnostics.Append(request.State.Get(ctx, &state)...) - - if response.Diagnostics.HasError() { - return - } - - output, err := findPolicyStoreByID(ctx, conn, state.ID.ValueString()) - - if tfresource.NotFound(err) { - response.State.RemoveResource(ctx) - return - } - - if err != nil { - response.Diagnostics.AddError( - create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionReading, ResNamePolicyStore, state.PolicyStoreID.ValueString(), err), - err.Error(), - ) - return - } - - response.Diagnostics.Append(flex.Flatten(ctx, output, &state)...) - - if response.Diagnostics.HasError() { - return - } - - response.Diagnostics.Append(response.State.Set(ctx, &state)...) -} - -func (r *resourcePolicyStore) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) { - conn := r.Meta().VerifiedPermissionsClient(ctx) - var state, plan resourcePolicyStoreData - - response.Diagnostics.Append(request.State.Get(ctx, &state)...) - - if response.Diagnostics.HasError() { - return - } - - response.Diagnostics.Append(request.Plan.Get(ctx, &plan)...) - - if response.Diagnostics.HasError() { - return - } - - if !plan.Description.Equal(state.Description) || !plan.ValidationSettings.Equal(state.ValidationSettings) { - input := &verifiedpermissions.UpdatePolicyStoreInput{} - response.Diagnostics.Append(flex.Expand(ctx, plan, input)...) - - if response.Diagnostics.HasError() { - return - } - - output, err := conn.UpdatePolicyStore(ctx, input) - - if err != nil { - response.Diagnostics.AddError( - create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionUpdating, ResNamePolicyStore, state.PolicyStoreID.ValueString(), err), - err.Error(), - ) - return - } - - response.Diagnostics.Append(flex.Flatten(ctx, output, &plan)...) - } - - response.Diagnostics.Append(response.State.Set(ctx, &plan)...) -} - -func (r *resourcePolicyStore) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) { - conn := r.Meta().VerifiedPermissionsClient(ctx) - var state resourcePolicyStoreData - - response.Diagnostics.Append(request.State.Get(ctx, &state)...) - - if response.Diagnostics.HasError() { - return - } - - tflog.Debug(ctx, "deleting Verified Permissions Policy Store", map[string]interface{}{ - "id": state.ID.ValueString(), - }) - - input := &verifiedpermissions.DeletePolicyStoreInput{ - PolicyStoreId: flex.StringFromFramework(ctx, state.ID), - } - - _, err := conn.DeletePolicyStore(ctx, input) - - if errs.IsA[*awstypes.ResourceNotFoundException](err) { - return - } - - if err != nil { - response.Diagnostics.AddError( - create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionDeleting, ResNamePolicyStore, state.PolicyStoreID.ValueString(), err), - err.Error(), - ) - return - } -} - -func (r *resourcePolicyStore) ImportState(ctx context.Context, request resource.ImportStateRequest, response *resource.ImportStateResponse) { - resource.ImportStatePassthroughID(ctx, path.Root("id"), request, response) -} - -type resourcePolicyStoreData struct { - ARN types.String `tfsdk:"arn"` - Description types.String `tfsdk:"description"` - ID types.String `tfsdk:"id"` - PolicyStoreID types.String `tfsdk:"policy_store_id"` - ValidationSettings fwtypes.ListNestedObjectValueOf[validationSettings] `tfsdk:"validation_settings"` -} - -type validationSettings struct { - Mode fwtypes.StringEnum[awstypes.ValidationMode] `tfsdk:"mode"` -} - -func findPolicyStoreByID(ctx context.Context, conn *verifiedpermissions.Client, id string) (*verifiedpermissions.GetPolicyStoreOutput, error) { - in := &verifiedpermissions.GetPolicyStoreInput{ - PolicyStoreId: aws.String(id), - } - - out, err := conn.GetPolicyStore(ctx, in) - if errs.IsA[*awstypes.ResourceNotFoundException](err) { - return nil, &retry.NotFoundError{ - LastError: err, - LastRequest: in, - } - } - if err != nil { - return nil, err - } - - if out == nil || out.Arn == nil { - return nil, tfresource.NewEmptyResultError(in) - } - - return out, nil -} From c0e92e77820a4194ae83e21322b6c07b05e975ce Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Thu, 4 Jan 2024 18:56:04 -0600 Subject: [PATCH 07/14] aws_verifiedpermissions_policy_store: update docs --- ...fiedpermissions_policy_store.html.markdown | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/website/docs/r/verifiedpermissions_policy_store.html.markdown b/website/docs/r/verifiedpermissions_policy_store.html.markdown index 2f3acab69f5..405e33100e7 100644 --- a/website/docs/r/verifiedpermissions_policy_store.html.markdown +++ b/website/docs/r/verifiedpermissions_policy_store.html.markdown @@ -46,22 +46,19 @@ In addition to all arguments above, the following attributes are exported: * `policy_store_id` - The ID of the Policy Store. * `arn` - The ARN of the Policy Store. -* `created_date` - The date the Policy Store was created. -* `last_updated_date` - The date the Policy Store was last updated. -* `schema_created_date` - The date the Policy Store Schema was created. -* `schema_last_updated_date` - The date the Policy Store Schema was last updated. -## Timeouts - -[Configuration options](https://developer.hashicorp.com/terraform/language/resources/syntax#operation-timeouts): +## Import -* `create` - (Default `30m`) -* `update` - (Default `30m`) -* `delete` - (Default `30m`) +In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import Verified Permissions Policy Store using the `policy_store_id`. For example: -## Import +```terraform +import { + to = aws_verifiedpermissions_policy_store.example + id = "DxQg2j8xvXJQ1tQCYNWj9T" +} +``` -Verified Permissions Policy Store can be imported using the policy_store_id, e.g., +Using `terraform import`, import Verified Permissions Policy Store using the `policy_store_id`. For example: ``` $ terraform import aws_verifiedpermissions_policy_store.example DxQg2j8xvXJQ1tQCYNWj9T From 48752291113d4f416237bc061b70d3ee553b38ce Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Thu, 4 Jan 2024 19:07:31 -0600 Subject: [PATCH 08/14] aws_verifiedpermissions_policy_store: update docs --- ...fiedpermissions_policy_store.html.markdown | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/website/docs/r/verifiedpermissions_policy_store.html.markdown b/website/docs/r/verifiedpermissions_policy_store.html.markdown index 405e33100e7..8a490e0e328 100644 --- a/website/docs/r/verifiedpermissions_policy_store.html.markdown +++ b/website/docs/r/verifiedpermissions_policy_store.html.markdown @@ -19,15 +19,6 @@ resource "aws_verifiedpermissions_policy_store" "example" { validation_settings { mode = "STRICT" } - - schema { - cedar_json = jsonencode({ - "Namespace" : { - "entityTypes" : {}, - "actions" : {} - } - }) - } } ``` @@ -37,8 +28,10 @@ The following arguments are required: * `validation_settings` - (Required) Validation settings for the policy store. * `mode` - (Required) The mode for the validation settings. Valid values: `OFF`, `STRICT`. -* `schema` - (Required) Schema for the policy store. - * `cedar_json` - (Required) The cedar json schema. + +The following arguments are optional: + +* `description` - (Optional) A description of the Policy Store. ## Attributes Reference @@ -60,6 +53,6 @@ import { Using `terraform import`, import Verified Permissions Policy Store using the `policy_store_id`. For example: -``` -$ terraform import aws_verifiedpermissions_policy_store.example DxQg2j8xvXJQ1tQCYNWj9T +```console + % terraform import aws_verifiedpermissions_policy_store.example DxQg2j8xvXJQ1tQCYNWj9T ``` From e320b23a38b423c1f75f1533b45d83516eaccc38 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Thu, 4 Jan 2024 19:11:51 -0600 Subject: [PATCH 09/14] chore: linter --- internal/service/verifiedpermissions/policy_store_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/service/verifiedpermissions/policy_store_test.go b/internal/service/verifiedpermissions/policy_store_test.go index 1e18a778cbd..6a28d6464d3 100644 --- a/internal/service/verifiedpermissions/policy_store_test.go +++ b/internal/service/verifiedpermissions/policy_store_test.go @@ -7,9 +7,9 @@ import ( "context" "errors" "fmt" - "regexp" "testing" + "github.com/YakDriver/regexache" "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" @@ -46,7 +46,7 @@ func TestAccVerifiedPermissionsPolicyStore_basic(t *testing.T) { testAccCheckPolicyStoreExists(ctx, resourceName, &policystore), resource.TestCheckResourceAttr(resourceName, "validation_settings.0.mode", "OFF"), resource.TestCheckResourceAttr(resourceName, "description", "Terraform acceptance test"), - acctest.MatchResourceAttrGlobalARN(resourceName, "arn", "verifiedpermissions", regexp.MustCompile(`policy-store/+.`)), + acctest.MatchResourceAttrGlobalARN(resourceName, "arn", "verifiedpermissions", regexache.MustCompile(`policy-store/+.`)), ), }, { From fd08d21b3eda2437b37694044ffb0fc8ccab6afe Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Thu, 4 Jan 2024 19:15:02 -0600 Subject: [PATCH 10/14] chore: linter --- .../docs/d/verifiedpermissions_policy_store.html.markdown | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/website/docs/d/verifiedpermissions_policy_store.html.markdown b/website/docs/d/verifiedpermissions_policy_store.html.markdown index 0e82f394427..6c8d52c7c60 100644 --- a/website/docs/d/verifiedpermissions_policy_store.html.markdown +++ b/website/docs/d/verifiedpermissions_policy_store.html.markdown @@ -15,8 +15,8 @@ Terraform data source for managing an AWS Verified Permissions Policy Store. ### Basic Usage ```terraform -data "aws_verifiedpermissions_policy_store" "example" { - id = "example" +data "aws_verifiedpermissions_policy_store" "example" { + id = "example" } ``` @@ -34,4 +34,3 @@ This data source exports the following attributes in addition to the arguments a * `created_date` - The date the Policy Store was created. * `last_updated_date` - The date the Policy Store was last updated. * `validation_settings` - Validation settings for the policy store. - From 789b5cce2d8b4e470a778e723cb966e976154767 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Thu, 4 Jan 2024 19:30:13 -0600 Subject: [PATCH 11/14] aws_verifiedpermissions_schema: add documentation --- ...fiedpermissions_policy_store.html.markdown | 4 +- .../verifiedpermissions_schema.html.markdown | 61 +++++++++++++++++++ 2 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 website/docs/r/verifiedpermissions_schema.html.markdown diff --git a/website/docs/r/verifiedpermissions_policy_store.html.markdown b/website/docs/r/verifiedpermissions_policy_store.html.markdown index 8a490e0e328..a16ffd03b46 100644 --- a/website/docs/r/verifiedpermissions_policy_store.html.markdown +++ b/website/docs/r/verifiedpermissions_policy_store.html.markdown @@ -33,9 +33,9 @@ The following arguments are optional: * `description` - (Optional) A description of the Policy Store. -## Attributes Reference +## Attribute Reference -In addition to all arguments above, the following attributes are exported: +This resource exports the following attributes in addition to the arguments above: * `policy_store_id` - The ID of the Policy Store. * `arn` - The ARN of the Policy Store. diff --git a/website/docs/r/verifiedpermissions_schema.html.markdown b/website/docs/r/verifiedpermissions_schema.html.markdown new file mode 100644 index 00000000000..1397648c790 --- /dev/null +++ b/website/docs/r/verifiedpermissions_schema.html.markdown @@ -0,0 +1,61 @@ +--- +subcategory: "Verified Permissions" +layout: "aws" +page_title: "AWS: aws_verifiedpermissions_schema" +description: |- + This is a Terraform resource for managing an AWS Verified Permissions Policy Store Schema. +--- + +# Resource: aws_verifiedpermissions_schema + +This is a Terraform resource for managing an AWS Verified Permissions Policy Store Schema. + +## Example Usage + +### Basic Usage + +```terraform +resource "aws_verifiedpermissions_schema" "example" { + policy_store_id = aws_verifiedpermissions_policy_store.example.policy_store_id + + definition { + value = jsonencode({ + "Namespace" : { + "entityTypes" : {}, + "actions" : {} + } + }) + } +} +``` + +## Argument Reference + +The following arguments are required: + +* `policy_store_id` - (Required) The ID of the Policy Store. +* `definition` - (Required) The definition of the schema. + * `value` - (Required) A JSON string representation of the schema. + +## Attribute Reference + +This resource exports the following attributes in addition to the arguments above: + +* `namespaces` - (Optional) Identifies the namespaces of the entities referenced by this schema. + +## Import + +In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import Verified Permissions Policy Store using the `policy_store_id`. For example: + +```terraform +import { + to = aws_verifiedpermissions_schema.example + id = "DxQg2j8xvXJQ1tQCYNWj9T" +} +``` + +Using `terraform import`, import Verified Permissions Policy Store Schema using the `policy_store_id`. For example: + +```console + % terraform import aws_verifiedpermissions_schema.example DxQg2j8xvXJQ1tQCYNWj9T +``` From db172710c3c9f08fdb2e035bcc817b476f334c69 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Thu, 4 Jan 2024 19:39:49 -0600 Subject: [PATCH 12/14] aws_verifiedpermissions_schema: linter --- website/docs/d/verifiedpermissions_policy_store.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/d/verifiedpermissions_policy_store.html.markdown b/website/docs/d/verifiedpermissions_policy_store.html.markdown index 6c8d52c7c60..e75674e10bd 100644 --- a/website/docs/d/verifiedpermissions_policy_store.html.markdown +++ b/website/docs/d/verifiedpermissions_policy_store.html.markdown @@ -15,7 +15,7 @@ Terraform data source for managing an AWS Verified Permissions Policy Store. ### Basic Usage ```terraform -data "aws_verifiedpermissions_policy_store" "example" { +data "aws_verifiedpermissions_policy_store" "example" { id = "example" } ``` From 9c5648fe700a16b42f89a0529c7a393d2153f4ed Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Fri, 5 Jan 2024 10:59:27 -0600 Subject: [PATCH 13/14] aws_verifiedpermissions_schema: add acceptance tests --- .../verifiedpermissions/exports_test.go | 4 +- .../service/verifiedpermissions/schema.go | 52 ++++- .../verifiedpermissions/schema_test.go | 192 ++++++++++++++++++ 3 files changed, 238 insertions(+), 10 deletions(-) create mode 100644 internal/service/verifiedpermissions/schema_test.go diff --git a/internal/service/verifiedpermissions/exports_test.go b/internal/service/verifiedpermissions/exports_test.go index 9a722e6e9f2..f6061a32bbf 100644 --- a/internal/service/verifiedpermissions/exports_test.go +++ b/internal/service/verifiedpermissions/exports_test.go @@ -6,6 +6,8 @@ package verifiedpermissions // Exports for use in tests only. var ( ResourcePolicyStore = newResourcePolicyStore + ResourceSchema = newResourceSchema - FindPolicyStoreByID = findPolicyStoreByID + FindPolicyStoreByID = findPolicyStoreByID + FindSchemaByPolicyStoreID = findSchemaByPolicyStoreID ) diff --git a/internal/service/verifiedpermissions/schema.go b/internal/service/verifiedpermissions/schema.go index 6e5e993f16e..4049a556175 100644 --- a/internal/service/verifiedpermissions/schema.go +++ b/internal/service/verifiedpermissions/schema.go @@ -5,6 +5,7 @@ package verifiedpermissions import ( "context" + "encoding/json" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions" @@ -53,7 +54,7 @@ func (r *resourceSchema) Schema(ctx context.Context, request resource.SchemaRequ s := schema.Schema{ Attributes: map[string]schema.Attribute{ "id": framework.IDAttribute(), - "namespaces": schema.ListAttribute{ + "namespaces": schema.SetAttribute{ ElementType: types.StringType, Computed: true, }, @@ -113,7 +114,7 @@ func (r *resourceSchema) Create(ctx context.Context, request resource.CreateRequ state := plan state.ID = flex.StringToFramework(ctx, output.PolicyStoreId) - state.Namespaces = flex.FlattenFrameworkStringValueList(ctx, output.Namespaces) + state.Namespaces = flex.FlattenFrameworkStringValueSet(ctx, output.Namespaces) response.Diagnostics.Append(response.State.Set(ctx, &state)...) } @@ -144,8 +145,12 @@ func (r *resourceSchema) Read(ctx context.Context, request resource.ReadRequest, } state.PolicyStoreID = flex.StringToFramework(ctx, output.PolicyStoreId) - state.Namespaces = flex.FlattenFrameworkStringValueList(ctx, output.Namespaces) - state.Definition = flattenDefinition(ctx, output) + state.Namespaces = flex.FlattenFrameworkStringValueSet(ctx, output.Namespaces) + state.Definition = flattenDefinition(ctx, output, &response.Diagnostics) + + if response.Diagnostics.HasError() { + return + } response.Diagnostics.Append(response.State.Set(ctx, &state)...) } @@ -176,7 +181,17 @@ func (r *resourceSchema) Update(ctx context.Context, request resource.UpdateRequ return } - output, err := conn.PutSchema(ctx, input) + _, err := conn.PutSchema(ctx, input) + + if err != nil { + response.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionUpdating, ResNamePolicyStoreSchema, state.PolicyStoreID.ValueString(), err), + err.Error(), + ) + return + } + + out, err := findSchemaByPolicyStoreID(ctx, conn, state.ID.ValueString()) if err != nil { response.Diagnostics.AddError( @@ -186,7 +201,7 @@ func (r *resourceSchema) Update(ctx context.Context, request resource.UpdateRequ return } - plan.Namespaces = flex.FlattenFrameworkStringValueList(ctx, output.Namespaces) + plan.Namespaces = flex.FlattenFrameworkStringValueSet(ctx, out.Namespaces) } response.Diagnostics.Append(response.State.Set(ctx, &plan)...) @@ -231,7 +246,7 @@ func (r *resourceSchema) ImportState(ctx context.Context, request resource.Impor type resourceSchemaData struct { ID types.String `tfsdk:"id"` Definition types.Object `tfsdk:"definition"` - Namespaces types.List `tfsdk:"namespaces"` + Namespaces types.Set `tfsdk:"namespaces"` PolicyStoreID types.String `tfsdk:"policy_store_id"` } @@ -276,14 +291,33 @@ func expandDefinition(ctx context.Context, object types.Object, diags *diag.Diag return out } -func flattenDefinition(ctx context.Context, input *verifiedpermissions.GetSchemaOutput) types.Object { +func flattenDefinition(ctx context.Context, input *verifiedpermissions.GetSchemaOutput, diags *diag.Diagnostics) types.Object { if input == nil { return fwtypes.NewObjectValueOfNull[definition](ctx).ObjectValue } + var data any + err := json.Unmarshal([]byte(aws.ToString(input.Schema)), &data) + if err != nil { + diags.AddError( + "unable to unmarshal schema", + err.Error(), + ) + return fwtypes.NewObjectValueOfNull[definition](ctx).ObjectValue + } + + val, err := json.Marshal(data) + if err != nil { + diags.AddError( + "unable to marshal schema", + err.Error(), + ) + return fwtypes.NewObjectValueOfNull[definition](ctx).ObjectValue + } + attributeTypes := fwtypes.AttributeTypesMust[definition](ctx) attrs := map[string]attr.Value{} - attrs["value"] = flex.StringToFramework(ctx, input.Schema) + attrs["value"] = flex.StringValueToFramework(ctx, string(val)) return types.ObjectValueMust(attributeTypes, attrs) } diff --git a/internal/service/verifiedpermissions/schema_test.go b/internal/service/verifiedpermissions/schema_test.go new file mode 100644 index 00000000000..11e459ca118 --- /dev/null +++ b/internal/service/verifiedpermissions/schema_test.go @@ -0,0 +1,192 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package verifiedpermissions_test + +import ( + "context" + "errors" + "fmt" + "testing" + + "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/create" + tfverifiedpermissions "github.com/hashicorp/terraform-provider-aws/internal/service/verifiedpermissions" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func TestAccVerifiedPermissionsSchema_basic(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var schema verifiedpermissions.GetSchemaOutput + resourceName := "aws_verifiedpermissions_schema.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.VerifiedPermissionsEndpointID) + testAccPolicyStoresPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.VerifiedPermissionsEndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckSchemaDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccSchemaConfig_basic("NAMESPACE"), + Check: resource.ComposeTestCheckFunc( + testAccCheckSchemaExists(ctx, resourceName, &schema), + resource.TestCheckTypeSetElemAttr(resourceName, "namespaces.*", "NAMESPACE"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccVerifiedPermissionsSchema_update(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var schema verifiedpermissions.GetSchemaOutput + resourceName := "aws_verifiedpermissions_schema.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.VerifiedPermissionsEndpointID) + testAccPolicyStoresPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.VerifiedPermissionsEndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckSchemaDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccSchemaConfig_basic("NAMESPACE"), + Check: resource.ComposeTestCheckFunc( + testAccCheckSchemaExists(ctx, resourceName, &schema), + resource.TestCheckTypeSetElemAttr(resourceName, "namespaces.*", "NAMESPACE"), + ), + }, + { + Config: testAccSchemaConfig_basic("CHANGED"), + Check: resource.ComposeTestCheckFunc( + testAccCheckSchemaExists(ctx, resourceName, &schema), + resource.TestCheckTypeSetElemAttr(resourceName, "namespaces.*", "CHANGED"), + ), + }, + }, + }) +} + +func TestAccVerifiedPermissionsSchema_disappears(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var schema verifiedpermissions.GetSchemaOutput + resourceName := "aws_verifiedpermissions_schema.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.VerifiedPermissionsEndpointID) + testAccPolicyStoresPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.VerifiedPermissionsEndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckSchemaDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccSchemaConfig_basic("NAMESPACE"), + Check: resource.ComposeTestCheckFunc( + testAccCheckSchemaExists(ctx, resourceName, &schema), + acctest.CheckFrameworkResourceDisappears(ctx, acctest.Provider, tfverifiedpermissions.ResourceSchema, resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccCheckSchemaDestroy(ctx context.Context) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).VerifiedPermissionsClient(ctx) + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_verifiedpermissions_schema" { + continue + } + + _, err := tfverifiedpermissions.FindSchemaByPolicyStoreID(ctx, conn, rs.Primary.ID) + + if tfresource.NotFound(err) { + continue + } + + if err != nil { + return err + } + + return create.Error(names.VerifiedPermissions, create.ErrActionCheckingDestroyed, tfverifiedpermissions.ResNamePolicyStoreSchema, rs.Primary.ID, errors.New("not destroyed")) + } + + return nil + } +} + +func testAccCheckSchemaExists(ctx context.Context, name string, schema *verifiedpermissions.GetSchemaOutput) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[name] + if !ok { + return create.Error(names.VerifiedPermissions, create.ErrActionCheckingExistence, tfverifiedpermissions.ResNamePolicyStoreSchema, name, errors.New("not found")) + } + + if rs.Primary.ID == "" { + return create.Error(names.VerifiedPermissions, create.ErrActionCheckingExistence, tfverifiedpermissions.ResNamePolicyStoreSchema, name, errors.New("not set")) + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).VerifiedPermissionsClient(ctx) + resp, err := tfverifiedpermissions.FindSchemaByPolicyStoreID(ctx, conn, rs.Primary.ID) + + if err != nil { + return create.Error(names.VerifiedPermissions, create.ErrActionCheckingExistence, tfverifiedpermissions.ResNamePolicyStoreSchema, rs.Primary.ID, err) + } + + *schema = *resp + + return nil + } +} + +func testAccSchemaConfig_basic(namespace string) string { + return fmt.Sprintf(` +resource "aws_verifiedpermissions_policy_store" "test" { + description = "Terraform acceptance test" + validation_settings { + mode = "STRICT" + } +} + +resource "aws_verifiedpermissions_schema" "test" { + policy_store_id = aws_verifiedpermissions_policy_store.test.policy_store_id + + definition { + value = "{\"%[1]s\":{\"actions\":{},\"entityTypes\":{}}}" + } +}`, namespace) +} From 10a8eee88ed84f7942592dd192b8c76735a3c616 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Fri, 5 Jan 2024 11:08:57 -0600 Subject: [PATCH 14/14] update CHANGELOG --- .changelog/32204.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.changelog/32204.txt b/.changelog/32204.txt index 2a8bf12d8d1..e1db85a7275 100644 --- a/.changelog/32204.txt +++ b/.changelog/32204.txt @@ -1,3 +1,11 @@ ```release-note:new-resource aws_verifiedpermissions_policy_store +``` + +```release-note:new-resource +aws_verifiedpermissions_schema +``` + +```release-note:new-data-source +aws_verifiedpermissions_policy_store ``` \ No newline at end of file