Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

f-DeleteUnusedFMManagedResources support for aws_fms_policy resource #21295

Merged
merged 31 commits into from
Feb 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
55e0cd4
added delete_unused_fms_resources enhancement to aws_fms_policy resource
Oct 13, 2021
36b0812
added changelog txt file
Oct 13, 2021
25a156c
updated changelog text file
Oct 13, 2021
69b3e8b
Generate list and update tag commands for fms policy using keyvalueta…
Victorp99 Oct 14, 2021
4eec3b7
Add tags and tags_all arguments to the fms policy resource.
Victorp99 Oct 14, 2021
373c555
Fix fms connection issue.
Victorp99 Oct 14, 2021
f8126ba
Add tests for new tags argument.
Victorp99 Oct 14, 2021
a77525e
Merge branch 'main' of github.com:Victorp99/terraform-provider-aws in…
Victorp99 Oct 14, 2021
d0e6d13
Update fms policy docs to include new tag attribute.
Victorp99 Oct 14, 2021
2802596
Add new changelog file.
Victorp99 Oct 14, 2021
7584309
Update fms policy tag code to work with new service restructure.
Victorp99 Oct 14, 2021
b214ede
Merge branch 'main' of github.com:hashicorp/terraform-provider-aws in…
zhelding Oct 15, 2021
cab10a1
Resolve merge conflicts from latest changes.
Victorp99 Oct 18, 2021
8d86181
Merge branch 'main' of github.com:Victorp99/terraform-provider-aws in…
Victorp99 Oct 21, 2021
4600ae1
Merge branch 'main' of github.com:Victorp99/terraform-provider-aws in…
Victorp99 Oct 21, 2021
627b183
Merge branch 'hashicorp:main' into f-aws_fms_policy_tags_enhancement
Victorp99 Oct 21, 2021
f721f75
Fix fms generate directives. Fix new tags tests.
Victorp99 Oct 28, 2021
a30e35c
Merge branch 'main' of github.com:Victorp99/terraform-provider-aws in…
Victorp99 Oct 28, 2021
0056f86
Merge branch 'f-aws_fms_policy_tags_enhancement' of github.com:Victor…
Victorp99 Oct 28, 2021
0ec25ed
Merge branch 'hashicorp:main' into f-aws_fms_policy_tags_enhancement
Victorp99 Nov 18, 2021
b338d01
Tweak CHANGELOG entry.
ewbankkit Dec 23, 2021
182c992
r/aws_fms_policy: 'delete_unused_fms_resources' -> 'delete_unused_fm_…
ewbankkit Dec 23, 2021
cdec28a
Merge branch 'main' into HEAD
ewbankkit Feb 17, 2022
e3b5538
r/aws_fms_policy: Alphabetize attributes.
ewbankkit Feb 17, 2022
22fbc4e
r/aws_fms_policy: Modernize.
ewbankkit Feb 17, 2022
1c9e097
r/aws_fms_policy: Acceptance tests can run in an Organization's manag…
ewbankkit Feb 17, 2022
5beb5ae
r/aws_fms_policy: All acceptance tests run in an Organization's manag…
ewbankkit Feb 17, 2022
15d151f
'testAccPolicy_tags' -> 'testAccPolicy_resourceTags'.
ewbankkit Feb 17, 2022
0ddf3be
Tweak CHANGELOG entry.
ewbankkit Feb 17, 2022
688fb7c
Merge remote-tracking branch 'origin/tmp-pr21299' into HEAD
ewbankkit Feb 17, 2022
92578c1
Tweak documentation.
ewbankkit Feb 17, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/21295.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/aws_fms_policy: Add `delete_unused_fm_managed_resources` argument
```
3 changes: 3 additions & 0 deletions .changelog/21299.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/aws_fms_policy: Add `tags` argument and `tags_all` attribute to support resource tagging
```
1 change: 1 addition & 0 deletions internal/service/fms/fms_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ func TestAccFMS_serial(t *testing.T) {
"cloudfrontDistribution": testAccPolicy_cloudFrontDistribution,
"includeMap": testAccPolicy_includeMap,
"update": testAccPolicy_update,
"resourceTags": testAccPolicy_resourceTags,
"tags": testAccPolicy_tags,
},
}
Expand Down
3 changes: 2 additions & 1 deletion internal/service/fms/generate.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//go:generate go run ../../generate/tags/main.go -ServiceTagsSlice -TagType=ResourceTag
//go:generate go run -tags generate ../../generate/tags/main.go -ListTags -ListTagsOp=ListTagsForResource -ListTagsInIDElem=ResourceArn -ListTagsOutTagsElem=TagList -ServiceTagsSlice -TagOp=TagResource -TagInTagsElem=TagList -TagInIDElem=ResourceArn -UpdateTags -TagType=Tag

