From b2ba2a22cd7576b4740c8294c6c36c1792972e25 Mon Sep 17 00:00:00 2001 From: Noah-Jerome Lotzer Date: Thu, 13 Jul 2023 02:07:24 +0200 Subject: [PATCH 1/9] verifiedpermissions: add policy template (#32205) --- .changelog/32205.txt | 3 + .../verifiedpermissions/policy_template.go | 235 ++++++++++++++++++ .../policy_template_test.go | 175 +++++++++++++ .../service_package_gen.go | 5 + ...dpermissions_policy_template.html.markdown | 55 ++++ 5 files changed, 473 insertions(+) create mode 100644 .changelog/32205.txt create mode 100644 internal/service/verifiedpermissions/policy_template.go create mode 100644 internal/service/verifiedpermissions/policy_template_test.go create mode 100644 website/docs/r/verifiedpermissions_policy_template.html.markdown diff --git a/.changelog/32205.txt b/.changelog/32205.txt new file mode 100644 index 00000000000..005752c308c --- /dev/null +++ b/.changelog/32205.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +aws_verifiedpermissions_policy_template +``` \ No newline at end of file diff --git a/internal/service/verifiedpermissions/policy_template.go b/internal/service/verifiedpermissions/policy_template.go new file mode 100644 index 00000000000..11235ebab07 --- /dev/null +++ b/internal/service/verifiedpermissions/policy_template.go @@ -0,0 +1,235 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package verifiedpermissions + +import ( + "context" + "errors" + "fmt" + "log" + "strings" + "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-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/errs" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" +) + +// @SDKResource("aws_verifiedpermissions_policy_template", name="Policy Template") +func ResourcePolicyTemplate() *schema.Resource { + return &schema.Resource{ + CreateWithoutTimeout: resourcePolicyTemplateCreate, + ReadWithoutTimeout: resourcePolicyTemplateRead, + UpdateWithoutTimeout: resourcePolicyTemplateUpdate, + DeleteWithoutTimeout: resourcePolicyTemplateDelete, + + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "policy_template_id": { + Type: schema.TypeString, + Computed: true, + }, + "policy_store_id": { + Type: schema.TypeString, + ForceNew: true, + Required: true, + }, + "description": { + Type: schema.TypeString, + Optional: true, + }, + "statement": { + Type: schema.TypeString, + Required: true, + }, + "created_date": { + Type: schema.TypeString, + Computed: true, + }, + "last_updated_date": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +const ( + ResNamePolicyTemplate = "Policy Template" +) + +func resourcePolicyTemplateCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).VerifiedPermissionsClient(ctx) + + in := &verifiedpermissions.CreatePolicyTemplateInput{ + PolicyStoreId: aws.String(d.Get("policy_store_id").(string)), + Statement: aws.String(d.Get("statement").(string)), + ClientToken: aws.String(id.UniqueId()), + } + + if description, ok := d.GetOk("description"); ok { + in.Description = aws.String(description.(string)) + } + + out, err := conn.CreatePolicyTemplate(ctx, in) + if err != nil { + return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionCreating, ResNamePolicyTemplate, d.Get("policy_store_id").(string), err)...) + } + + if out == nil || out.PolicyStoreId == nil { + return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionCreating, ResNamePolicyTemplate, d.Get("policy_store_id").(string), errors.New("empty output"))...) + } + + d.SetId(fmt.Sprintf("%s:%s", aws.ToString(out.PolicyStoreId), aws.ToString(out.PolicyTemplateId))) + + return append(diags, resourcePolicyTemplateRead(ctx, d, meta)...) +} + +func resourcePolicyTemplateRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).VerifiedPermissionsClient(ctx) + + policyStoreID, policyTemplateID, err := PolicyTemplateParseID(d.Id()) + if err != nil { + return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionReading, ResNamePolicyTemplate, d.Id(), err)...) + } + + out, err := findPolicyTemplateByID(ctx, conn, policyStoreID, policyTemplateID) + + if !d.IsNewResource() && tfresource.NotFound(err) { + log.Printf("[WARN] VerifiedPermissions PolicyTemplate (%s) not found, removing from state", d.Id()) + d.SetId("") + return diags + } + + if err != nil { + return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionReading, ResNamePolicyTemplate, d.Id(), err)...) + } + + d.Set("policy_store_id", out.PolicyStoreId) + d.Set("created_date", out.CreatedDate.Format(time.RFC3339Nano)) + d.Set("last_updated_date", out.LastUpdatedDate.Format(time.RFC3339Nano)) + d.Set("description", out.Description) + d.Set("statement", out.Statement) + d.Set("policy_template_id", out.PolicyTemplateId) + + return diags +} + +func resourcePolicyTemplateUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).VerifiedPermissionsClient(ctx) + + update := false + + policyStoreId, policyTemplateID, err := PolicyTemplateParseID(d.Id()) + if err != nil { + return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionUpdating, ResNamePolicyTemplate, d.Id(), err)...) + } + + in := &verifiedpermissions.UpdatePolicyTemplateInput{ + PolicyStoreId: aws.String(policyStoreId), + PolicyTemplateId: aws.String(policyTemplateID), + } + + if d.HasChanges("statement") { + in.Statement = aws.String(d.Get("statement").(string)) + update = true + } + + if d.HasChanges("description") { + in.Description = aws.String(d.Get("description").(string)) + update = true + } + + if !update { + return diags + } + + log.Printf("[DEBUG] Updating VerifiedPermissions PolicyTemplate (%s): %#v", d.Id(), in) + _, err = conn.UpdatePolicyTemplate(ctx, in) + if err != nil { + return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionUpdating, ResNamePolicyTemplate, d.Id(), err)...) + } + + return append(diags, resourcePolicyTemplateRead(ctx, d, meta)...) +} + +func resourcePolicyTemplateDelete(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 PolicyTemplate %s", d.Id()) + + policyStoreId, policyTemplateID, err := PolicyTemplateParseID(d.Id()) + if err != nil { + return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionDeleting, ResNamePolicyTemplate, d.Id(), err)...) + } + + _, err = conn.DeletePolicyTemplate(ctx, &verifiedpermissions.DeletePolicyTemplateInput{ + PolicyStoreId: aws.String(policyStoreId), + PolicyTemplateId: aws.String(policyTemplateID), + }) + + if errs.IsA[*types.ResourceNotFoundException](err) { + return diags + } + if err != nil { + return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionDeleting, ResNamePolicyTemplate, d.Id(), err)...) + } + + return diags +} + +func findPolicyTemplateByID(ctx context.Context, conn *verifiedpermissions.Client, policyStoreId, id string) (*verifiedpermissions.GetPolicyTemplateOutput, error) { + in := &verifiedpermissions.GetPolicyTemplateInput{ + PolicyStoreId: aws.String(policyStoreId), + PolicyTemplateId: aws.String(id), + } + out, err := conn.GetPolicyTemplate(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.PolicyStoreId == nil { + return nil, tfresource.NewEmptyResultError(in) + } + + return out, nil +} + +func PolicyTemplateParseID(id string) (string, string, error) { + parts := strings.Split(id, ":") + + if len(parts) == 2 && parts[0] != "" && parts[1] != "" { + return parts[0], parts[1], nil + } + + return "", "", fmt.Errorf("unexpected format for ID (%s), expected POLICY-STORE-ID:POLICY-TEMPLATE-ID", id) +} diff --git a/internal/service/verifiedpermissions/policy_template_test.go b/internal/service/verifiedpermissions/policy_template_test.go new file mode 100644 index 00000000000..464f15cc131 --- /dev/null +++ b/internal/service/verifiedpermissions/policy_template_test.go @@ -0,0 +1,175 @@ +// 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/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 TestAccVerifiedPermissionsPolicyTemplate_basic(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var policytemplate verifiedpermissions.GetPolicyTemplateOutput + resourceName := "aws_verifiedpermissions_policy_template.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.VerifiedPermissions) + }, + ErrorCheck: acctest.ErrorCheck(t, names.VerifiedPermissions), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckPolicyTemplateDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccPolicyTemplateConfig_basic("permit (principal in ?principal, action in PhotoFlash::Action::\"FullPhotoAccess\", resource == ?resource) unless { resource.IsPrivate };", ""), + Check: resource.ComposeTestCheckFunc( + testAccCheckPolicyTemplateExists(ctx, resourceName, &policytemplate), + resource.TestCheckResourceAttr(resourceName, "statement", "permit (principal in ?principal, action in PhotoFlash::Action::\"FullPhotoAccess\", resource == ?resource) unless { resource.IsPrivate };"), + resource.TestCheckResourceAttr(resourceName, "description", ""), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccPolicyTemplateConfig_basic("permit (principal in ?principal, action in PhotoFlash::Action::\"FullPhotoAccess\", resource == ?resource);", "test"), + Check: resource.ComposeTestCheckFunc( + testAccCheckPolicyTemplateExists(ctx, resourceName, &policytemplate), + resource.TestCheckResourceAttr(resourceName, "statement", "permit (principal in ?principal, action in PhotoFlash::Action::\"FullPhotoAccess\", resource == ?resource);"), + resource.TestCheckResourceAttr(resourceName, "description", "test"), + ), + }, + }, + }) +} + +func TestAccVerifiedPermissionsPolicyTemplate_disappears(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var policytemplate verifiedpermissions.GetPolicyTemplateOutput + resourceName := "aws_verifiedpermissions_policy_template.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.VerifiedPermissions) + }, + ErrorCheck: acctest.ErrorCheck(t, names.VerifiedPermissions), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckPolicyTemplateDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccPolicyTemplateConfig_basic(`permit (principal in ?principal, action in PhotoFlash::Action::"FullPhotoAccess", resource == ?resource) unless { resource.IsPrivate };`, ""), + Check: resource.ComposeTestCheckFunc( + testAccCheckPolicyTemplateExists(ctx, resourceName, &policytemplate), + acctest.CheckResourceDisappears(ctx, acctest.Provider, tfverifiedpermissions.ResourcePolicyTemplate(), resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccCheckPolicyTemplateDestroy(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_template" { + continue + } + policyStoreID, policyTemplateID, err := tfverifiedpermissions.PolicyTemplateParseID(rs.Primary.ID) + if err != nil { + return create.Error(names.VerifiedPermissions, create.ErrActionCheckingDestroyed, tfverifiedpermissions.ResNamePolicyTemplate, rs.Primary.ID, err) + } + + _, err = conn.GetPolicyTemplate(ctx, &verifiedpermissions.GetPolicyTemplateInput{ + PolicyTemplateId: &policyTemplateID, + PolicyStoreId: &policyStoreID, + }) + if errs.IsA[*types.ResourceNotFoundException](err) { + return nil + } + if err != nil { + return err + } + + return create.Error(names.VerifiedPermissions, create.ErrActionCheckingDestroyed, tfverifiedpermissions.ResNamePolicyTemplate, rs.Primary.ID, errors.New("not destroyed")) + } + + return nil + } +} + +func testAccCheckPolicyTemplateExists(ctx context.Context, name string, policytemplate *verifiedpermissions.GetPolicyTemplateOutput) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[name] + if !ok { + return create.Error(names.VerifiedPermissions, create.ErrActionCheckingExistence, tfverifiedpermissions.ResNamePolicyTemplate, name, errors.New("not found")) + } + + if rs.Primary.ID == "" { + return create.Error(names.VerifiedPermissions, create.ErrActionCheckingExistence, tfverifiedpermissions.ResNamePolicyTemplate, name, errors.New("not set")) + } + + policyStoreID, policyTemplateID, err := tfverifiedpermissions.PolicyTemplateParseID(rs.Primary.ID) + if err != nil { + return create.Error(names.VerifiedPermissions, create.ErrActionCheckingExistence, tfverifiedpermissions.ResNamePolicyTemplate, rs.Primary.ID, err) + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).VerifiedPermissionsClient(ctx) + resp, err := conn.GetPolicyTemplate(ctx, &verifiedpermissions.GetPolicyTemplateInput{ + PolicyTemplateId: &policyTemplateID, + PolicyStoreId: &policyStoreID, + }) + + if err != nil { + return create.Error(names.VerifiedPermissions, create.ErrActionCheckingExistence, tfverifiedpermissions.ResNamePolicyTemplate, rs.Primary.ID, err) + } + + *policytemplate = *resp + + return nil + } +} + +func testAccPolicyTemplateConfig_basic(statement, description string) string { + return fmt.Sprintf(` +resource "aws_verifiedpermissions_policy_store" "test" { + validation_settings { + mode = "OFF" + } +} + +resource "aws_verifiedpermissions_policy_template" "test" { + policy_store_id = aws_verifiedpermissions_policy_store.test.id + + statement = %[1]q + description = %[2]q +} +`, statement, description) +} diff --git a/internal/service/verifiedpermissions/service_package_gen.go b/internal/service/verifiedpermissions/service_package_gen.go index 8515063768b..ae924e744d3 100644 --- a/internal/service/verifiedpermissions/service_package_gen.go +++ b/internal/service/verifiedpermissions/service_package_gen.go @@ -33,6 +33,11 @@ func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePacka TypeName: "aws_verifiedpermissions_policy_store", Name: "Policy Store", }, + { + Factory: ResourcePolicyTemplate, + TypeName: "aws_verifiedpermissions_policy_template", + Name: "Policy Template", + }, } } diff --git a/website/docs/r/verifiedpermissions_policy_template.html.markdown b/website/docs/r/verifiedpermissions_policy_template.html.markdown new file mode 100644 index 00000000000..d983f5acd77 --- /dev/null +++ b/website/docs/r/verifiedpermissions_policy_template.html.markdown @@ -0,0 +1,55 @@ +--- +subcategory: "Verified Permissions" +layout: "aws" +page_title: "AWS: aws_verifiedpermissions_policy_template" +description: |- + Terraform resource for managing an AWS Verified Permissions Policy Template. +--- +# Resource: aws_verifiedpermissions_policy_template + +Terraform resource for managing an AWS Verified Permissions Policy Template. + +## Example Usage + +### Basic Usage + +```terraform +resource "aws_verifiedpermissions_policy_template" "example" { + policy_store_id = aws_verifiedpermissions_policy_store.test.id + + description = "" + statement = "" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `policy_store_id` - (Required) The ID of the Policy Store. +* `statement` - (Required) Defines the content of the statement, written in Cedar policy language. +* `description` - (Optional) Provides a description for the policy template. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `policy_template_id` - The ID of the Policy Store. +* `created_date` - The date the Policy Store was created. +* `last_updated_date` - The date the Policy Store 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 Template can be imported using the `policy_store_id:policy_template_id`, e.g., + +``` +$ terraform import aws_verifiedpermissions_policy_template.example policyStoreId:policyTemplateId +``` From 32df95a3e890be3098b050618f681ba26794f28d Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Fri, 5 Jan 2024 13:05:50 -0600 Subject: [PATCH 2/9] rm duplicate files --- .changelog/32204.txt | 3 - .../verifiedpermissions/policy_store.go | 379 ------------------ .../verifiedpermissions/policy_store_test.go | 193 --------- ...fiedpermissions_policy_store.html.markdown | 68 ---- 4 files changed, 643 deletions(-) delete mode 100644 .changelog/32204.txt delete mode 100644 internal/service/verifiedpermissions/policy_store.go delete mode 100644 internal/service/verifiedpermissions/policy_store_test.go delete mode 100644 website/docs/r/verifiedpermissions_policy_store.html.markdown diff --git a/.changelog/32204.txt b/.changelog/32204.txt deleted file mode 100644 index 2a8bf12d8d1..00000000000 --- a/.changelog/32204.txt +++ /dev/null @@ -1,3 +0,0 @@ -```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 deleted file mode 100644 index 351d750c3a6..00000000000 --- a/internal/service/verifiedpermissions/policy_store.go +++ /dev/null @@ -1,379 +0,0 @@ -// 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 deleted file mode 100644 index 410caad3de7..00000000000 --- a/internal/service/verifiedpermissions/policy_store_test.go +++ /dev/null @@ -1,193 +0,0 @@ -// 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/website/docs/r/verifiedpermissions_policy_store.html.markdown b/website/docs/r/verifiedpermissions_policy_store.html.markdown deleted file mode 100644 index 2f3acab69f5..00000000000 --- a/website/docs/r/verifiedpermissions_policy_store.html.markdown +++ /dev/null @@ -1,68 +0,0 @@ ---- -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 0dcdea9d3ee0150db5906cef8324b73f8eb793fc Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Mon, 8 Jan 2024 16:04:01 -0600 Subject: [PATCH 3/9] aws_verifiedpermissions_policy_template: use Framework --- .../verifiedpermissions/exports_test.go | 9 +- .../verifiedpermissions/policy_template.go | 423 ++++++++---------- .../verifiedpermissions/policy_template_fw.go | 288 ++++++++++++ .../policy_template_test.go | 2 +- .../service_package_gen.go | 12 +- 5 files changed, 494 insertions(+), 240 deletions(-) create mode 100644 internal/service/verifiedpermissions/policy_template_fw.go diff --git a/internal/service/verifiedpermissions/exports_test.go b/internal/service/verifiedpermissions/exports_test.go index f6061a32bbf..2f7393764dc 100644 --- a/internal/service/verifiedpermissions/exports_test.go +++ b/internal/service/verifiedpermissions/exports_test.go @@ -5,9 +5,14 @@ package verifiedpermissions // Exports for use in tests only. var ( - ResourcePolicyStore = newResourcePolicyStore - ResourceSchema = newResourceSchema + ResourcePolicyStore = newResourcePolicyStore + ResourcePolicyTemplate = newResourcePolicyTemplate + ResourceSchema = newResourceSchema FindPolicyStoreByID = findPolicyStoreByID FindSchemaByPolicyStoreID = findSchemaByPolicyStoreID ) + +var ( + PolicyTemplateParseID = policyTemplateParseID +) diff --git a/internal/service/verifiedpermissions/policy_template.go b/internal/service/verifiedpermissions/policy_template.go index 11235ebab07..c0ebdcfe122 100644 --- a/internal/service/verifiedpermissions/policy_template.go +++ b/internal/service/verifiedpermissions/policy_template.go @@ -3,233 +3,196 @@ package verifiedpermissions -import ( - "context" - "errors" - "fmt" - "log" - "strings" - "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-provider-aws/internal/conns" - "github.com/hashicorp/terraform-provider-aws/internal/create" - "github.com/hashicorp/terraform-provider-aws/internal/errs" - "github.com/hashicorp/terraform-provider-aws/internal/tfresource" - "github.com/hashicorp/terraform-provider-aws/names" -) - -// @SDKResource("aws_verifiedpermissions_policy_template", name="Policy Template") -func ResourcePolicyTemplate() *schema.Resource { - return &schema.Resource{ - CreateWithoutTimeout: resourcePolicyTemplateCreate, - ReadWithoutTimeout: resourcePolicyTemplateRead, - UpdateWithoutTimeout: resourcePolicyTemplateUpdate, - DeleteWithoutTimeout: resourcePolicyTemplateDelete, - - Importer: &schema.ResourceImporter{ - StateContext: schema.ImportStatePassthroughContext, - }, - - Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(30 * time.Minute), - Update: schema.DefaultTimeout(30 * time.Minute), - Delete: schema.DefaultTimeout(30 * time.Minute), - }, - - Schema: map[string]*schema.Schema{ - "policy_template_id": { - Type: schema.TypeString, - Computed: true, - }, - "policy_store_id": { - Type: schema.TypeString, - ForceNew: true, - Required: true, - }, - "description": { - Type: schema.TypeString, - Optional: true, - }, - "statement": { - Type: schema.TypeString, - Required: true, - }, - "created_date": { - Type: schema.TypeString, - Computed: true, - }, - "last_updated_date": { - Type: schema.TypeString, - Computed: true, - }, - }, - } -} - -const ( - ResNamePolicyTemplate = "Policy Template" -) - -func resourcePolicyTemplateCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).VerifiedPermissionsClient(ctx) - - in := &verifiedpermissions.CreatePolicyTemplateInput{ - PolicyStoreId: aws.String(d.Get("policy_store_id").(string)), - Statement: aws.String(d.Get("statement").(string)), - ClientToken: aws.String(id.UniqueId()), - } - - if description, ok := d.GetOk("description"); ok { - in.Description = aws.String(description.(string)) - } - - out, err := conn.CreatePolicyTemplate(ctx, in) - if err != nil { - return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionCreating, ResNamePolicyTemplate, d.Get("policy_store_id").(string), err)...) - } - - if out == nil || out.PolicyStoreId == nil { - return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionCreating, ResNamePolicyTemplate, d.Get("policy_store_id").(string), errors.New("empty output"))...) - } - - d.SetId(fmt.Sprintf("%s:%s", aws.ToString(out.PolicyStoreId), aws.ToString(out.PolicyTemplateId))) - - return append(diags, resourcePolicyTemplateRead(ctx, d, meta)...) -} - -func resourcePolicyTemplateRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).VerifiedPermissionsClient(ctx) - - policyStoreID, policyTemplateID, err := PolicyTemplateParseID(d.Id()) - if err != nil { - return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionReading, ResNamePolicyTemplate, d.Id(), err)...) - } - - out, err := findPolicyTemplateByID(ctx, conn, policyStoreID, policyTemplateID) - - if !d.IsNewResource() && tfresource.NotFound(err) { - log.Printf("[WARN] VerifiedPermissions PolicyTemplate (%s) not found, removing from state", d.Id()) - d.SetId("") - return diags - } - - if err != nil { - return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionReading, ResNamePolicyTemplate, d.Id(), err)...) - } - - d.Set("policy_store_id", out.PolicyStoreId) - d.Set("created_date", out.CreatedDate.Format(time.RFC3339Nano)) - d.Set("last_updated_date", out.LastUpdatedDate.Format(time.RFC3339Nano)) - d.Set("description", out.Description) - d.Set("statement", out.Statement) - d.Set("policy_template_id", out.PolicyTemplateId) - - return diags -} - -func resourcePolicyTemplateUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).VerifiedPermissionsClient(ctx) - - update := false - - policyStoreId, policyTemplateID, err := PolicyTemplateParseID(d.Id()) - if err != nil { - return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionUpdating, ResNamePolicyTemplate, d.Id(), err)...) - } - - in := &verifiedpermissions.UpdatePolicyTemplateInput{ - PolicyStoreId: aws.String(policyStoreId), - PolicyTemplateId: aws.String(policyTemplateID), - } - - if d.HasChanges("statement") { - in.Statement = aws.String(d.Get("statement").(string)) - update = true - } - - if d.HasChanges("description") { - in.Description = aws.String(d.Get("description").(string)) - update = true - } - - if !update { - return diags - } - - log.Printf("[DEBUG] Updating VerifiedPermissions PolicyTemplate (%s): %#v", d.Id(), in) - _, err = conn.UpdatePolicyTemplate(ctx, in) - if err != nil { - return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionUpdating, ResNamePolicyTemplate, d.Id(), err)...) - } - - return append(diags, resourcePolicyTemplateRead(ctx, d, meta)...) -} - -func resourcePolicyTemplateDelete(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 PolicyTemplate %s", d.Id()) - - policyStoreId, policyTemplateID, err := PolicyTemplateParseID(d.Id()) - if err != nil { - return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionDeleting, ResNamePolicyTemplate, d.Id(), err)...) - } - - _, err = conn.DeletePolicyTemplate(ctx, &verifiedpermissions.DeletePolicyTemplateInput{ - PolicyStoreId: aws.String(policyStoreId), - PolicyTemplateId: aws.String(policyTemplateID), - }) - - if errs.IsA[*types.ResourceNotFoundException](err) { - return diags - } - if err != nil { - return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionDeleting, ResNamePolicyTemplate, d.Id(), err)...) - } - - return diags -} - -func findPolicyTemplateByID(ctx context.Context, conn *verifiedpermissions.Client, policyStoreId, id string) (*verifiedpermissions.GetPolicyTemplateOutput, error) { - in := &verifiedpermissions.GetPolicyTemplateInput{ - PolicyStoreId: aws.String(policyStoreId), - PolicyTemplateId: aws.String(id), - } - out, err := conn.GetPolicyTemplate(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.PolicyStoreId == nil { - return nil, tfresource.NewEmptyResultError(in) - } - - return out, nil -} - -func PolicyTemplateParseID(id string) (string, string, error) { - parts := strings.Split(id, ":") - - if len(parts) == 2 && parts[0] != "" && parts[1] != "" { - return parts[0], parts[1], nil - } - - return "", "", fmt.Errorf("unexpected format for ID (%s), expected POLICY-STORE-ID:POLICY-TEMPLATE-ID", id) -} +//import ( +// "context" +// "errors" +// "fmt" +// "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-provider-aws/internal/conns" +// "github.com/hashicorp/terraform-provider-aws/internal/create" +// "github.com/hashicorp/terraform-provider-aws/internal/errs" +// "github.com/hashicorp/terraform-provider-aws/internal/tfresource" +// "github.com/hashicorp/terraform-provider-aws/names" +//) +// +//// @SDKResource("aws_verifiedpermissions_policy_template", name="Policy Template") +//func ResourcePolicyTemplate() *schema.Resource { +// return &schema.Resource{ +// CreateWithoutTimeout: resourcePolicyTemplateCreate, +// ReadWithoutTimeout: resourcePolicyTemplateRead, +// UpdateWithoutTimeout: resourcePolicyTemplateUpdate, +// DeleteWithoutTimeout: resourcePolicyTemplateDelete, +// +// Importer: &schema.ResourceImporter{ +// StateContext: schema.ImportStatePassthroughContext, +// }, +// +// Timeouts: &schema.ResourceTimeout{ +// Create: schema.DefaultTimeout(30 * time.Minute), +// Update: schema.DefaultTimeout(30 * time.Minute), +// Delete: schema.DefaultTimeout(30 * time.Minute), +// }, +// +// Schema: map[string]*schema.Schema{ +// "policy_template_id": { +// Type: schema.TypeString, +// Computed: true, +// }, +// "policy_store_id": { +// Type: schema.TypeString, +// ForceNew: true, +// Required: true, +// }, +// "description": { +// Type: schema.TypeString, +// Optional: true, +// }, +// "statement": { +// Type: schema.TypeString, +// Required: true, +// }, +// "created_date": { +// Type: schema.TypeString, +// Computed: true, +// }, +// "last_updated_date": { +// Type: schema.TypeString, +// Computed: true, +// }, +// }, +// } +//} +// +//func resourcePolicyTemplateCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { +// var diags diag.Diagnostics +// conn := meta.(*conns.AWSClient).VerifiedPermissionsClient(ctx) +// +// in := &verifiedpermissions.CreatePolicyTemplateInput{ +// PolicyStoreId: aws.String(d.Get("policy_store_id").(string)), +// Statement: aws.String(d.Get("statement").(string)), +// ClientToken: aws.String(id.UniqueId()), +// } +// +// if description, ok := d.GetOk("description"); ok { +// in.Description = aws.String(description.(string)) +// } +// +// out, err := conn.CreatePolicyTemplate(ctx, in) +// if err != nil { +// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionCreating, ResNamePolicyTemplate, d.Get("policy_store_id").(string), err)...) +// } +// +// if out == nil || out.PolicyStoreId == nil { +// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionCreating, ResNamePolicyTemplate, d.Get("policy_store_id").(string), errors.New("empty output"))...) +// } +// +// d.SetId(fmt.Sprintf("%s:%s", aws.ToString(out.PolicyStoreId), aws.ToString(out.PolicyTemplateId))) +// +// return append(diags, resourcePolicyTemplateRead(ctx, d, meta)...) +//} +// +//func resourcePolicyTemplateRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { +// var diags diag.Diagnostics +// conn := meta.(*conns.AWSClient).VerifiedPermissionsClient(ctx) +// +// policyStoreID, policyTemplateID, err := policyTemplateParseID(d.Id()) +// if err != nil { +// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionReading, ResNamePolicyTemplate, d.Id(), err)...) +// } +// +// out, err := findPolicyTemplateByID(ctx, conn, policyStoreID, policyTemplateID) +// +// if !d.IsNewResource() && tfresource.NotFound(err) { +// log.Printf("[WARN] VerifiedPermissions PolicyTemplate (%s) not found, removing from state", d.Id()) +// d.SetId("") +// return diags +// } +// +// if err != nil { +// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionReading, ResNamePolicyTemplate, d.Id(), err)...) +// } +// +// d.Set("policy_store_id", out.PolicyStoreId) +// d.Set("created_date", out.CreatedDate.Format(time.RFC3339Nano)) +// d.Set("last_updated_date", out.LastUpdatedDate.Format(time.RFC3339Nano)) +// d.Set("description", out.Description) +// d.Set("statement", out.Statement) +// d.Set("policy_template_id", out.PolicyTemplateId) +// +// return diags +//} +// +//func resourcePolicyTemplateUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { +// var diags diag.Diagnostics +// conn := meta.(*conns.AWSClient).VerifiedPermissionsClient(ctx) +// +// update := false +// +// policyStoreId, policyTemplateID, err := policyTemplateParseID(d.Id()) +// if err != nil { +// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionUpdating, ResNamePolicyTemplate, d.Id(), err)...) +// } +// +// in := &verifiedpermissions.UpdatePolicyTemplateInput{ +// PolicyStoreId: aws.String(policyStoreId), +// PolicyTemplateId: aws.String(policyTemplateID), +// } +// +// if d.HasChanges("statement") { +// in.Statement = aws.String(d.Get("statement").(string)) +// update = true +// } +// +// if d.HasChanges("description") { +// in.Description = aws.String(d.Get("description").(string)) +// update = true +// } +// +// if !update { +// return diags +// } +// +// log.Printf("[DEBUG] Updating VerifiedPermissions PolicyTemplate (%s): %#v", d.Id(), in) +// _, err = conn.UpdatePolicyTemplate(ctx, in) +// if err != nil { +// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionUpdating, ResNamePolicyTemplate, d.Id(), err)...) +// } +// +// return append(diags, resourcePolicyTemplateRead(ctx, d, meta)...) +//} +// +//func resourcePolicyTemplateDelete(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 PolicyTemplate %s", d.Id()) +// +// policyStoreId, policyTemplateID, err := policyTemplateParseID(d.Id()) +// if err != nil { +// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionDeleting, ResNamePolicyTemplate, d.Id(), err)...) +// } +// +// _, err = conn.DeletePolicyTemplate(ctx, &verifiedpermissions.DeletePolicyTemplateInput{ +// PolicyStoreId: aws.String(policyStoreId), +// PolicyTemplateId: aws.String(policyTemplateID), +// }) +// +// if errs.IsA[*types.ResourceNotFoundException](err) { +// return diags +// } +// if err != nil { +// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionDeleting, ResNamePolicyTemplate, d.Id(), err)...) +// } +// +// return diags +//} +// diff --git a/internal/service/verifiedpermissions/policy_template_fw.go b/internal/service/verifiedpermissions/policy_template_fw.go new file mode 100644 index 00000000000..9e546aebef2 --- /dev/null +++ b/internal/service/verifiedpermissions/policy_template_fw.go @@ -0,0 +1,288 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package verifiedpermissions + +import ( + "context" + "fmt" + "strings" + + "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/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-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/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" + + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/framework" +) + +// @FrameworkResource(name="Policy Template") +func newResourcePolicyTemplate(context.Context) (resource.ResourceWithConfigure, error) { + r := &resourcePolicyTemplate{} + + return r, nil +} + +const ( + ResNamePolicyTemplate = "Policy Template" +) + +type resourcePolicyTemplate struct { + framework.ResourceWithConfigure + framework.WithImportByID +} + +func (r *resourcePolicyTemplate) Metadata(_ context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) { + response.TypeName = "aws_verifiedpermissions_policy_template" +} + +// Schema returns the schema for this resource. +func (r *resourcePolicyTemplate) Schema(ctx context.Context, request resource.SchemaRequest, response *resource.SchemaResponse) { + s := schema.Schema{ + Attributes: map[string]schema.Attribute{ + "created_date": schema.StringAttribute{ + CustomType: fwtypes.TimestampType, + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, + "description": schema.StringAttribute{ + Optional: true, + }, + "id": framework.IDAttribute(), + "policy_store_id": schema.StringAttribute{ + Required: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + }, + "policy_template_id": schema.StringAttribute{ + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, + "statement": schema.StringAttribute{ + Required: true, + }, + }, + } + + response.Schema = s +} + +func (r *resourcePolicyTemplate) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) { + conn := r.Meta().VerifiedPermissionsClient(ctx) + var plan resourcePolicyTemplateData + + response.Diagnostics.Append(request.Plan.Get(ctx, &plan)...) + + if response.Diagnostics.HasError() { + return + } + + input := &verifiedpermissions.CreatePolicyTemplateInput{} + response.Diagnostics.Append(flex.Expand(ctx, plan, input)...) + + if response.Diagnostics.HasError() { + return + } + + input.ClientToken = aws.String(id.UniqueId()) + + output, err := conn.CreatePolicyTemplate(ctx, input) + + if err != nil { + response.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionCreating, ResNamePolicyTemplate, plan.PolicyStoreID.ValueString(), err), + err.Error(), + ) + return + } + + state := plan + state.ID = flex.StringValueToFramework(ctx, fmt.Sprintf("%s:%s", aws.ToString(output.PolicyStoreId), aws.ToString(output.PolicyTemplateId))) + + response.Diagnostics.Append(flex.Flatten(ctx, output, &state)...) + + if response.Diagnostics.HasError() { + return + } + + response.Diagnostics.Append(response.State.Set(ctx, &state)...) +} + +func (r *resourcePolicyTemplate) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) { + conn := r.Meta().VerifiedPermissionsClient(ctx) + var state resourcePolicyTemplateData + + response.Diagnostics.Append(request.State.Get(ctx, &state)...) + + if response.Diagnostics.HasError() { + return + } + + policyStoreID, policyTemplateID, err := policyTemplateParseID(state.ID.ValueString()) + if err != nil { + response.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionReading, ResNamePolicyTemplate, state.ID.ValueString(), err), + err.Error(), + ) + return + } + + output, err := findPolicyTemplateByID(ctx, conn, policyStoreID, policyTemplateID) + + if tfresource.NotFound(err) { + response.State.RemoveResource(ctx) + return + } + + if err != nil { + response.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionReading, ResNamePolicyTemplate, state.ID.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)...) +} + +// Update is called to update the state of the resource. +// Config, planned state, and prior state values should be read from the UpdateRequest and new state values set on the UpdateResponse. +func (r *resourcePolicyTemplate) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) { + conn := r.Meta().VerifiedPermissionsClient(ctx) + var state, plan resourcePolicyTemplateData + + 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.Statement.Equal(state.Statement) { + input := &verifiedpermissions.UpdatePolicyTemplateInput{} + response.Diagnostics.Append(flex.Expand(ctx, plan, input)...) + + if response.Diagnostics.HasError() { + return + } + + output, err := conn.UpdatePolicyTemplate(ctx, input) + + if err != nil { + response.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionUpdating, ResNamePolicyTemplate, state.ID.ValueString(), err), + err.Error(), + ) + return + } + + response.Diagnostics.Append(flex.Flatten(ctx, output, &plan)...) + } + + response.Diagnostics.Append(response.State.Set(ctx, &plan)...) +} + +func (r *resourcePolicyTemplate) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) { + conn := r.Meta().VerifiedPermissionsClient(ctx) + var state resourcePolicyTemplateData + + response.Diagnostics.Append(request.State.Get(ctx, &state)...) + + if response.Diagnostics.HasError() { + return + } + + tflog.Debug(ctx, "deleting Verified Permissions Policy Template", map[string]interface{}{ + "id": state.ID.ValueString(), + }) + + input := &verifiedpermissions.DeletePolicyTemplateInput{ + PolicyStoreId: aws.String(state.PolicyStoreID.ValueString()), + PolicyTemplateId: aws.String(state.PolicyTemplateID.ValueString()), + } + + _, err := conn.DeletePolicyTemplate(ctx, input) + + if errs.IsA[*awstypes.ResourceNotFoundException](err) { + return + } + + if err != nil { + response.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionDeleting, ResNamePolicyTemplate, state.ID.ValueString(), err), + err.Error(), + ) + return + } +} + +type resourcePolicyTemplateData struct { + CreatedDate fwtypes.Timestamp `tfsdk:"created_date"` + Description types.String `tfsdk:"description"` + ID types.String `tfsdk:"id"` + PolicyStoreID types.String `tfsdk:"policy_store_id"` + PolicyTemplateID types.String `tfsdk:"policy_template_id"` + Statement types.String `tfsdk:"statement"` +} + +func findPolicyTemplateByID(ctx context.Context, conn *verifiedpermissions.Client, policyStoreId, id string) (*verifiedpermissions.GetPolicyTemplateOutput, error) { + in := &verifiedpermissions.GetPolicyTemplateInput{ + PolicyStoreId: aws.String(policyStoreId), + PolicyTemplateId: aws.String(id), + } + out, err := conn.GetPolicyTemplate(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.PolicyStoreId == nil { + return nil, tfresource.NewEmptyResultError(in) + } + + return out, nil +} + +func policyTemplateParseID(id string) (string, string, error) { + parts := strings.Split(id, ":") + + if len(parts) == 2 && parts[0] != "" && parts[1] != "" { + return parts[0], parts[1], nil + } + + return "", "", fmt.Errorf("unexpected format for ID (%s), expected POLICY-STORE-ID:POLICY-TEMPLATE-ID", id) +} diff --git a/internal/service/verifiedpermissions/policy_template_test.go b/internal/service/verifiedpermissions/policy_template_test.go index 464f15cc131..dc366ce6f0d 100644 --- a/internal/service/verifiedpermissions/policy_template_test.go +++ b/internal/service/verifiedpermissions/policy_template_test.go @@ -86,7 +86,7 @@ func TestAccVerifiedPermissionsPolicyTemplate_disappears(t *testing.T) { Config: testAccPolicyTemplateConfig_basic(`permit (principal in ?principal, action in PhotoFlash::Action::"FullPhotoAccess", resource == ?resource) unless { resource.IsPrivate };`, ""), Check: resource.ComposeTestCheckFunc( testAccCheckPolicyTemplateExists(ctx, resourceName, &policytemplate), - acctest.CheckResourceDisappears(ctx, acctest.Provider, tfverifiedpermissions.ResourcePolicyTemplate(), resourceName), + acctest.CheckFrameworkResourceDisappears(ctx, acctest.Provider, tfverifiedpermissions.ResourcePolicyTemplate, resourceName), ), ExpectNonEmptyPlan: true, }, diff --git a/internal/service/verifiedpermissions/service_package_gen.go b/internal/service/verifiedpermissions/service_package_gen.go index fe412e04b31..2c61c23e615 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: newResourcePolicyTemplate, + Name: "Policy Template", + }, { Factory: newResourceSchema, Name: "Schema", @@ -41,13 +45,7 @@ func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePac } func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePackageSDKResource { - return []*types.ServicePackageSDKResource{ - { - Factory: ResourcePolicyTemplate, - TypeName: "aws_verifiedpermissions_policy_template", - Name: "Policy Template", - }, - } + return []*types.ServicePackageSDKResource{} } func (p *servicePackage) ServicePackageName() string { From 4497c9664529c457b38fab5f543afa29f30bc91a Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Mon, 8 Jan 2024 16:05:50 -0600 Subject: [PATCH 4/9] rename file --- .../verifiedpermissions/policy_template.go | 474 +++++++++++------- .../verifiedpermissions/policy_template_fw.go | 288 ----------- 2 files changed, 281 insertions(+), 481 deletions(-) delete mode 100644 internal/service/verifiedpermissions/policy_template_fw.go diff --git a/internal/service/verifiedpermissions/policy_template.go b/internal/service/verifiedpermissions/policy_template.go index c0ebdcfe122..fa454328de6 100644 --- a/internal/service/verifiedpermissions/policy_template.go +++ b/internal/service/verifiedpermissions/policy_template.go @@ -3,196 +3,284 @@ package verifiedpermissions -//import ( -// "context" -// "errors" -// "fmt" -// "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-provider-aws/internal/conns" -// "github.com/hashicorp/terraform-provider-aws/internal/create" -// "github.com/hashicorp/terraform-provider-aws/internal/errs" -// "github.com/hashicorp/terraform-provider-aws/internal/tfresource" -// "github.com/hashicorp/terraform-provider-aws/names" -//) -// -//// @SDKResource("aws_verifiedpermissions_policy_template", name="Policy Template") -//func ResourcePolicyTemplate() *schema.Resource { -// return &schema.Resource{ -// CreateWithoutTimeout: resourcePolicyTemplateCreate, -// ReadWithoutTimeout: resourcePolicyTemplateRead, -// UpdateWithoutTimeout: resourcePolicyTemplateUpdate, -// DeleteWithoutTimeout: resourcePolicyTemplateDelete, -// -// Importer: &schema.ResourceImporter{ -// StateContext: schema.ImportStatePassthroughContext, -// }, -// -// Timeouts: &schema.ResourceTimeout{ -// Create: schema.DefaultTimeout(30 * time.Minute), -// Update: schema.DefaultTimeout(30 * time.Minute), -// Delete: schema.DefaultTimeout(30 * time.Minute), -// }, -// -// Schema: map[string]*schema.Schema{ -// "policy_template_id": { -// Type: schema.TypeString, -// Computed: true, -// }, -// "policy_store_id": { -// Type: schema.TypeString, -// ForceNew: true, -// Required: true, -// }, -// "description": { -// Type: schema.TypeString, -// Optional: true, -// }, -// "statement": { -// Type: schema.TypeString, -// Required: true, -// }, -// "created_date": { -// Type: schema.TypeString, -// Computed: true, -// }, -// "last_updated_date": { -// Type: schema.TypeString, -// Computed: true, -// }, -// }, -// } -//} -// -//func resourcePolicyTemplateCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { -// var diags diag.Diagnostics -// conn := meta.(*conns.AWSClient).VerifiedPermissionsClient(ctx) -// -// in := &verifiedpermissions.CreatePolicyTemplateInput{ -// PolicyStoreId: aws.String(d.Get("policy_store_id").(string)), -// Statement: aws.String(d.Get("statement").(string)), -// ClientToken: aws.String(id.UniqueId()), -// } -// -// if description, ok := d.GetOk("description"); ok { -// in.Description = aws.String(description.(string)) -// } -// -// out, err := conn.CreatePolicyTemplate(ctx, in) -// if err != nil { -// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionCreating, ResNamePolicyTemplate, d.Get("policy_store_id").(string), err)...) -// } -// -// if out == nil || out.PolicyStoreId == nil { -// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionCreating, ResNamePolicyTemplate, d.Get("policy_store_id").(string), errors.New("empty output"))...) -// } -// -// d.SetId(fmt.Sprintf("%s:%s", aws.ToString(out.PolicyStoreId), aws.ToString(out.PolicyTemplateId))) -// -// return append(diags, resourcePolicyTemplateRead(ctx, d, meta)...) -//} -// -//func resourcePolicyTemplateRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { -// var diags diag.Diagnostics -// conn := meta.(*conns.AWSClient).VerifiedPermissionsClient(ctx) -// -// policyStoreID, policyTemplateID, err := policyTemplateParseID(d.Id()) -// if err != nil { -// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionReading, ResNamePolicyTemplate, d.Id(), err)...) -// } -// -// out, err := findPolicyTemplateByID(ctx, conn, policyStoreID, policyTemplateID) -// -// if !d.IsNewResource() && tfresource.NotFound(err) { -// log.Printf("[WARN] VerifiedPermissions PolicyTemplate (%s) not found, removing from state", d.Id()) -// d.SetId("") -// return diags -// } -// -// if err != nil { -// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionReading, ResNamePolicyTemplate, d.Id(), err)...) -// } -// -// d.Set("policy_store_id", out.PolicyStoreId) -// d.Set("created_date", out.CreatedDate.Format(time.RFC3339Nano)) -// d.Set("last_updated_date", out.LastUpdatedDate.Format(time.RFC3339Nano)) -// d.Set("description", out.Description) -// d.Set("statement", out.Statement) -// d.Set("policy_template_id", out.PolicyTemplateId) -// -// return diags -//} -// -//func resourcePolicyTemplateUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { -// var diags diag.Diagnostics -// conn := meta.(*conns.AWSClient).VerifiedPermissionsClient(ctx) -// -// update := false -// -// policyStoreId, policyTemplateID, err := policyTemplateParseID(d.Id()) -// if err != nil { -// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionUpdating, ResNamePolicyTemplate, d.Id(), err)...) -// } -// -// in := &verifiedpermissions.UpdatePolicyTemplateInput{ -// PolicyStoreId: aws.String(policyStoreId), -// PolicyTemplateId: aws.String(policyTemplateID), -// } -// -// if d.HasChanges("statement") { -// in.Statement = aws.String(d.Get("statement").(string)) -// update = true -// } -// -// if d.HasChanges("description") { -// in.Description = aws.String(d.Get("description").(string)) -// update = true -// } -// -// if !update { -// return diags -// } -// -// log.Printf("[DEBUG] Updating VerifiedPermissions PolicyTemplate (%s): %#v", d.Id(), in) -// _, err = conn.UpdatePolicyTemplate(ctx, in) -// if err != nil { -// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionUpdating, ResNamePolicyTemplate, d.Id(), err)...) -// } -// -// return append(diags, resourcePolicyTemplateRead(ctx, d, meta)...) -//} -// -//func resourcePolicyTemplateDelete(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 PolicyTemplate %s", d.Id()) -// -// policyStoreId, policyTemplateID, err := policyTemplateParseID(d.Id()) -// if err != nil { -// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionDeleting, ResNamePolicyTemplate, d.Id(), err)...) -// } -// -// _, err = conn.DeletePolicyTemplate(ctx, &verifiedpermissions.DeletePolicyTemplateInput{ -// PolicyStoreId: aws.String(policyStoreId), -// PolicyTemplateId: aws.String(policyTemplateID), -// }) -// -// if errs.IsA[*types.ResourceNotFoundException](err) { -// return diags -// } -// if err != nil { -// return append(diags, create.DiagError(names.VerifiedPermissions, create.ErrActionDeleting, ResNamePolicyTemplate, d.Id(), err)...) -// } -// -// return diags -//} -// +import ( + "context" + "fmt" + "strings" + + "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/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-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/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" + + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/framework" +) + +// @FrameworkResource(name="Policy Template") +func newResourcePolicyTemplate(context.Context) (resource.ResourceWithConfigure, error) { + r := &resourcePolicyTemplate{} + + return r, nil +} + +const ( + ResNamePolicyTemplate = "Policy Template" +) + +type resourcePolicyTemplate struct { + framework.ResourceWithConfigure + framework.WithImportByID +} + +func (r *resourcePolicyTemplate) Metadata(_ context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) { + response.TypeName = "aws_verifiedpermissions_policy_template" +} + +// Schema returns the schema for this resource. +func (r *resourcePolicyTemplate) Schema(ctx context.Context, request resource.SchemaRequest, response *resource.SchemaResponse) { + s := schema.Schema{ + Attributes: map[string]schema.Attribute{ + "created_date": schema.StringAttribute{ + CustomType: fwtypes.TimestampType, + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, + "description": schema.StringAttribute{ + Optional: true, + }, + "id": framework.IDAttribute(), + "policy_store_id": schema.StringAttribute{ + Required: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + }, + "policy_template_id": schema.StringAttribute{ + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, + "statement": schema.StringAttribute{ + Required: true, + }, + }, + } + + response.Schema = s +} + +func (r *resourcePolicyTemplate) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) { + conn := r.Meta().VerifiedPermissionsClient(ctx) + var plan resourcePolicyTemplateData + + response.Diagnostics.Append(request.Plan.Get(ctx, &plan)...) + + if response.Diagnostics.HasError() { + return + } + + input := &verifiedpermissions.CreatePolicyTemplateInput{} + response.Diagnostics.Append(flex.Expand(ctx, plan, input)...) + + if response.Diagnostics.HasError() { + return + } + + input.ClientToken = aws.String(id.UniqueId()) + + output, err := conn.CreatePolicyTemplate(ctx, input) + + if err != nil { + response.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionCreating, ResNamePolicyTemplate, plan.PolicyStoreID.ValueString(), err), + err.Error(), + ) + return + } + + state := plan + state.ID = flex.StringValueToFramework(ctx, fmt.Sprintf("%s:%s", aws.ToString(output.PolicyStoreId), aws.ToString(output.PolicyTemplateId))) + + response.Diagnostics.Append(flex.Flatten(ctx, output, &state)...) + + if response.Diagnostics.HasError() { + return + } + + response.Diagnostics.Append(response.State.Set(ctx, &state)...) +} + +func (r *resourcePolicyTemplate) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) { + conn := r.Meta().VerifiedPermissionsClient(ctx) + var state resourcePolicyTemplateData + + response.Diagnostics.Append(request.State.Get(ctx, &state)...) + + if response.Diagnostics.HasError() { + return + } + + policyStoreID, policyTemplateID, err := policyTemplateParseID(state.ID.ValueString()) + if err != nil { + response.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionReading, ResNamePolicyTemplate, state.ID.ValueString(), err), + err.Error(), + ) + return + } + + output, err := findPolicyTemplateByID(ctx, conn, policyStoreID, policyTemplateID) + + if tfresource.NotFound(err) { + response.State.RemoveResource(ctx) + return + } + + if err != nil { + response.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionReading, ResNamePolicyTemplate, state.ID.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 *resourcePolicyTemplate) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) { + conn := r.Meta().VerifiedPermissionsClient(ctx) + var state, plan resourcePolicyTemplateData + + 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.Statement.Equal(state.Statement) { + input := &verifiedpermissions.UpdatePolicyTemplateInput{} + response.Diagnostics.Append(flex.Expand(ctx, plan, input)...) + + if response.Diagnostics.HasError() { + return + } + + output, err := conn.UpdatePolicyTemplate(ctx, input) + + if err != nil { + response.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionUpdating, ResNamePolicyTemplate, state.ID.ValueString(), err), + err.Error(), + ) + return + } + + response.Diagnostics.Append(flex.Flatten(ctx, output, &plan)...) + } + + response.Diagnostics.Append(response.State.Set(ctx, &plan)...) +} + +func (r *resourcePolicyTemplate) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) { + conn := r.Meta().VerifiedPermissionsClient(ctx) + var state resourcePolicyTemplateData + + response.Diagnostics.Append(request.State.Get(ctx, &state)...) + + if response.Diagnostics.HasError() { + return + } + + tflog.Debug(ctx, "deleting Verified Permissions Policy Template", map[string]interface{}{ + "id": state.ID.ValueString(), + }) + + input := &verifiedpermissions.DeletePolicyTemplateInput{ + PolicyStoreId: aws.String(state.PolicyStoreID.ValueString()), + PolicyTemplateId: aws.String(state.PolicyTemplateID.ValueString()), + } + + _, err := conn.DeletePolicyTemplate(ctx, input) + + if errs.IsA[*awstypes.ResourceNotFoundException](err) { + return + } + + if err != nil { + response.Diagnostics.AddError( + create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionDeleting, ResNamePolicyTemplate, state.ID.ValueString(), err), + err.Error(), + ) + return + } +} + +type resourcePolicyTemplateData struct { + CreatedDate fwtypes.Timestamp `tfsdk:"created_date"` + Description types.String `tfsdk:"description"` + ID types.String `tfsdk:"id"` + PolicyStoreID types.String `tfsdk:"policy_store_id"` + PolicyTemplateID types.String `tfsdk:"policy_template_id"` + Statement types.String `tfsdk:"statement"` +} + +func findPolicyTemplateByID(ctx context.Context, conn *verifiedpermissions.Client, policyStoreId, id string) (*verifiedpermissions.GetPolicyTemplateOutput, error) { + in := &verifiedpermissions.GetPolicyTemplateInput{ + PolicyStoreId: aws.String(policyStoreId), + PolicyTemplateId: aws.String(id), + } + out, err := conn.GetPolicyTemplate(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.PolicyStoreId == nil { + return nil, tfresource.NewEmptyResultError(in) + } + + return out, nil +} + +func policyTemplateParseID(id string) (string, string, error) { + parts := strings.Split(id, ":") + + if len(parts) == 2 && parts[0] != "" && parts[1] != "" { + return parts[0], parts[1], nil + } + + return "", "", fmt.Errorf("unexpected format for ID (%s), expected POLICY-STORE-ID:POLICY-TEMPLATE-ID", id) +} diff --git a/internal/service/verifiedpermissions/policy_template_fw.go b/internal/service/verifiedpermissions/policy_template_fw.go deleted file mode 100644 index 9e546aebef2..00000000000 --- a/internal/service/verifiedpermissions/policy_template_fw.go +++ /dev/null @@ -1,288 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package verifiedpermissions - -import ( - "context" - "fmt" - "strings" - - "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/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-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/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" - - "github.com/hashicorp/terraform-plugin-framework/types" - "github.com/hashicorp/terraform-plugin-log/tflog" - "github.com/hashicorp/terraform-provider-aws/internal/framework" -) - -// @FrameworkResource(name="Policy Template") -func newResourcePolicyTemplate(context.Context) (resource.ResourceWithConfigure, error) { - r := &resourcePolicyTemplate{} - - return r, nil -} - -const ( - ResNamePolicyTemplate = "Policy Template" -) - -type resourcePolicyTemplate struct { - framework.ResourceWithConfigure - framework.WithImportByID -} - -func (r *resourcePolicyTemplate) Metadata(_ context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) { - response.TypeName = "aws_verifiedpermissions_policy_template" -} - -// Schema returns the schema for this resource. -func (r *resourcePolicyTemplate) Schema(ctx context.Context, request resource.SchemaRequest, response *resource.SchemaResponse) { - s := schema.Schema{ - Attributes: map[string]schema.Attribute{ - "created_date": schema.StringAttribute{ - CustomType: fwtypes.TimestampType, - Computed: true, - PlanModifiers: []planmodifier.String{ - stringplanmodifier.UseStateForUnknown(), - }, - }, - "description": schema.StringAttribute{ - Optional: true, - }, - "id": framework.IDAttribute(), - "policy_store_id": schema.StringAttribute{ - Required: true, - PlanModifiers: []planmodifier.String{ - stringplanmodifier.RequiresReplace(), - }, - }, - "policy_template_id": schema.StringAttribute{ - Computed: true, - PlanModifiers: []planmodifier.String{ - stringplanmodifier.UseStateForUnknown(), - }, - }, - "statement": schema.StringAttribute{ - Required: true, - }, - }, - } - - response.Schema = s -} - -func (r *resourcePolicyTemplate) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) { - conn := r.Meta().VerifiedPermissionsClient(ctx) - var plan resourcePolicyTemplateData - - response.Diagnostics.Append(request.Plan.Get(ctx, &plan)...) - - if response.Diagnostics.HasError() { - return - } - - input := &verifiedpermissions.CreatePolicyTemplateInput{} - response.Diagnostics.Append(flex.Expand(ctx, plan, input)...) - - if response.Diagnostics.HasError() { - return - } - - input.ClientToken = aws.String(id.UniqueId()) - - output, err := conn.CreatePolicyTemplate(ctx, input) - - if err != nil { - response.Diagnostics.AddError( - create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionCreating, ResNamePolicyTemplate, plan.PolicyStoreID.ValueString(), err), - err.Error(), - ) - return - } - - state := plan - state.ID = flex.StringValueToFramework(ctx, fmt.Sprintf("%s:%s", aws.ToString(output.PolicyStoreId), aws.ToString(output.PolicyTemplateId))) - - response.Diagnostics.Append(flex.Flatten(ctx, output, &state)...) - - if response.Diagnostics.HasError() { - return - } - - response.Diagnostics.Append(response.State.Set(ctx, &state)...) -} - -func (r *resourcePolicyTemplate) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) { - conn := r.Meta().VerifiedPermissionsClient(ctx) - var state resourcePolicyTemplateData - - response.Diagnostics.Append(request.State.Get(ctx, &state)...) - - if response.Diagnostics.HasError() { - return - } - - policyStoreID, policyTemplateID, err := policyTemplateParseID(state.ID.ValueString()) - if err != nil { - response.Diagnostics.AddError( - create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionReading, ResNamePolicyTemplate, state.ID.ValueString(), err), - err.Error(), - ) - return - } - - output, err := findPolicyTemplateByID(ctx, conn, policyStoreID, policyTemplateID) - - if tfresource.NotFound(err) { - response.State.RemoveResource(ctx) - return - } - - if err != nil { - response.Diagnostics.AddError( - create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionReading, ResNamePolicyTemplate, state.ID.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)...) -} - -// Update is called to update the state of the resource. -// Config, planned state, and prior state values should be read from the UpdateRequest and new state values set on the UpdateResponse. -func (r *resourcePolicyTemplate) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) { - conn := r.Meta().VerifiedPermissionsClient(ctx) - var state, plan resourcePolicyTemplateData - - 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.Statement.Equal(state.Statement) { - input := &verifiedpermissions.UpdatePolicyTemplateInput{} - response.Diagnostics.Append(flex.Expand(ctx, plan, input)...) - - if response.Diagnostics.HasError() { - return - } - - output, err := conn.UpdatePolicyTemplate(ctx, input) - - if err != nil { - response.Diagnostics.AddError( - create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionUpdating, ResNamePolicyTemplate, state.ID.ValueString(), err), - err.Error(), - ) - return - } - - response.Diagnostics.Append(flex.Flatten(ctx, output, &plan)...) - } - - response.Diagnostics.Append(response.State.Set(ctx, &plan)...) -} - -func (r *resourcePolicyTemplate) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) { - conn := r.Meta().VerifiedPermissionsClient(ctx) - var state resourcePolicyTemplateData - - response.Diagnostics.Append(request.State.Get(ctx, &state)...) - - if response.Diagnostics.HasError() { - return - } - - tflog.Debug(ctx, "deleting Verified Permissions Policy Template", map[string]interface{}{ - "id": state.ID.ValueString(), - }) - - input := &verifiedpermissions.DeletePolicyTemplateInput{ - PolicyStoreId: aws.String(state.PolicyStoreID.ValueString()), - PolicyTemplateId: aws.String(state.PolicyTemplateID.ValueString()), - } - - _, err := conn.DeletePolicyTemplate(ctx, input) - - if errs.IsA[*awstypes.ResourceNotFoundException](err) { - return - } - - if err != nil { - response.Diagnostics.AddError( - create.ProblemStandardMessage(names.VerifiedPermissions, create.ErrActionDeleting, ResNamePolicyTemplate, state.ID.ValueString(), err), - err.Error(), - ) - return - } -} - -type resourcePolicyTemplateData struct { - CreatedDate fwtypes.Timestamp `tfsdk:"created_date"` - Description types.String `tfsdk:"description"` - ID types.String `tfsdk:"id"` - PolicyStoreID types.String `tfsdk:"policy_store_id"` - PolicyTemplateID types.String `tfsdk:"policy_template_id"` - Statement types.String `tfsdk:"statement"` -} - -func findPolicyTemplateByID(ctx context.Context, conn *verifiedpermissions.Client, policyStoreId, id string) (*verifiedpermissions.GetPolicyTemplateOutput, error) { - in := &verifiedpermissions.GetPolicyTemplateInput{ - PolicyStoreId: aws.String(policyStoreId), - PolicyTemplateId: aws.String(id), - } - out, err := conn.GetPolicyTemplate(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.PolicyStoreId == nil { - return nil, tfresource.NewEmptyResultError(in) - } - - return out, nil -} - -func policyTemplateParseID(id string) (string, string, error) { - parts := strings.Split(id, ":") - - if len(parts) == 2 && parts[0] != "" && parts[1] != "" { - return parts[0], parts[1], nil - } - - return "", "", fmt.Errorf("unexpected format for ID (%s), expected POLICY-STORE-ID:POLICY-TEMPLATE-ID", id) -} From 7d025c7eb13ee3eb8a85a559891062504ca760d9 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Mon, 8 Jan 2024 16:13:45 -0600 Subject: [PATCH 5/9] aws_verifiedpermissions_policy_template: fmt --- internal/service/verifiedpermissions/policy_template.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/internal/service/verifiedpermissions/policy_template.go b/internal/service/verifiedpermissions/policy_template.go index fa454328de6..c675af2c8e6 100644 --- a/internal/service/verifiedpermissions/policy_template.go +++ b/internal/service/verifiedpermissions/policy_template.go @@ -15,18 +15,17 @@ import ( "github.com/hashicorp/terraform-plugin-framework/resource/schema" "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/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" - - "github.com/hashicorp/terraform-plugin-framework/types" - "github.com/hashicorp/terraform-plugin-log/tflog" - "github.com/hashicorp/terraform-provider-aws/internal/framework" ) // @FrameworkResource(name="Policy Template") From ed3a6e280958dc05de8f8a5966e947f35494768c Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Mon, 8 Jan 2024 16:20:37 -0600 Subject: [PATCH 6/9] aws_verifiedpermissions_policy_template: add updates test --- .../verifiedpermissions/exports_test.go | 1 + .../policy_template_test.go | 57 +++++++++++++------ 2 files changed, 42 insertions(+), 16 deletions(-) diff --git a/internal/service/verifiedpermissions/exports_test.go b/internal/service/verifiedpermissions/exports_test.go index 2f7393764dc..728be6893c1 100644 --- a/internal/service/verifiedpermissions/exports_test.go +++ b/internal/service/verifiedpermissions/exports_test.go @@ -10,6 +10,7 @@ var ( ResourceSchema = newResourceSchema FindPolicyStoreByID = findPolicyStoreByID + FindPolicyTemplateByID = findPolicyTemplateByID FindSchemaByPolicyStoreID = findSchemaByPolicyStoreID ) diff --git a/internal/service/verifiedpermissions/policy_template_test.go b/internal/service/verifiedpermissions/policy_template_test.go index dc366ce6f0d..fe5a24549d6 100644 --- a/internal/service/verifiedpermissions/policy_template_test.go +++ b/internal/service/verifiedpermissions/policy_template_test.go @@ -10,14 +10,13 @@ import ( "testing" "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" ) @@ -33,9 +32,9 @@ func TestAccVerifiedPermissionsPolicyTemplate_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) }, - ErrorCheck: acctest.ErrorCheck(t, names.VerifiedPermissions), + ErrorCheck: acctest.ErrorCheck(t, names.VerifiedPermissionsEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckPolicyTemplateDestroy(ctx), Steps: []resource.TestStep{ @@ -52,6 +51,36 @@ func TestAccVerifiedPermissionsPolicyTemplate_basic(t *testing.T) { ImportState: true, ImportStateVerify: true, }, + }, + }) +} + +func TestAccVerifiedPermissionsPolicyTemplate_update(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var policytemplate verifiedpermissions.GetPolicyTemplateOutput + resourceName := "aws_verifiedpermissions_policy_template.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.VerifiedPermissionsEndpointID) + }, + ErrorCheck: acctest.ErrorCheck(t, names.VerifiedPermissionsEndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckPolicyTemplateDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccPolicyTemplateConfig_basic("permit (principal in ?principal, action in PhotoFlash::Action::\"FullPhotoAccess\", resource == ?resource) unless { resource.IsPrivate };", ""), + Check: resource.ComposeTestCheckFunc( + testAccCheckPolicyTemplateExists(ctx, resourceName, &policytemplate), + resource.TestCheckResourceAttr(resourceName, "statement", "permit (principal in ?principal, action in PhotoFlash::Action::\"FullPhotoAccess\", resource == ?resource) unless { resource.IsPrivate };"), + resource.TestCheckResourceAttr(resourceName, "description", ""), + ), + }, { Config: testAccPolicyTemplateConfig_basic("permit (principal in ?principal, action in PhotoFlash::Action::\"FullPhotoAccess\", resource == ?resource);", "test"), Check: resource.ComposeTestCheckFunc( @@ -76,9 +105,9 @@ func TestAccVerifiedPermissionsPolicyTemplate_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) }, - ErrorCheck: acctest.ErrorCheck(t, names.VerifiedPermissions), + ErrorCheck: acctest.ErrorCheck(t, names.VerifiedPermissionsEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckPolicyTemplateDestroy(ctx), Steps: []resource.TestStep{ @@ -107,13 +136,12 @@ func testAccCheckPolicyTemplateDestroy(ctx context.Context) resource.TestCheckFu return create.Error(names.VerifiedPermissions, create.ErrActionCheckingDestroyed, tfverifiedpermissions.ResNamePolicyTemplate, rs.Primary.ID, err) } - _, err = conn.GetPolicyTemplate(ctx, &verifiedpermissions.GetPolicyTemplateInput{ - PolicyTemplateId: &policyTemplateID, - PolicyStoreId: &policyStoreID, - }) - if errs.IsA[*types.ResourceNotFoundException](err) { - return nil + _, err = tfverifiedpermissions.FindPolicyTemplateByID(ctx, conn, policyStoreID, policyTemplateID) + + if tfresource.NotFound(err) { + continue } + if err != nil { return err } @@ -142,10 +170,7 @@ func testAccCheckPolicyTemplateExists(ctx context.Context, name string, policyte } conn := acctest.Provider.Meta().(*conns.AWSClient).VerifiedPermissionsClient(ctx) - resp, err := conn.GetPolicyTemplate(ctx, &verifiedpermissions.GetPolicyTemplateInput{ - PolicyTemplateId: &policyTemplateID, - PolicyStoreId: &policyStoreID, - }) + resp, err := tfverifiedpermissions.FindPolicyTemplateByID(ctx, conn, policyStoreID, policyTemplateID) if err != nil { return create.Error(names.VerifiedPermissions, create.ErrActionCheckingExistence, tfverifiedpermissions.ResNamePolicyTemplate, rs.Primary.ID, err) From cf4006388b04b38608ec1213ca4a7748b23456d9 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Mon, 8 Jan 2024 16:25:42 -0600 Subject: [PATCH 7/9] aws_verifiedpermissions_policy_template: update documentation --- ...dpermissions_policy_template.html.markdown | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/website/docs/r/verifiedpermissions_policy_template.html.markdown b/website/docs/r/verifiedpermissions_policy_template.html.markdown index d983f5acd77..1626f47c8c3 100644 --- a/website/docs/r/verifiedpermissions_policy_template.html.markdown +++ b/website/docs/r/verifiedpermissions_policy_template.html.markdown @@ -15,41 +15,43 @@ Terraform resource for managing an AWS Verified Permissions Policy Template. ```terraform resource "aws_verifiedpermissions_policy_template" "example" { - policy_store_id = aws_verifiedpermissions_policy_store.test.id - - description = "" - statement = "" + policy_store_id = aws_verifiedpermissions_policy_store.example.id + + statement = "permit (principal in ?principal, action in PhotoFlash::Action::\"FullPhotoAccess\", resource == ?resource) unless { resource.IsPrivate };" } ``` ## Argument Reference -The following arguments are supported: +The following arguments are required: * `policy_store_id` - (Required) The ID of the Policy Store. * `statement` - (Required) Defines the content of the statement, written in Cedar policy language. + +The following arguments are optional: + * `description` - (Optional) Provides a description for the policy template. -## 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_template_id` - The ID of the Policy Store. * `created_date` - The date the Policy Store was created. -* `last_updated_date` - The date the Policy Store 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 Template can be imported using the `policy_store_id:policy_template_id`, e.g., +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:policy_template_id`. For example: +```terraform +import { + to = aws_verifiedpermissions_policy_template.example + id = "DxQg2j8xvXJQ1tQCYNWj9T:X19yzj8xvXJQ1tQCYNWj9T" +} ``` -$ terraform import aws_verifiedpermissions_policy_template.example policyStoreId:policyTemplateId + +Using `terraform import`, import Verified Permissions Policy Store using the `policy_store_id:policy_template_id`. For example: + +```console +% terraform import aws_verifiedpermissions_policy_template.example policyStoreId:policyTemplateId ``` From 343971d021f1b84556c0da4476e3975a5ec65544 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Mon, 8 Jan 2024 16:27:27 -0600 Subject: [PATCH 8/9] chore: linter --- .../docs/r/verifiedpermissions_policy_template.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/verifiedpermissions_policy_template.html.markdown b/website/docs/r/verifiedpermissions_policy_template.html.markdown index 1626f47c8c3..57ea01c0180 100644 --- a/website/docs/r/verifiedpermissions_policy_template.html.markdown +++ b/website/docs/r/verifiedpermissions_policy_template.html.markdown @@ -17,7 +17,7 @@ Terraform resource for managing an AWS Verified Permissions Policy Template. resource "aws_verifiedpermissions_policy_template" "example" { policy_store_id = aws_verifiedpermissions_policy_store.example.id - statement = "permit (principal in ?principal, action in PhotoFlash::Action::\"FullPhotoAccess\", resource == ?resource) unless { resource.IsPrivate };" + statement = "permit (principal in ?principal, action in PhotoFlash::Action::\"FullPhotoAccess\", resource == ?resource) unless { resource.IsPrivate };" } ``` From fd195a21e0581738ec995ddefe460d64b75c1dc0 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Mon, 8 Jan 2024 16:39:50 -0600 Subject: [PATCH 9/9] chore: linter --- .../docs/r/verifiedpermissions_policy_template.html.markdown | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/website/docs/r/verifiedpermissions_policy_template.html.markdown b/website/docs/r/verifiedpermissions_policy_template.html.markdown index 57ea01c0180..d836e15a8f2 100644 --- a/website/docs/r/verifiedpermissions_policy_template.html.markdown +++ b/website/docs/r/verifiedpermissions_policy_template.html.markdown @@ -16,8 +16,7 @@ Terraform resource for managing an AWS Verified Permissions Policy Template. ```terraform resource "aws_verifiedpermissions_policy_template" "example" { policy_store_id = aws_verifiedpermissions_policy_store.example.id - - statement = "permit (principal in ?principal, action in PhotoFlash::Action::\"FullPhotoAccess\", resource == ?resource) unless { resource.IsPrivate };" + statement = "permit (principal in ?principal, action in PhotoFlash::Action::\"FullPhotoAccess\", resource == ?resource) unless { resource.IsPrivate };" } ```