Skip to content

Commit 6085d24

Browse files
Introduced resource dynatrace_policy_boundary (#645)
* Implemented `dynatrace_iam_policy_boundary` and added it to `dynatrace_iam_policy_bindings_v2` as attribute * added documentation * removed unnecessary code * Added dependency for `iam_policy_bindings_v2` to `iam_policy_boundary` * Excluded resource from default export
1 parent abda5de commit 6085d24

File tree

8 files changed

+302
-1
lines changed

8 files changed

+302
-1
lines changed
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
package boundaries
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
"strings"
8+
9+
"github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/api"
10+
"github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/api/iam"
11+
boundaries "github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/api/iam/boundaries/settings"
12+
"github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/settings"
13+
)
14+
15+
func Service(credentials *settings.Credentials) settings.CRUDService[*boundaries.PolicyBoundary] {
16+
return &BoundaryServiceClient{
17+
clientID: credentials.IAM.ClientID,
18+
accountID: credentials.IAM.AccountID,
19+
clientSecret: credentials.IAM.ClientSecret,
20+
tokenURL: credentials.IAM.TokenURL,
21+
endpointURL: credentials.IAM.EndpointURL,
22+
}
23+
}
24+
25+
type BoundaryServiceClient struct {
26+
clientID string
27+
accountID string
28+
clientSecret string
29+
tokenURL string
30+
endpointURL string
31+
}
32+
33+
func (me *BoundaryServiceClient) ClientID() string {
34+
return me.clientID
35+
}
36+
37+
func (me *BoundaryServiceClient) AccountID() string {
38+
return me.accountID
39+
}
40+
41+
func (me *BoundaryServiceClient) ClientSecret() string {
42+
return me.clientSecret
43+
}
44+
45+
func (me *BoundaryServiceClient) TokenURL() string {
46+
return me.tokenURL
47+
}
48+
49+
func (me *BoundaryServiceClient) EndpointURL() string {
50+
return me.endpointURL
51+
}
52+
53+
func (me *BoundaryServiceClient) List(ctx context.Context) (api.Stubs, error) {
54+
var err error
55+
var responseBytes []byte
56+
57+
client := iam.NewIAMClient(me)
58+
59+
if responseBytes, err = client.GET(ctx, fmt.Sprintf("%s/iam/v1/repo/account/%s/boundaries", me.endpointURL, strings.TrimPrefix(me.AccountID(), "urn:dtaccount:")), 200, false); err != nil {
60+
return nil, err
61+
}
62+
63+
var response ListPolicyBoundariesResponse
64+
if err = json.Unmarshal(responseBytes, &response); err != nil {
65+
return nil, err
66+
}
67+
if len(response.PolicyBoundaries) == 0 {
68+
return api.Stubs{}, nil
69+
}
70+
stubs := api.Stubs{}
71+
for _, boundary := range response.PolicyBoundaries {
72+
stubs = append(stubs, &api.Stub{ID: boundary.UUID, Name: boundary.Name})
73+
}
74+
return stubs, nil
75+
}
76+
77+
func (me *BoundaryServiceClient) Get(ctx context.Context, id string, v *boundaries.PolicyBoundary) error {
78+
var err error
79+
var responseBytes []byte
80+
81+
client := iam.NewIAMClient(me)
82+
83+
if responseBytes, err = client.GET(ctx, fmt.Sprintf("%s/iam/v1/repo/account/%s/boundaries/%s", me.endpointURL, strings.TrimPrefix(me.AccountID(), "urn:dtaccount:"), id), 200, false); err != nil {
84+
return err
85+
}
86+
87+
if err = json.Unmarshal(responseBytes, v); err != nil {
88+
return err
89+
}
90+
return nil
91+
}
92+
93+
func (me *BoundaryServiceClient) SchemaID() string {
94+
return "accounts:iam:boundaries"
95+
}
96+
97+
func (me *BoundaryServiceClient) Create(ctx context.Context, v *boundaries.PolicyBoundary) (*api.Stub, error) {
98+
var err error
99+
var responseBytes []byte
100+
101+
client := iam.NewIAMClient(me)
102+
103+
if responseBytes, err = client.POST(
104+
ctx,
105+
fmt.Sprintf("%s/iam/v1/repo/account/%s/boundaries", me.endpointURL, strings.TrimPrefix(me.AccountID(), "urn:dtaccount:")),
106+
v,
107+
201,
108+
false,
109+
); err != nil {
110+
return nil, err
111+
}
112+
113+
response := struct {
114+
UUID string `json:"uuid"`
115+
Name string `json:"name"`
116+
}{}
117+
118+
if err = json.Unmarshal(responseBytes, &response); err != nil {
119+
return nil, err
120+
}
121+
122+
return &api.Stub{ID: response.UUID, Name: response.Name}, nil
123+
}
124+
125+
func (me *BoundaryServiceClient) Update(ctx context.Context, id string, v *boundaries.PolicyBoundary) error {
126+
var err error
127+
var responseBytes []byte
128+
129+
client := iam.NewIAMClient(me)
130+
131+
if responseBytes, err = client.PUT(
132+
ctx,
133+
fmt.Sprintf("%s/iam/v1/repo/account/%s/boundaries/%s", me.endpointURL, strings.TrimPrefix(me.AccountID(), "urn:dtaccount:"), id),
134+
v,
135+
201,
136+
false,
137+
); err != nil {
138+
return err
139+
}
140+
141+
response := struct {
142+
UUID string `json:"uuid"`
143+
Name string `json:"name"`
144+
}{}
145+
146+
if err = json.Unmarshal(responseBytes, &response); err != nil {
147+
return err
148+
}
149+
150+
return nil
151+
}
152+
153+
func (me *BoundaryServiceClient) Delete(ctx context.Context, id string) error {
154+
var err error
155+
156+
client := iam.NewIAMClient(me)
157+
158+
if _, err = client.DELETE(
159+
ctx,
160+
fmt.Sprintf("%s/iam/v1/repo/account/%s/boundaries/%s", me.endpointURL, strings.TrimPrefix(me.AccountID(), "urn:dtaccount:"), id),
161+
204,
162+
false,
163+
); err != nil {
164+
return err
165+
}
166+
167+
return nil
168+
}
169+
170+
type PolicyBoundary struct {
171+
UUID string `json:"uuid"`
172+
LevelType string `json:"levelType"`
173+
LevelID string `json:"levelId"`
174+
Name string `json:"name"`
175+
Query string `json:"boundaryQuery"`
176+
}
177+
178+
type ListPolicyBoundariesResponse struct {
179+
PageSize int `json:"pageSize"`
180+
PageNumber int `json:"pageNumber"`
181+
TotalCount int `json:"totalCount"`
182+
PolicyBoundaries []PolicyBoundary `json:"content"`
183+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package boundaries
2+
3+
import (
4+
"github.com/dynatrace-oss/terraform-provider-dynatrace/terraform/hcl"
5+
6+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
7+
)
8+
9+
type PolicyBoundary struct {
10+
Name string `json:"name"`
11+
Query string `json:"boundaryQuery"`
12+
}
13+
14+
func (me *PolicyBoundary) Schema() map[string]*schema.Schema {
15+
return map[string]*schema.Schema{
16+
"name": {
17+
Type: schema.TypeString,
18+
Required: true,
19+
Description: "The name of the policy",
20+
},
21+
"query": {
22+
Type: schema.TypeString,
23+
Required: true,
24+
Description: "The boundary query",
25+
},
26+
}
27+
}
28+
29+
func (me *PolicyBoundary) MarshalHCL(properties hcl.Properties) error {
30+
return properties.EncodeAll(map[string]any{
31+
"name": me.Name,
32+
"query": me.Query,
33+
})
34+
}
35+
36+
func (me *PolicyBoundary) UnmarshalHCL(decoder hcl.Decoder) error {
37+
return decoder.DecodeAll(map[string]any{
38+
"name": &me.Name,
39+
"query": &me.Query,
40+
})
41+
}

dynatrace/api/iam/v2bindings/service.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ type BindingsResponse struct {
9898
GroupUUIDs []string `json:"groups"`
9999
Parameters map[string]string `json:"parameters"`
100100
Metadata map[string]string `json:"metadata"`
101+
Boundaries []string `json:"boundaries"`
101102
} `json:"policyBindings"`
102103
}
103104

