Skip to content

Commit 6a4a8f4

Browse files
authored
Merge pull request #18 from CruGlobal/external-user-shouldnt-make-changes
fix(external_user): Refactor external_user from resource to data source.
2 parents 8ef52f1 + c3a7602 commit 6a4a8f4

File tree

11 files changed

+411
-536
lines changed

11 files changed

+411
-536
lines changed

docs/data-sources/external_user.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "semaphoreui_external_user Data Source - semaphoreui"
4+
subcategory: ""
5+
description: |-
6+
7+
---
8+
9+
# semaphoreui_external_user (Data Source)
10+
11+
12+
13+
## Example Usage
14+
15+
```terraform
16+
# Lookup or Create External User
17+
data "semaphoreui_user" "user" {
18+
username = "batman"
19+
}
20+
21+
# Lookup or Create External User with additional attributes
22+
data "semaphoreui_user" "batman" {
23+
username = "batman"
24+
name = "Bruce Wayne"
25+
26+
}
27+
```
28+
29+
<!-- schema generated by tfplugindocs -->
30+
## Schema
31+
32+
### Required
33+
34+
- `username` (String) Username.
35+
36+
### Optional
37+
38+
- `email` (String) Email address. Defaults to the username if not supplied.
39+
- `name` (String) Display name. Defaults to the username if not supplied.
40+
41+
### Read-Only
42+
43+
- `admin` (Boolean) Indicates if the user is an admin.
44+
- `alert` (Boolean) Indicates if alerts should be sent to the user's email.
45+
- `created` (String) Creation date of the user.
46+
- `external` (Boolean) Indicates if the user is linked to an external identity provider.
47+
- `id` (Number) The ID of the external user.

docs/resources/external_user.md

Lines changed: 0 additions & 61 deletions
This file was deleted.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Lookup or Create External User
2+
data "semaphoreui_user" "user" {
3+
username = "batman"
4+
}
5+
6+
# Lookup or Create External User with additional attributes
7+
data "semaphoreui_user" "batman" {
8+
username = "batman"
9+
name = "Bruce Wayne"
10+
11+
}

examples/resources/semaphoreui_external_user/import.sh

Lines changed: 0 additions & 10 deletions
This file was deleted.

examples/resources/semaphoreui_external_user/resource.tf

Lines changed: 0 additions & 8 deletions
This file was deleted.
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
package provider
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"github.com/hashicorp/terraform-plugin-framework/types"
7+
apiclient "terraform-provider-semaphoreui/semaphoreui/client"
8+
"terraform-provider-semaphoreui/semaphoreui/client/user"
9+
"terraform-provider-semaphoreui/semaphoreui/models"
10+
11+
"github.com/hashicorp/terraform-plugin-framework/datasource"
12+
)
13+
14+
// Ensure the implementation satisfies the expected interfaces.
15+
var (
16+
_ datasource.DataSource = &externalUserDataSource{}
17+
)
18+
19+
func NewExternalUserDataSource() datasource.DataSource {
20+
return &externalUserDataSource{}
21+
}
22+
23+
type externalUserDataSource struct {
24+
client *apiclient.SemaphoreUI
25+
}
26+
27+
func (d *externalUserDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
28+
if req.ProviderData == nil {
29+
return
30+
}
31+
32+
client, ok := req.ProviderData.(*apiclient.SemaphoreUI)
33+
if !ok {
34+
resp.Diagnostics.AddError(
35+
"Unexpected Resource Configure Type",
36+
"Expected *client.SemaphoreUI, got %T. Please report this issue to the provider developers.",
37+
)
38+
return
39+
}
40+
d.client = client
41+
}
42+
43+
// Metadata returns the data source type name.
44+
func (d *externalUserDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
45+
resp.TypeName = req.ProviderTypeName + "_external_user"
46+
}
47+
48+
// Schema defines the schema for the data source.
49+
func (d *externalUserDataSource) Schema(ctx context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
50+
resp.Schema = ExternalUserSchema().GetDataSource(ctx)
51+
}
52+
53+
func convertResponseToExternalUserModel(user *models.User) ExternalUserModel {
54+
return ExternalUserModel{
55+
ID: types.Int64Value(user.ID),
56+
Username: types.StringValue(user.Username),
57+
Name: types.StringValue(user.Name),
58+
Email: types.StringValue(user.Email),
59+
Admin: types.BoolValue(user.Admin),
60+
Alert: types.BoolValue(user.Alert),
61+
External: types.BoolValue(user.External),
62+
Created: types.StringValue(user.Created),
63+
}
64+
}
65+
66+
func convertExternalUserModelToUserRequest(user ExternalUserModel) *models.UserRequest {
67+
userRequest := models.UserRequest{
68+
Username: user.Username.ValueString(),
69+
Name: user.Name.ValueString(),
70+
Email: user.Email.ValueString(),
71+
External: true,
72+
}
73+
if !user.Name.IsUnknown() && !user.Name.IsNull() {
74+
userRequest.Name = user.Name.ValueString()
75+
} else {
76+
userRequest.Name = user.Username.ValueString()
77+
}
78+
if !user.Email.IsUnknown() && !user.Email.IsNull() {
79+
userRequest.Email = user.Email.ValueString()
80+
} else {
81+
userRequest.Email = user.Username.ValueString()
82+
}
83+
return &userRequest
84+
}
85+
86+
func (r *externalUserDataSource) GetExternalUserByUsername(username string) (*ExternalUserModel, error) {
87+
response, err := r.client.User.GetUsers(&user.GetUsersParams{}, nil)
88+
if err != nil {
89+
return nil, fmt.Errorf("could not get users: %s", err.Error())
90+
}
91+
for _, usr := range response.Payload {
92+
if usr.Username == username {
93+
if !usr.External {
94+
return nil, fmt.Errorf("user with username %s is not an external user", username)
95+
}
96+
model := convertResponseToExternalUserModel(usr)
97+
return &model, nil
98+
}
99+
}
100+
return nil, fmt.Errorf("user with username %s not found", username)
101+
}
102+
103+
func (d *externalUserDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
104+
var config ExternalUserModel
105+
resp.Diagnostics.Append(req.Config.Get(ctx, &config)...)
106+
if resp.Diagnostics.HasError() {
107+
return
108+
}
109+
110+
// Lookup user by username
111+
externalUser, err := d.GetExternalUserByUsername(config.Username.ValueString())
112+
if err != nil {
113+
// If user not found, create new user
114+
if err.Error() == fmt.Sprintf("user with username %s not found", config.Username.ValueString()) {
115+
response, err := d.client.User.PostUsers(&user.PostUsersParams{
116+
User: convertExternalUserModelToUserRequest(config),
117+
}, nil)
118+
if err != nil {
119+
resp.Diagnostics.AddError(
120+
"Error Reading SemaphoreUI User",
121+
"Could not create user, unexpected error: "+err.Error(),
122+
)
123+
return
124+
}
125+
usr := convertResponseToExternalUserModel(response.Payload)
126+
externalUser = &usr
127+
} else {
128+
resp.Diagnostics.AddError(
129+
"Error Reading SemaphoreUI User",
130+
err.Error(),
131+
)
132+
return
133+
}
134+
}
135+
136+
resp.Diagnostics.Append(resp.State.Set(ctx, externalUser)...)
137+
if resp.Diagnostics.HasError() {
138+
return
139+
}
140+
}

0 commit comments

Comments
 (0)