// ONLY generate directives and package declaration! Do not add anything else to this file.

package fms
245 changes: 150 additions & 95 deletions internal/service/fms/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/fms"
"github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
"github.com/hashicorp/terraform-provider-aws/internal/flex"
tftags "github.com/hashicorp/terraform-provider-aws/internal/tags"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
"github.com/hashicorp/terraform-provider-aws/internal/verify"
)

Expand All @@ -22,27 +24,32 @@ func ResourcePolicy() *schema.Resource {
Read: resourcePolicyRead,
Update: resourcePolicyUpdate,
Delete: resourcePolicyDelete,

Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

CustomizeDiff: verify.SetTagsDiff,

Schema: map[string]*schema.Schema{
"name": {
"arn": {
Type: schema.TypeString,
Required: true,
Computed: true,
},

"delete_all_policy_resources": {
Type: schema.TypeBool,
Optional: true,
Default: true,
},

"delete_unused_fm_managed_resources": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
"exclude_resource_tags": {
Type: schema.TypeBool,
Required: true,
},

"exclude_map": {
Type: schema.TypeList,
MaxItems: 1,
Expand All @@ -67,7 +74,6 @@ func ResourcePolicy() *schema.Resource {
},
},
},

"include_map": {
Type: schema.TypeList,
MaxItems: 1,
Expand All @@ -92,108 +98,190 @@ func ResourcePolicy() *schema.Resource {
},
},
},

"name": {
Type: schema.TypeString,
Required: true,
},
"policy_update_token": {
Type: schema.TypeString,
Computed: true,
},
"remediation_enabled": {
Type: schema.TypeBool,
Optional: true,
},

"resource_type_list": {
Type: schema.TypeSet,
Optional: true,
Computed: true,
Set: schema.HashString,
ConflictsWith: []string{"resource_type"},
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateFunc: validation.StringMatch(regexp.MustCompile(`^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$`), "must match a supported resource type, such as AWS::EC2::VPC, see also: https://docs.aws.amazon.com/fms/2018-01-01/APIReference/API_Policy.html"),
},
},

"resource_tags": tftags.TagsSchema(),
"resource_type": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ConflictsWith: []string{"resource_type_list"},
ValidateFunc: validation.StringMatch(regexp.MustCompile(`^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$`), "must match a supported resource type, such as AWS::EC2::VPC, see also: https://docs.aws.amazon.com/fms/2018-01-01/APIReference/API_Policy.html"),
ConflictsWith: []string{"resource_type_list"},
},

"policy_update_token": {
Type: schema.TypeString,
"resource_type_list": {
Type: schema.TypeSet,
Optional: true,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateFunc: validation.StringMatch(regexp.MustCompile(`^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$`), "must match a supported resource type, such as AWS::EC2::VPC, see also: https://docs.aws.amazon.com/fms/2018-01-01/APIReference/API_Policy.html"),
},
ConflictsWith: []string{"resource_type"},
},

"resource_tags": tftags.TagsSchema(),

