diff --git a/acceptance/openstack/identity/v3.0/users_test.go b/acceptance/openstack/identity/v3.0/users_test.go index b33151253..ae3698a3b 100644 --- a/acceptance/openstack/identity/v3.0/users_test.go +++ b/acceptance/openstack/identity/v3.0/users_test.go @@ -2,6 +2,7 @@ package v3 import ( "os" + "strings" "testing" "github.com/opentelekomcloud/gophertelekomcloud/acceptance/clients" @@ -129,3 +130,72 @@ func TestSecurityLifecycle(t *testing.T) { th.AssertNoErr(t, err) tools.PrintResource(t, list) } + +func TestUserLifecycleSwiss(t *testing.T) { + if os.Getenv("OS_TENANT_ADMIN") == "" { + t.Skip("Policy doesn't allow NewIdentityV3AdminClient() to be initialized.") + } + + client, err := clients.NewIdentityV30AdminClient() + th.AssertNoErr(t, err) + + if !strings.Contains(client.Endpoint, "eu-ch2") { + t.Skip("Test is working only for SWISSCLOUD") + } + + oldClient, err := clients.NewIdentityV3AdminClient() + th.AssertNoErr(t, err) + + createOpts := users.CreateOpts{ + Name: tools.RandomString("user-name-", 4), + Enabled: pointerto.Bool(true), + DomainID: client.DomainID, + } + + user, err := users.CreateUser(client, createOpts) + if err != nil { + t.Fatalf("Unable to create user: %v", err) + } + + t.Cleanup(func() { + // SWISS requires xuser_type and xuser_id modification before deletion + _, err = users.ModifyUserAdmin(client, users.UpdateAdminOpts{ + XuserId: "", + XuserType: "", + Id: user.ID, + }) + th.AssertNoErr(t, err) + + err = oldusers.Delete(oldClient, user.ID).ExtractErr() + th.AssertNoErr(t, err) + }) + + th.AssertEquals(t, createOpts.Name, user.Name) + th.AssertEquals(t, *createOpts.Enabled, user.Enabled) + + userGet, err := users.GetUser(client, user.ID) + if err != nil { + t.Fatalf("Unable to retrieve user: %v", err) + } + + th.AssertEquals(t, userGet.Name, user.Name) + th.AssertEquals(t, userGet.Enabled, user.Enabled) + th.AssertEquals(t, userGet.Email, user.Email) + th.AssertEquals(t, userGet.DomainID, user.DomainID) + + updateOpts := users.UpdateOpts{ + Enabled: pointerto.Bool(false), + Name: tools.RandomString("new-user-name-", 4), + Password: tools.RandomString("Hello-world-", 5), + } + + userUpdate, err := users.ModifyUser(client, user.ID, updateOpts) + if err != nil { + t.Fatalf("Unable to update user info: %v", err) + } + + th.AssertEquals(t, userUpdate.Name, updateOpts.Name) + th.AssertEquals(t, userUpdate.Enabled, *updateOpts.Enabled) + th.AssertEquals(t, userUpdate.Email, updateOpts.Email) + th.AssertEquals(t, userUpdate.DomainID, userGet.DomainID) +} diff --git a/openstack/identity/v3.0/users/ModifyUserAdmin.go b/openstack/identity/v3.0/users/ModifyUserAdmin.go new file mode 100644 index 000000000..d08723dd4 --- /dev/null +++ b/openstack/identity/v3.0/users/ModifyUserAdmin.go @@ -0,0 +1,64 @@ +package users + +import ( + golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/build" + "github.com/opentelekomcloud/gophertelekomcloud/internal/extract" +) + +// UpdateAdminOpts provides options used to update user as administrator +type UpdateAdminOpts struct { + // Id is the IAM user ID + Id string `json:"-"` + + // Name is the name of the new user. + Name string `json:"name,omitempty"` + + // Password is the password of the new user. + Password string `json:"password,omitempty"` + + // Email address with a maximum of 255 characters + Email string `json:"email,omitempty"` + + // AreaCode is a country code, must be used together with Phone. + AreaCode string `json:"areacode,omitempty"` + + // Phone is a mobile number with a maximum of 32 digits, must be used together with AreaCode. + Phone string `json:"phone,omitempty"` + + // Description is a description of the user. + Description string `json:"description,omitempty"` + + // AccessMode is the access type for IAM user + AccessMode string `json:"access_mode,omitempty"` + + // Enabled sets the user status to enabled or disabled. + Enabled *bool `json:"enabled,omitempty"` + + // PwdStatus Indicates whether the user must change their password at the first login. + PwdStatus *bool `json:"pwd_status,omitempty"` + + // XuserType is the type of the user in the external system. + XuserType string `json:"xuser_type"` + + // XuserId is the ID of the user in the external system. + XuserId string `json:"xuser_id"` +} + +func ModifyUserAdmin(client *golangsdk.ServiceClient, opts UpdateAdminOpts) (*User, error) { + b, err := build.RequestBody(opts, "user") + if err != nil { + return nil, err + } + + // PUT /v3.0/OS-USER/users/{user_id} + raw, err := client.Put(client.ServiceURL("OS-USER", "users", opts.Id), b, nil, &golangsdk.RequestOpts{ + OkCodes: []int{200}, + }) + if err != nil { + return nil, err + } + + var res User + return &res, extract.IntoStructPtr(raw.Body, &res, "user") +}