Skip to content

Commit 67e97be

Browse files
committed
feat: Add dynatrace_iam_service_user resource and data source
1 parent 2b84720 commit 67e97be

File tree

8 files changed

+1297
-0
lines changed

8 files changed

+1297
-0
lines changed
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
/**
2+
* @license
3+
* Copyright 2025 Dynatrace LLC
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package serviceusers
19+
20+
import (
21+
"context"
22+
"sort"
23+
24+
"github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/api/iam/serviceusers"
25+
su "github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/api/iam/serviceusers/settings"
26+
"github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/settings"
27+
"github.com/dynatrace-oss/terraform-provider-dynatrace/provider/config"
28+
"github.com/dynatrace-oss/terraform-provider-dynatrace/provider/logging"
29+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
30+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
31+
)
32+
33+
func DataSource() *schema.Resource {
34+
return &schema.Resource{
35+
ReadContext: logging.EnableDSCtx(DataSourceRead),
36+
Description: "Fetches IAM service user details by name, ID, or email",
37+
Schema: map[string]*schema.Schema{
38+
"name": {
39+
Type: schema.TypeString,
40+
Optional: true,
41+
Description: "The name of the service user",
42+
ExactlyOneOf: []string{"name", "id", "email"},
43+
},
44+
"id": {
45+
Type: schema.TypeString,
46+
Optional: true,
47+
Description: "The UUID of the service user",
48+
ExactlyOneOf: []string{"name", "id", "email"},
49+
},
50+
"email": {
51+
Type: schema.TypeString,
52+
Optional: true,
53+
Description: "The email of the service user",
54+
ExactlyOneOf: []string{"name", "id", "email"},
55+
},
56+
"description": {
57+
Type: schema.TypeString,
58+
Computed: true,
59+
Description: "The description of the service user",
60+
},
61+
"groups": {
62+
Type: schema.TypeList,
63+
Elem: &schema.Schema{Type: schema.TypeString},
64+
Computed: true,
65+
Description: "The UUIDs of the groups the service user belongs to",
66+
},
67+
},
68+
}
69+
}
70+
71+
func DataSourceRead(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
72+
creds, err := config.Credentials(m, config.CredValIAM)
73+
if err != nil {
74+
return diag.FromErr(err)
75+
}
76+
77+
service := serviceusers.Service(creds)
78+
return dataSourceReadWithService(ctx, d, service)
79+
}
80+
81+
func dataSourceReadWithService(ctx context.Context, d *schema.ResourceData, service settings.CRUDService[*su.ServiceUser]) diag.Diagnostics {
82+
// Determine lookup method
83+
var lookupByID string
84+
var lookupByName string
85+
var lookupByEmail string
86+
87+
if v, ok := d.GetOk("id"); ok {
88+
lookupByID = v.(string)
89+
}
90+
if v, ok := d.GetOk("name"); ok {
91+
lookupByName = v.(string)
92+
}
93+
if v, ok := d.GetOk("email"); ok {
94+
lookupByEmail = v.(string)
95+
}
96+
97+
// If looking up by ID, get directly
98+
if len(lookupByID) > 0 {
99+
var serviceUser su.ServiceUser
100+
if err := service.Get(ctx, lookupByID, &serviceUser); err != nil {
101+
return diag.FromErr(err)
102+
}
103+
return setServiceUserData(d, &serviceUser)
104+
}
105+
106+
// For name or email lookup, we need to list and find
107+
stubs, err := service.List(ctx)
108+
if err != nil {
109+
return diag.FromErr(err)
110+
}
111+
112+
for _, stub := range stubs {
113+
var serviceUser su.ServiceUser
114+
if err := service.Get(ctx, stub.ID, &serviceUser); err != nil {
115+
return diag.FromErr(err)
116+
}
117+
118+
if len(lookupByName) > 0 && serviceUser.Name == lookupByName {
119+
return setServiceUserData(d, &serviceUser)
120+
}
121+
if len(lookupByEmail) > 0 && serviceUser.Email == lookupByEmail {
122+
return setServiceUserData(d, &serviceUser)
123+
}
124+
}
125+
126+
// Not found
127+
d.SetId("")
128+
return diag.Errorf("Service user not found")
129+
}
130+
131+
func setServiceUserData(d *schema.ResourceData, serviceUser *su.ServiceUser) diag.Diagnostics {
132+
d.SetId(serviceUser.UID)
133+
d.Set("id", serviceUser.UID)
134+
d.Set("name", serviceUser.Name)
135+
d.Set("email", serviceUser.Email)
136+
d.Set("description", serviceUser.Description)
137+
138+
if len(serviceUser.Groups) > 0 {
139+
sort.Strings(serviceUser.Groups)
140+
d.Set("groups", serviceUser.Groups)
141+
} else {
142+
d.Set("groups", []string{})
143+
}
144+
145+
return diag.Diagnostics{}
146+
}

0 commit comments

Comments
 (0)