Skip to content

Commit cd31961

Browse files
authored
Merge pull request #38328 from chrisbrowning/f-aws_cloudwatch_log_account_policy
add aws_cloudwatch_log_account_policy resource
2 parents 1c1d430 + 68e4bd3 commit cd31961

File tree

9 files changed

+1313
-630
lines changed

9 files changed

+1313
-630
lines changed

.changelog/38328.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:new-resource
2+
aws_cloudwatch_log_account_policy
3+
```

go.mod

Lines changed: 210 additions & 210 deletions
Large diffs are not rendered by default.

go.sum

Lines changed: 420 additions & 420 deletions
Large diffs are not rendered by default.
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package logs
5+
6+
import (
7+
"context"
8+
"fmt"
9+
"log"
10+
"strings"
11+
12+
"github.com/aws/aws-sdk-go-v2/aws"
13+
"github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs"
14+
"github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs/types"
15+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
16+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry"
17+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
18+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure"
19+
"github.com/hashicorp/terraform-provider-aws/internal/conns"
20+
"github.com/hashicorp/terraform-provider-aws/internal/enum"
21+
"github.com/hashicorp/terraform-provider-aws/internal/errs"
22+
"github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag"
23+
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
24+
"github.com/hashicorp/terraform-provider-aws/internal/verify"
25+
"github.com/hashicorp/terraform-provider-aws/names"
26+
)
27+
28+
// @SDKResource("aws_cloudwatch_log_account_policy", name="Account Policy")
29+
func resourceAccountPolicy() *schema.Resource {
30+
return &schema.Resource{
31+
CreateWithoutTimeout: resourceAccountPolicyPut,
32+
ReadWithoutTimeout: resourceAccountPolicyRead,
33+
UpdateWithoutTimeout: resourceAccountPolicyPut,
34+
DeleteWithoutTimeout: resourceAccountPolicyDelete,
35+
36+
Importer: &schema.ResourceImporter{
37+
State: resourceAccountPolicyImport,
38+
},
39+
40+
Schema: map[string]*schema.Schema{
41+
"policy_document": {
42+
Type: schema.TypeString,
43+
Required: true,
44+
ValidateFunc: validAccountPolicyDocument,
45+
DiffSuppressFunc: verify.SuppressEquivalentJSONDiffs,
46+
DiffSuppressOnRefresh: true,
47+
StateFunc: func(v interface{}) string {
48+
json, _ := structure.NormalizeJsonString(v)
49+
return json
50+
},
51+
},
52+
"policy_name": {
53+
Type: schema.TypeString,
54+
Required: true,
55+
ForceNew: true,
56+
},
57+
"policy_type": {
58+
Type: schema.TypeString,
59+
Required: true,
60+
ForceNew: true,
61+
ValidateDiagFunc: enum.Validate[types.PolicyType](),
62+
},
63+
names.AttrScope: {
64+
Type: schema.TypeString,
65+
Optional: true,
66+
Default: types.ScopeAll,
67+
ValidateDiagFunc: enum.Validate[types.Scope](),
68+
},
69+
"selection_criteria": {
70+
Type: schema.TypeString,
71+
Optional: true,
72+
ForceNew: true,
73+
},
74+
},
75+
}
76+
}
77+
78+
func resourceAccountPolicyPut(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
79+
var diags diag.Diagnostics
80+
conn := meta.(*conns.AWSClient).LogsClient(ctx)
81+
82+
policy, err := structure.NormalizeJsonString(d.Get("policy_document").(string))
83+
if err != nil {
84+
return sdkdiag.AppendFromErr(diags, err)
85+
}
86+
87+
name := d.Get("policy_name").(string)
88+
input := &cloudwatchlogs.PutAccountPolicyInput{
89+
PolicyDocument: aws.String(policy),
90+
PolicyName: aws.String(name),
91+
PolicyType: types.PolicyType(d.Get("policy_type").(string)),
92+
Scope: types.Scope(d.Get(names.AttrScope).(string)),
93+
}
94+
95+
if v, ok := d.GetOk("selection_criteria"); ok {
96+
input.SelectionCriteria = aws.String(v.(string))
97+
}
98+
99+
output, err := conn.PutAccountPolicy(ctx, input)
100+
101+
if err != nil {
102+
return sdkdiag.AppendErrorf(diags, "creating CloudWatch Logs Account Policy (%s): %s", name, err)
103+
}
104+
105+
d.SetId(aws.ToString(output.AccountPolicy.PolicyName))
106+
107+
return append(diags, resourceAccountPolicyRead(ctx, d, meta)...)
108+
}
109+
110+
func resourceAccountPolicyRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
111+
var diags diag.Diagnostics
112+
conn := meta.(*conns.AWSClient).LogsClient(ctx)
113+
114+
output, err := findAccountPolicyByTwoPartKey(ctx, conn, types.PolicyType(d.Get("policy_type").(string)), d.Id())
115+
116+
if !d.IsNewResource() && tfresource.NotFound(err) {
117+
log.Printf("[WARN] CloudWatch Logs Account Policy (%s) not found, removing from state", d.Id())
118+
d.SetId("")
119+
return diags
120+
}
121+
122+
if err != nil {
123+
return sdkdiag.AppendErrorf(diags, "reading CloudWatch Logs Account Policy (%s): %s", d.Id(), err)
124+
}
125+
126+
policyToSet, err := verify.SecondJSONUnlessEquivalent(d.Get("policy_document").(string), aws.ToString(output.PolicyDocument))
127+
if err != nil {
128+
return sdkdiag.AppendFromErr(diags, err)
129+
}
130+
131+
policyToSet, err = structure.NormalizeJsonString(policyToSet)
132+
if err != nil {
133+
return sdkdiag.AppendFromErr(diags, err)
134+
}
135+
136+
d.Set("policy_document", policyToSet)
137+
d.Set("policy_name", output.PolicyName)
138+
d.Set("policy_type", output.PolicyType)
139+
d.Set(names.AttrScope, output.Scope)
140+
d.Set("selection_criteria", output.SelectionCriteria)
141+
142+
return diags
143+
}
144+
145+
func resourceAccountPolicyDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
146+
var diags diag.Diagnostics
147+
conn := meta.(*conns.AWSClient).LogsClient(ctx)
148+
149+
log.Printf("[DEBUG] Deleting CloudWatch Logs Account Policy: %s", d.Id())
150+
_, err := conn.DeleteAccountPolicy(ctx, &cloudwatchlogs.DeleteAccountPolicyInput{
151+
PolicyName: aws.String(d.Id()),
152+
PolicyType: types.PolicyType(d.Get("policy_type").(string)),
153+
})
154+
155+
if errs.IsA[*types.ResourceNotFoundException](err) {
156+
return diags
157+
}
158+
159+
if err != nil {
160+
return sdkdiag.AppendErrorf(diags, "deleting CloudWatch Logs Account Policy (%s): %s", d.Id(), err)
161+
}
162+
163+
return diags
164+
}
165+
166+
func resourceAccountPolicyImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
167+
parts := strings.Split(d.Id(), ":")
168+
if len(parts) != 2 {
169+
return []*schema.ResourceData{}, fmt.Errorf("wrong format of import ID (%s), use: '<policy-name>:<policy-type>'", d.Id())
170+
}
171+
172+
policyName := parts[0]
173+
policyType := parts[1]
174+
175+
d.SetId(policyName)
176+
d.Set("policy_type", policyType)
177+
178+
return []*schema.ResourceData{d}, nil
179+
}
180+
181+
func findAccountPolicyByTwoPartKey(ctx context.Context, conn *cloudwatchlogs.Client, policyType types.PolicyType, policyName string) (*types.AccountPolicy, error) {
182+
input := &cloudwatchlogs.DescribeAccountPoliciesInput{
183+
PolicyName: aws.String(policyName),
184+
PolicyType: policyType,
185+
}
186+
187+
output, err := conn.DescribeAccountPolicies(ctx, input)
188+
189+
if errs.IsA[*types.ResourceNotFoundException](err) {
190+
return nil, &retry.NotFoundError{
191+
LastError: err,
192+
LastRequest: input,
193+
}
194+
}
195+
196+
if err != nil {
197+
return nil, err
198+
}
199+
200+
if output == nil {
201+
return nil, tfresource.NewEmptyResultError(input)
202+
}
203+
204+
return tfresource.AssertSingleValueResult(output.AccountPolicies)
205+
}

0 commit comments

Comments
 (0)