"security_service_policy_data": {
Type: schema.TypeList,
Required: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"type": {
Type: schema.TypeString,
Required: true,
},
"managed_service_data": {
Type: schema.TypeString,
Optional: true,
DiffSuppressFunc: verify.SuppressEquivalentJSONDiffs,
},
"type": {
Type: schema.TypeString,
Required: true,
},
},
},
},
"arn": {
Type: schema.TypeString,
Computed: true,
},
"tags": tftags.TagsSchema(),
"tags_all": tftags.TagsSchemaComputed(),
},
}
}

func resourcePolicyCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*conns.AWSClient).FMSConn
defaultTagsConfig := meta.(*conns.AWSClient).DefaultTagsConfig
tags := defaultTagsConfig.MergeTags(tftags.New(d.Get("tags").(map[string]interface{})))

fmsPolicy := resourcePolicyExpandPolicy(d)

params := &fms.PutPolicyInput{
Policy: fmsPolicy,
input := &fms.PutPolicyInput{
Policy: resourcePolicyExpandPolicy(d),
TagList: Tags(tags.IgnoreAWS()),
}

var resp *fms.PutPolicyOutput
var err error

resp, err = conn.PutPolicy(params)
output, err := conn.PutPolicy(input)

if err != nil {
return fmt.Errorf("Creating Policy Failed: %s", err.Error())
return fmt.Errorf("error creating FMS Policy: %w", err)
}

d.SetId(aws.StringValue(resp.Policy.PolicyId))
d.SetId(aws.StringValue(output.Policy.PolicyId))

return resourcePolicyRead(d, meta)
}

func resourcePolicyRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*conns.AWSClient).FMSConn
defaultTagsConfig := meta.(*conns.AWSClient).DefaultTagsConfig
ignoreTagsConfig := meta.(*conns.AWSClient).IgnoreTagsConfig

output, err := FindPolicyByID(conn, d.Id())

var resp *fms.GetPolicyOutput
var req = &fms.GetPolicyInput{
PolicyId: aws.String(d.Id()),
if !d.IsNewResource() && tfresource.NotFound(err) {
log.Printf("[WARN] FMS Policy %s not found, removing from state", d.Id())
d.SetId("")
return nil
}

resp, err := conn.GetPolicy(req)
if err != nil {
return fmt.Errorf("error reading FMS Policy (%s): %w", d.Id(), err)
}

if err := resourcePolicyFlattenPolicy(d, output); err != nil {
return err
}

tags, err := ListTags(conn, d.Get("arn").(string))

if err != nil {
if tfawserr.ErrMessageContains(err, fms.ErrCodeResourceNotFoundException, "") {
log.Printf("[WARN] FMS Policy (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
return fmt.Errorf("error listing tags for FMS Policy (%s): %w", d.Id(), err)
}

tags = tags.IgnoreAWS().IgnoreConfig(ignoreTagsConfig)

if err := d.Set("tags", tags.RemoveDefaultConfig(defaultTagsConfig).Map()); err != nil {
return fmt.Errorf("error setting tags: %w", err)
}

if err := d.Set("tags_all", tags.Map()); err != nil {
return fmt.Errorf("error setting tags_all: %w", err)
}

return nil
}

func resourcePolicyUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*conns.AWSClient).FMSConn

if d.HasChangesExcept("tags", "tags_all") {
input := &fms.PutPolicyInput{
Policy: resourcePolicyExpandPolicy(d),
}
return err

_, err := conn.PutPolicy(input)

if err != nil {
return fmt.Errorf("error updating FMS Policy (%s): %w", d.Id(), err)
}
}

if d.HasChange("tags_all") {
o, n := d.GetChange("tags_all")

if err := UpdateTags(conn, d.Get("arn").(string), o, n); err != nil {
return fmt.Errorf("error updating FMS Policy (%s) tags: %w", d.Id(), err)
}
}

return resourcePolicyRead(d, meta)
}

func resourcePolicyDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*conns.AWSClient).FMSConn

log.Printf("[DEBUG] Deleting FMS Policy: %s", d.Id())
_, err := conn.DeletePolicy(&fms.DeletePolicyInput{
PolicyId: aws.String(d.Id()),
DeleteAllPolicyResources: aws.Bool(d.Get("delete_all_policy_resources").(bool)),
})