@@ -166,6 +167,9 @@ func (me *BindingServiceClient) resolvePolicies(ctx context.Context, uuid string
166167
policy.Metadata[key] = value
167168
}
168169
}
170+
if len(policyBinding.Boundaries) > 0 {
171+
policy.Boundaries = append([]string{}, policyBinding.Boundaries...)
172+
}
169173
results = append(results, policy)
170174
}
171175
return results, nil
@@ -192,9 +196,11 @@ func (me *BindingServiceClient) Update(ctx context.Context, id string, v *bindin
192196
payload := struct {
193197
Parameters map[string]string `json:"parameters"`
194198
Metadata map[string]string `json:"metadata"`
199+
Boundaries []string `json:"boundaries"`
195200
}{
196201
Parameters: policy.Parameters,
197202
Metadata: policy.Metadata,
203+
Boundaries: policy.Boundaries,
198204
}
199205
retries := 0
200206
for retries < 10 {

dynatrace/api/iam/v2bindings/settings/policy.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ type Policy struct {
1111
ID string
1212
Parameters map[string]string
1313
Metadata map[string]string
14+
Boundaries []string
1415
}
1516

1617
func (me *Policy) Schema() map[string]*schema.Schema {
@@ -30,6 +31,11 @@ func (me *Policy) Schema() map[string]*schema.Schema {
3031
Optional: true,
3132
Elem: &schema.Schema{Type: schema.TypeString},
3233
},
34+
"boundaries": {
35+
Type: schema.TypeSet,
36+
Optional: true,
37+
Elem: &schema.Schema{Type: schema.TypeString},
38+
},
3339
}
3440
}
3541

@@ -43,6 +49,9 @@ func (me *Policy) MarshalHCL(properties hcl.Properties) error {
4349
if err := properties.Encode("metadata", me.Metadata); err != nil {
4450
return err
4551
}
52+
if err := properties.Encode("boundaries", me.Boundaries); err != nil {
53+
return err
54+
}
4655
return nil
4756
}
4857

@@ -56,5 +65,8 @@ func (me *Policy) UnmarshalHCL(decoder hcl.Decoder) error {
5665
if err := decoder.Decode("metadata", &me.Metadata); err != nil {
5766
return err
5867
}
68+
if err := decoder.Decode("boundaries", &me.Boundaries); err != nil {
69+
return err
70+
}
5971
return nil
6072
}

dynatrace/export/enums.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ var ResourceTypes = struct {
235235
IAMPolicy ResourceType
236236
IAMPolicyBindings ResourceType
237237
IAMPolicyBindingsV2 ResourceType
238+
IAMPolicyBoundary ResourceType
238239
ProcessGroupAnomalies ResourceType
239240
DDUPool ResourceType
240241
ProcessGroupAlerting ResourceType
@@ -571,6 +572,7 @@ var ResourceTypes = struct {
571572
"dynatrace_iam_policy",
572573
"dynatrace_iam_policy_bindings",
573574
"dynatrace_iam_policy_bindings_v2",
575+
"dynatrace_iam_policy_boundary",
574576
"dynatrace_pg_anomalies",
575577
"dynatrace_ddu_pool",
576578
"dynatrace_pg_alerting",

dynatrace/export/resource_descriptor.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,7 @@ import (
291291
directshares "github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/api/documents/directshares"
292292
documents "github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/api/documents/document"
293293
"github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/api/iam/bindings"
294+
"github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/api/iam/boundaries"
294295
"github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/api/iam/groups"
295296
"github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/api/iam/permissions"
296297
"github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/api/iam/policies"
@@ -776,9 +777,11 @@ var AllResources = map[ResourceType]ResourceDescriptor{
776777
v2bindings.Service,
777778
Dependencies.ID(ResourceTypes.IAMGroup),
778779
Dependencies.ID(ResourceTypes.IAMPolicy),
780+
Dependencies.ID(ResourceTypes.IAMPolicyBoundary),
779781
Dependencies.GlobalPolicy,
780782
),
781-
ResourceTypes.DDUPool: NewResourceDescriptor(ddupool.Service),
783+
ResourceTypes.IAMPolicyBoundary: NewResourceDescriptor(boundaries.Service),
784+
ResourceTypes.DDUPool: NewResourceDescriptor(ddupool.Service),
782785
ResourceTypes.ProcessGroupAnomalies: NewResourceDescriptor(
783786
pg_anomalies.Service,
784787
Coalesce(Dependencies.ProcessGroup),
@@ -1488,6 +1491,7 @@ var excludeListedResourceGroups = []ResourceExclusionGroup{
14881491
{ResourceTypes.IAMPolicy, ""},
14891492
{ResourceTypes.IAMPolicyBindings, ""},
14901493
{ResourceTypes.IAMPolicyBindingsV2, ""},
1494+
{ResourceTypes.IAMPolicyBoundary, ""},
14911495
},
14921496
},
14931497
{

provider/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,7 @@ func Provider() *schema.Provider {
341341
"dynatrace_iam_policy": resources.NewGeneric(export.ResourceTypes.IAMPolicy, resources.CredValIAM).Resource(),
342342
"dynatrace_iam_policy_bindings": resources.NewGeneric(export.ResourceTypes.IAMPolicyBindings, resources.CredValIAM).Resource(),
343343
"dynatrace_iam_policy_bindings_v2": resources.NewGeneric(export.ResourceTypes.IAMPolicyBindingsV2, resources.CredValIAM).Resource(),
344+
"dynatrace_iam_policy_boundary": resources.NewGeneric(export.ResourceTypes.IAMPolicyBoundary, resources.CredValIAM).Resource(),
344345
"dynatrace_api_token": apitokens.Resource(),
345346
"dynatrace_custom_tags": customtags.Resource(),
346347
"dynatrace_pg_anomalies": resources.NewGeneric(export.ResourceTypes.ProcessGroupAnomalies).Resource(),

0 commit comments

Comments
 (0)