Skip to content

Commit 7ab4ccd

Browse files
gbloquelremyleoneCodelax
authored
feat(iam): add iam user resource (#2152)
* feat(iam): add iam user resource * fix(iam): type on last_login_at * docs(iam): fix lint * chore: fix provider.go and rename invalid file --------- Co-authored-by: Gregory Bloquel <[email protected]> Co-authored-by: Rémy Léone <[email protected]> Co-authored-by: Jules Casteran <[email protected]>
1 parent 5759d40 commit 7ab4ccd

File tree

5 files changed

+486
-0
lines changed

5 files changed

+486
-0
lines changed

docs/resources/iam_user.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
---
2+
subcategory: "IAM"
3+
page_title: "Scaleway: scaleway_iam_user"
4+
---
5+
6+
# scaleway_iam_user
7+
8+
Creates and manages Scaleway IAM Users.
9+
For more information, see [the documentation](https://www.scaleway.com/en/developers/api/iam/#path-users-list-users-of-an-organization).
10+
11+
## Examples
12+
13+
### Basic
14+
15+
```hcl
16+
resource "scaleway_iam_user" "basic" {
17+
18+
}
19+
```
20+
21+
## Argument Reference
22+
23+
- `email` - (Required) The email of the IAM user.
24+
25+
- `organization_id` - (Defaults to [provider](../index.md#organization_d) `organization_id`) The ID of the organization the user is associated with.
26+
27+
## Attributes Reference
28+
29+
In addition to all above arguments, the following attributes are exported:
30+
31+
- `id` - The ID of the user (UUID format).
32+
- `email` - The email of the user
33+
- `created_at` - The date and time of the creation of the iam user.
34+
- `updated_at` - The date and time of the last update of the iam user.
35+
- `deletable` - Whether the iam user is deletable.
36+
- `organization_id` - The ID of the organization the user.
37+
- `last_login_at` - The date of the last login.
38+
- `type` - The type of user. Check the possible values on
39+
our [sdk](https://github.com/scaleway/scaleway-sdk-go/blob/master/api/iam/v1alpha1/iam_sdk.go#L508-L515C2).
40+
- `two_factor_enabled` - Deprecated, use "mfa" instead.
41+
- `status` - The status of user invitation. Check the possible values on
42+
our [sdk](https://github.com/scaleway/scaleway-sdk-go/blob/master/api/iam/v1alpha1/iam_sdk.go#L475-L480).
43+
- `mfa` - Whether the MFA is enabled.
44+
- `account_root_user_id` - The ID of the account root user associated with the user.
45+
46+
## Import
47+
48+
IAM users can be imported using the `{id}`, e.g.
49+
50+
```bash
51+
$ terraform import scaleway_iam_user.basic 11111111-1111-1111-1111-111111111111
52+
```

scaleway/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ func Provider(config *ProviderConfig) plugin.ProviderFunc {
116116
"scaleway_iam_group": resourceScalewayIamGroup(),
117117
"scaleway_iam_group_membership": resourceScalewayIamGroupMembership(),
118118
"scaleway_iam_policy": resourceScalewayIamPolicy(),
119+
"scaleway_iam_user": resourceScalewayIamUser(),
119120
"scaleway_instance_user_data": resourceScalewayInstanceUserData(),
120121
"scaleway_instance_image": resourceScalewayInstanceImage(),
121122
"scaleway_instance_ip": resourceScalewayInstanceIP(),

scaleway/resource_iam_user.go

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
package scaleway
2+
3+
//#TODO see update empty
4+
5+
import (
6+
"context"
7+
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
10+
iam "github.com/scaleway/scaleway-sdk-go/api/iam/v1alpha1"
11+
"github.com/scaleway/scaleway-sdk-go/scw"
12+
)
13+
14+
func resourceScalewayIamUser() *schema.Resource {
15+
return &schema.Resource{
16+
CreateContext: resourceScalewayIamUserCreate,
17+
ReadContext: resourceScalewayIamUserRead,
18+
DeleteContext: resourceScalewayIamUserDelete,
19+
Importer: &schema.ResourceImporter{
20+
StateContext: schema.ImportStatePassthroughContext,
21+
},
22+
SchemaVersion: 0,
23+
Schema: map[string]*schema.Schema{
24+
"email": {
25+
Type: schema.TypeString,
26+
Required: true,
27+
ForceNew: true,
28+
Description: "The description of the iam user",
29+
},
30+
"created_at": {
31+
Type: schema.TypeString,
32+
Computed: true,
33+
Description: "The date and time of the creation of the iam user",
34+
},
35+
"updated_at": {
36+
Type: schema.TypeString,
37+
Computed: true,
38+
Description: "The date and time of the last update of the iam user",
39+
},
40+
"deletable": {
41+
Type: schema.TypeBool,
42+
Computed: true,
43+
Description: "Whether or not the iam user is editable",
44+
},
45+
"last_login_at": {
46+
Type: schema.TypeString,
47+
Computed: true,
48+
Description: "The date and time of last login of the iam user",
49+
},
50+
"type": {
51+
Type: schema.TypeString,
52+
Computed: true,
53+
Description: "The type of the iam user",
54+
},
55+
"two_factor_enabled": {
56+
Type: schema.TypeBool,
57+
Computed: true,
58+
Description: "Deprecated, use 'mfa' instead.",
59+
},
60+
"status": {
61+
Type: schema.TypeString,
62+
Computed: true,
63+
Description: "The status of user invitation.",
64+
},
65+
"mfa": {
66+
Type: schema.TypeBool,
67+
Computed: true,
68+
Description: "Whether or not the MFA is enabled",
69+
},
70+
"account_root_user_id": {
71+
Type: schema.TypeString,
72+
Computed: true,
73+
Description: "The ID of the account root user associated with the iam user.",
74+
},
75+
"organization_id": organizationIDOptionalSchema(),
76+
},
77+
}
78+
}
79+
80+
func resourceScalewayIamUserCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
81+
iamAPI := iamAPI(meta)
82+
user, err := iamAPI.CreateUser(&iam.CreateUserRequest{
83+
OrganizationID: d.Get("organization_id").(string),
84+
Email: d.Get("email").(string),
85+
}, scw.WithContext(ctx))
86+
if err != nil {
87+
return diag.FromErr(err)
88+
}
89+
90+
d.SetId(user.ID)
91+
92+
return resourceScalewayIamUserRead(ctx, d, meta)
93+
}
94+
95+
func resourceScalewayIamUserRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
96+
api := iamAPI(meta)
97+
user, err := api.GetUser(&iam.GetUserRequest{
98+
UserID: d.Id(),
99+
}, scw.WithContext(ctx))
100+
if err != nil {
101+
if is404Error(err) {
102+
d.SetId("")
103+
return nil
104+
}
105+
return diag.FromErr(err)
106+
}
107+
108+
_ = d.Set("email", user.Email)
109+
_ = d.Set("created_at", flattenTime(user.CreatedAt))
110+
_ = d.Set("updated_at", flattenTime(user.UpdatedAt))
111+
_ = d.Set("organization_id", user.OrganizationID)
112+
_ = d.Set("deletable", user.Deletable)
113+
_ = d.Set("last_login_at", flattenTime(user.LastLoginAt))
114+
_ = d.Set("type", user.Type)
115+
_ = d.Set("two_factor_enabled", user.TwoFactorEnabled)
116+
_ = d.Set("status", user.Status)
117+
_ = d.Set("mfa", user.Mfa)
118+
119+
return nil
120+
}
121+
122+
func resourceScalewayIamUserDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
123+
api := iamAPI(meta)
124+
125+
err := api.DeleteUser(&iam.DeleteUserRequest{
126+
UserID: d.Id(),
127+
}, scw.WithContext(ctx))
128+
if err != nil && !is404Error(err) {
129+
return diag.FromErr(err)
130+
}
131+
132+
return nil
133+
}

scaleway/resource_iam_user_test.go

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package scaleway
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
9+
iam "github.com/scaleway/scaleway-sdk-go/api/iam/v1alpha1"
10+
"github.com/scaleway/scaleway-sdk-go/scw"
11+
)
12+
13+
func init() {
14+
resource.AddTestSweepers("scaleway_iam_user", &resource.Sweeper{
15+
Name: "scaleway_iam_user",
16+
F: testSweepIamUser,
17+
})
18+
}
19+
20+
func testSweepIamUser(_ string) error {
21+
return sweep(func(scwClient *scw.Client) error {
22+
api := iam.NewAPI(scwClient)
23+
24+
orgID, exists := scwClient.GetDefaultOrganizationID()
25+
if !exists {
26+
return fmt.Errorf("missing organizationID")
27+
}
28+
29+
listUsers, err := api.ListUsers(&iam.ListUsersRequest{
30+
OrganizationID: &orgID,
31+
})
32+
if err != nil {
33+
return fmt.Errorf("failed to list users: %w", err)
34+
}
35+
for _, user := range listUsers.Users {
36+
if !isTestResource(user.Email) {
37+
continue
38+
}
39+
err = api.DeleteUser(&iam.DeleteUserRequest{
40+
UserID: user.ID,
41+
})
42+
if err != nil {
43+
return fmt.Errorf("failed to delete user: %w", err)
44+
}
45+
}
46+
return nil
47+
})
48+
}
49+
50+
func TestAccScalewayIamUser_Basic(t *testing.T) {
51+
tt := NewTestTools(t)
52+
defer tt.Cleanup()
53+
resource.ParallelTest(t, resource.TestCase{
54+
ProviderFactories: tt.ProviderFactories,
55+
CheckDestroy: testAccCheckScalewayIamUserDestroy(tt),
56+
Steps: []resource.TestStep{
57+
{
58+
Config: `
59+
resource "scaleway_iam_user" "user_basic" {
60+
61+
}
62+
`,
63+
Check: resource.ComposeTestCheckFunc(
64+
testAccCheckScalewayIamUserExists(tt, "scaleway_iam_user.user_basic"),
65+
testCheckResourceAttrUUID("scaleway_iam_user.user_basic", "id"),
66+
resource.TestCheckResourceAttr("scaleway_iam_user.user_basic", "email", "[email protected]"),
67+
),
68+
},
69+
},
70+
})
71+
}
72+
73+
func testAccCheckScalewayIamUserDestroy(tt *TestTools) resource.TestCheckFunc {
74+
return func(s *terraform.State) error {
75+
for _, rs := range s.RootModule().Resources {
76+
if rs.Type != "scaleway_iam_user" {
77+
continue
78+
}
79+
80+
iamAPI := iamAPI(tt.Meta)
81+
82+
_, err := iamAPI.GetUser(&iam.GetUserRequest{
83+
UserID: rs.Primary.ID,
84+
})
85+
86+
// If no error resource still exist
87+
if err == nil {
88+
return fmt.Errorf("resource %s(%s) still exist", rs.Type, rs.Primary.ID)
89+
}
90+
91+
// Unexpected api error we return it
92+
if !is404Error(err) {
93+
return err
94+
}
95+
}
96+
97+
return nil
98+
}
99+
}

0 commit comments

Comments
 (0)