Skip to content

Commit c4f3b86

Browse files
feat: Add codefresh_service_account resource and datasource (#157)
1 parent 59f99a0 commit c4f3b86

13 files changed

+1056
-29
lines changed

codefresh/cfclient/api_key.go

+89
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,95 @@ func (client *Client) GetApiKeysList() ([]ApiKey, error) {
245245
return apiKeys, nil
246246
}
247247

248+
func (client *Client) GetAPIKeyServiceUser(keyID string, serviceUserId string) (*ApiKey, error) {
249+
250+
opts := RequestOptions{
251+
Path: fmt.Sprintf("/auth/key/service-user/%s/%s", serviceUserId, keyID),
252+
Method: "GET",
253+
}
254+
255+
resp, err := client.RequestAPI(&opts)
256+
257+
if err != nil {
258+
return nil, err
259+
}
260+
261+
var apiKey ApiKey
262+
263+
err = DecodeResponseInto(resp, &apiKey)
264+
if err != nil {
265+
return nil, err
266+
}
267+
268+
return &apiKey, nil
269+
}
270+
271+
func (client *Client) DeleteAPIKeyServiceUser(keyID string, serviceUserId string) error {
272+
273+
opts := RequestOptions{
274+
Path: fmt.Sprintf("/auth/key/service-user/%s/%s", serviceUserId, keyID),
275+
Method: "DELETE",
276+
}
277+
278+
resp, err := client.RequestAPI(&opts)
279+
if err != nil {
280+
fmt.Println(string(resp))
281+
return err
282+
}
283+
284+
return nil
285+
}
286+
287+
func (client *Client) UpdateAPIKeyServiceUser(key *ApiKey, serviceUserId string) error {
288+
289+
keyID := key.ID
290+
if keyID == "" {
291+
return errors.New("[ERROR] Key ID is empty")
292+
}
293+
294+
body, err := EncodeToJSON(key)
295+
if err != nil {
296+
return err
297+
}
298+
299+
opts := RequestOptions{
300+
Path: fmt.Sprintf("/auth/key/service-user/%s/%s", serviceUserId, keyID),
301+
Method: "PATCH",
302+
Body: body,
303+
}
304+
305+
resp, err := client.RequestAPI(&opts)
306+
307+
if err != nil {
308+
fmt.Println(string(resp))
309+
return err
310+
}
311+
312+
return nil
313+
}
314+
315+
func (client *Client) CreateApiKeyServiceUser(serviceUserId string, apiKey *ApiKey) (string, error) {
316+
317+
body, err := EncodeToJSON(apiKey)
318+
if err != nil {
319+
return "", err
320+
}
321+
322+
opts := RequestOptions{
323+
Path: fmt.Sprintf("/auth/key/service-user/%s", serviceUserId),
324+
Method: "POST",
325+
Body: body,
326+
}
327+
328+
resp, err := client.RequestAPI(&opts)
329+
330+
if err != nil {
331+
return "", err
332+
}
333+
334+
return string(resp), nil
335+
}
336+
248337
func (client *Client) createRandomUser(accountId string) (string, error) {
249338
// add user
250339
userPrefix := acctest.RandString(10)

codefresh/cfclient/service_user.go

+174
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
package cfclient
2+
3+
import (
4+
"fmt"
5+
"golang.org/x/exp/slices"
6+
)
7+
8+
type ServiceUserTeam struct {
9+
ID string `json:"_id,omitempty"`
10+
}
11+
12+
type ServiceUser struct {
13+
ID string `json:"_id,omitempty"`
14+
Name string `json:"userName,omitempty"`
15+
Teams []ServiceUserTeam `json:"teams,omitempty"`
16+
Roles []string `json:"roles,omitempty"`
17+
}
18+
19+
type ServiceUserCreateUpdate struct {
20+
ID string `json:"_id,omitempty"`
21+
Name string `json:"userName,omitempty"`
22+
TeamIDs []string `json:"teamIds,omitempty"`
23+
AssignAdminRole bool `json:"assignAdminRole,omitempty"`
24+
}
25+
26+
// GetID implement CodefreshObject interface
27+
func (serviceuser *ServiceUser) GetID() string {
28+
return serviceuser.ID
29+
}
30+
31+
func (serviceuser *ServiceUser) HasAdminRole() bool {
32+
return slices.Contains(serviceuser.Roles, "Admin")
33+
}
34+
35+
func (client *Client) GetServiceUserList() ([]ServiceUser, error) {
36+
fullPath := "/service-users"
37+
opts := RequestOptions{
38+
Path: fullPath,
39+
Method: "GET",
40+
}
41+
42+
resp, err := client.RequestAPI(&opts)
43+
44+
if err != nil {
45+
return nil, err
46+
}
47+
48+
var serviceusers []ServiceUser
49+
50+
err = DecodeResponseInto(resp, &serviceusers)
51+
if err != nil {
52+
return nil, err
53+
}
54+
55+
return serviceusers, nil
56+
}
57+
58+
func (client *Client) GetServiceUserByName(name string) (*ServiceUser, error) {
59+
60+
serviceusers, err := client.GetServiceUserList()
61+
if err != nil {
62+
return nil, err
63+
}
64+
65+
for _, serviceuser := range serviceusers {
66+
if serviceuser.Name == name {
67+
return &serviceuser, nil
68+
}
69+
}
70+
71+
return nil, nil
72+
}
73+
74+
func (client *Client) GetServiceUserByID(id string) (*ServiceUser, error) {
75+
76+
fullPath := fmt.Sprintf("/service-users/%s", id)
77+
opts := RequestOptions{
78+
Path: fullPath,
79+
Method: "GET",
80+
}
81+
82+
resp, err := client.RequestAPI(&opts)
83+
84+
if err != nil {
85+
return nil, err
86+
}
87+
88+
var serviceuser ServiceUser
89+
90+
err = DecodeResponseInto(resp, &serviceuser)
91+
if err != nil {
92+
return nil, err
93+
}
94+
95+
return &serviceuser, nil
96+
}
97+
98+
func (client *Client) CreateServiceUser(serviceUserCreateUpdate *ServiceUserCreateUpdate) (*ServiceUser, error) {
99+
100+
fullPath := "/service-users"
101+
body, err := EncodeToJSON(serviceUserCreateUpdate)
102+
103+
if err != nil {
104+
return nil, err
105+
}
106+
107+
opts := RequestOptions{
108+
Path: fullPath,
109+
Method: "POST",
110+
Body: body,
111+
}
112+
113+
resp, err := client.RequestAPI(&opts)
114+
115+
if err != nil {
116+
return nil, err
117+
}
118+
119+
var serviceuser ServiceUser
120+
121+
err = DecodeResponseInto(resp, &serviceuser)
122+
if err != nil {
123+
return nil, err
124+
}
125+
126+
return &serviceuser, nil
127+
}
128+
129+
func (client *Client) UpdateServiceUser(serviceUserCreateUpdate *ServiceUserCreateUpdate) (*ServiceUser, error) {
130+
131+
fullPath := fmt.Sprintf("/service-users/%s", serviceUserCreateUpdate.ID)
132+
body, err := EncodeToJSON(serviceUserCreateUpdate)
133+
134+
if err != nil {
135+
return nil, err
136+
}
137+
138+
opts := RequestOptions{
139+
Path: fullPath,
140+
Method: "PATCH",
141+
Body: body,
142+
}
143+
144+
resp, err := client.RequestAPI(&opts)
145+
146+
if err != nil {
147+
return nil, err
148+
}
149+
150+
var serviceuser ServiceUser
151+
152+
err = DecodeResponseInto(resp, &serviceuser)
153+
if err != nil {
154+
return nil, err
155+
}
156+
157+
return &serviceuser, nil
158+
}
159+
160+
func (client *Client) DeleteServiceUser(id string) error {
161+
fullPath := fmt.Sprintf("/service-users/%s", id)
162+
opts := RequestOptions{
163+
Path: fullPath,
164+
Method: "DELETE",
165+
}
166+
167+
_, err := client.RequestAPI(&opts)
168+
169+
if err != nil {
170+
return err
171+
}
172+
173+
return nil
174+
}

codefresh/data_service_account.go

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package codefresh
2+
3+
import (
4+
"fmt"
5+
6+
cfClient "github.com/codefresh-io/terraform-provider-codefresh/codefresh/cfclient"
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
8+
)
9+
10+
func dataSourceServiceAccount() *schema.Resource {
11+
return &schema.Resource{
12+
Description: "This data source retrieves a Codefresh service account by its ID or name.",
13+
Read: dataSourceServiceAccountRead,
14+
Schema: map[string]*schema.Schema{
15+
"_id": {
16+
Type: schema.TypeString,
17+
Optional: true,
18+
},
19+
"name": {
20+
Description: "Service account name",
21+
Type: schema.TypeString,
22+
Optional: true,
23+
AtLeastOneOf: []string{"_id", "name"},
24+
},
25+
"assign_admin_role": {
26+
Description: "Whether or not account admin role is assigned to the service account",
27+
Type: schema.TypeBool,
28+
Optional: true,
29+
},
30+
"assigned_teams": {
31+
Description: "A list of team IDs the service account is be assigned to",
32+
Type: schema.TypeSet,
33+
Optional: true,
34+
Elem: &schema.Schema{
35+
Type: schema.TypeString,
36+
},
37+
},
38+
},
39+
}
40+
}
41+
42+
func dataSourceServiceAccountRead(d *schema.ResourceData, meta interface{}) error {
43+
44+
client := meta.(*cfClient.Client)
45+
var serviceAccount *cfClient.ServiceUser
46+
var err error
47+
48+
if _id, _idOk := d.GetOk("_id"); _idOk {
49+
serviceAccount, err = client.GetServiceUserByID(_id.(string))
50+
} else if name, nameOk := d.GetOk("name"); nameOk {
51+
serviceAccount, err = client.GetServiceUserByName(name.(string))
52+
}
53+
54+
if err != nil {
55+
return err
56+
}
57+
58+
if serviceAccount == nil {
59+
return fmt.Errorf("data.codefresh_service_account - cannot find service account")
60+
}
61+
62+
return mapDataServiceAccountToResource(serviceAccount, d)
63+
64+
}
65+
66+
func mapDataServiceAccountToResource(serviceAccount *cfClient.ServiceUser, d *schema.ResourceData) error {
67+
68+
if serviceAccount == nil || serviceAccount.ID == "" {
69+
return fmt.Errorf("data.codefresh_service_account - failed to mapDataServiceAccountToResource")
70+
}
71+
72+
d.SetId(serviceAccount.ID)
73+
d.Set("name", serviceAccount.Name)
74+
d.Set("assign_admin_role", serviceAccount.HasAdminRole())
75+
76+
teamIds := []string{}
77+
78+
for _, team := range serviceAccount.Teams {
79+
teamIds = append(teamIds, team.ID)
80+
}
81+
82+
d.Set("assigned_teams", teamIds)
83+
84+
return nil
85+
}

codefresh/provider.go

+2
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ func Provider() *schema.Provider {
5353
"codefresh_account_idp": dataSourceAccountIdp(),
5454
"codefresh_project": dataSourceProject(),
5555
"codefresh_account_gitops_settings": dataSourceAccountGitopsSettings(),
56+
"codefresh_service_account": dataSourceServiceAccount(),
5657
},
5758
ResourcesMap: map[string]*schema.Resource{
5859
"codefresh_account": resourceAccount(),
@@ -73,6 +74,7 @@ func Provider() *schema.Provider {
7374
"codefresh_idp": resourceIdp(),
7475
"codefresh_account_idp": resourceAccountIdp(),
7576
"codefresh_account_gitops_settings": resourceAccountGitopsSettings(),
77+
"codefresh_service_account": resourceServiceAccount(),
7678
},
7779
ConfigureFunc: configureProvider,
7880
}

0 commit comments

Comments
 (0)