if tfawserr.ErrCodeEquals(err, fms.ErrCodeResourceNotFoundException) {
return nil
}

return resourcePolicyFlattenPolicy(d, resp)
if err != nil {
return fmt.Errorf("error deleting FMS Policy (%s): %w", d.Id(), err)
}

return nil
}

func FindPolicyByID(conn *fms.FMS, id string) (*fms.GetPolicyOutput, error) {
input := &fms.GetPolicyInput{
PolicyId: aws.String(id),
}

output, err := conn.GetPolicy(input)

if tfawserr.ErrCodeEquals(err, fms.ErrCodeResourceNotFoundException) {
return nil, &resource.NotFoundError{
LastError: err,
LastRequest: input,
}
}

if err != nil {
return nil, err
}

if output == nil {
return nil, tfresource.NewEmptyResultError(input)
}

return output, nil
}

func resourcePolicyFlattenPolicy(d *schema.ResourceData, resp *fms.GetPolicyOutput) error {
Expand All @@ -211,6 +299,7 @@ func resourcePolicyFlattenPolicy(d *schema.ResourceData, resp *fms.GetPolicyOutp
if err := d.Set("resource_type_list", resp.Policy.ResourceTypeList); err != nil {
return err
}
d.Set("delete_unused_fm_managed_resources", resp.Policy.DeleteUnusedFMManagedResources)
d.Set("resource_type", resp.Policy.ResourceType)
d.Set("policy_update_token", resp.Policy.PolicyUpdateToken)
if err := d.Set("resource_tags", flattenFMSResourceTags(resp.Policy.ResourceTags)); err != nil {
Expand All @@ -236,11 +325,12 @@ func resourcePolicyExpandPolicy(d *schema.ResourceData) *fms.Policy {
}

fmsPolicy := &fms.Policy{
PolicyName: aws.String(d.Get("name").(string)),
RemediationEnabled: aws.Bool(d.Get("remediation_enabled").(bool)),
ResourceType: resourceType,
ResourceTypeList: resourceTypeList,
ExcludeResourceTags: aws.Bool(d.Get("exclude_resource_tags").(bool)),
PolicyName: aws.String(d.Get("name").(string)),
RemediationEnabled: aws.Bool(d.Get("remediation_enabled").(bool)),
ResourceType: resourceType,
ResourceTypeList: resourceTypeList,
ExcludeResourceTags: aws.Bool(d.Get("exclude_resource_tags").(bool)),
DeleteUnusedFMManagedResources: aws.Bool(d.Get("delete_unused_fm_managed_resources").(bool)),
}

if d.Id() != "" {
Expand All @@ -263,41 +353,6 @@ func resourcePolicyExpandPolicy(d *schema.ResourceData) *fms.Policy {
return fmsPolicy
}

func resourcePolicyUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*conns.AWSClient).FMSConn

fmsPolicy := resourcePolicyExpandPolicy(d)

params := &fms.PutPolicyInput{Policy: fmsPolicy}
_, err := conn.PutPolicy(params)

if err != nil {
return fmt.Errorf("Error modifying FMS Policy Rule: %s", err)
}

return resourcePolicyRead(d, meta)
}

func resourcePolicyDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*conns.AWSClient).FMSConn
log.Printf("[DEBUG] Delete FMS Policy: %s", d.Id())

_, err := conn.DeletePolicy(&fms.DeletePolicyInput{
PolicyId: aws.String(d.Id()),
DeleteAllPolicyResources: aws.Bool(d.Get("delete_all_policy_resources").(bool)),
})

if tfawserr.ErrMessageContains(err, fms.ErrCodeResourceNotFoundException, "") {
return nil
}

if err != nil {
return fmt.Errorf("error deleting FMS Policy (%s): %s", d.Id(), err)
}

return nil
}

func expandFMSPolicyMap(set []interface{}) map[string][]*string {
fmsPolicyMap := map[string][]*string{}
if len(set) > 0 {
Expand Down
Loading