-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(lh-86966): add new Terraform resource to manage users in an MSP-…
…managed tenant (#146) * feat(lh-86966): add new Terraform resource to manage users in an MSP-managed tenant This adds a new resource that allows an MSP portal super-admin to create users in a tenant managed by the MSP portal. * refactor(lh-86966): address Ido's comments Also add validator for user role
- Loading branch information
1 parent
0306b38
commit bf6e271
Showing
24 changed files
with
739 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package users_test | ||
|
||
const ( | ||
baseUrl = "https://unittest.cdo.cisco.com" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package users | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/internal/http" | ||
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/internal/publicapi" | ||
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/internal/url" | ||
) | ||
|
||
func Create(ctx context.Context, client http.Client, createInp MspCreateUsersInput) (*[]UserDetails, *CreateError) { | ||
client.Logger.Printf("Creating %d users in %s\n", len(createInp.Users), createInp.TenantUid) | ||
createUrl := url.CreateUsersInMspManagedTenant(client.BaseUrl(), createInp.TenantUid) | ||
transaction, err := publicapi.TriggerTransaction( | ||
ctx, | ||
client, | ||
createUrl, | ||
createInp, | ||
) | ||
if err != nil { | ||
return nil, &CreateError{ | ||
Err: err, | ||
CreatedResourceId: &transaction.EntityUid, | ||
} | ||
} | ||
transaction, err = publicapi.WaitForTransactionToFinishWithDefaults( | ||
ctx, | ||
client, | ||
transaction, | ||
fmt.Sprintf("Waiting for users to be created and added to MSP-managed tenant %s...", createInp.TenantUid), | ||
) | ||
if err != nil { | ||
return nil, &CreateError{ | ||
Err: err, | ||
CreatedResourceId: &transaction.EntityUid, | ||
} | ||
} | ||
|
||
return &createInp.Users, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
package users_test | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/internal/http" | ||
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/internal/publicapi" | ||
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/internal/publicapi/transaction" | ||
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/internal/publicapi/transaction/transactionstatus" | ||
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/internal/publicapi/transaction/transactiontype" | ||
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/model/user/auth/role" | ||
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/msp/users" | ||
"github.com/google/uuid" | ||
"github.com/jarcoal/httpmock" | ||
"github.com/stretchr/testify/assert" | ||
netHttp "net/http" | ||
"testing" | ||
"time" | ||
) | ||
|
||
func TestCreate(t *testing.T) { | ||
httpmock.Activate() | ||
defer httpmock.DeactivateAndReset() | ||
|
||
t.Run("successfully create users in MSP-managed tenant", func(t *testing.T) { | ||
httpmock.Reset() | ||
var managedTenantUid = uuid.New().String() | ||
var createInp = users.MspCreateUsersInput{ | ||
TenantUid: managedTenantUid, | ||
Users: []users.UserDetails{ | ||
{Username: "[email protected]", Role: string(role.SuperAdmin), ApiOnlyUser: false}, | ||
{Username: "api-only-user", Role: string(role.ReadOnly), ApiOnlyUser: true}, | ||
}, | ||
} | ||
var transactionUid = uuid.New().String() | ||
var inProgressTransaction = transaction.Type{ | ||
TransactionUid: transactionUid, | ||
TenantUid: uuid.New().String(), | ||
EntityUid: managedTenantUid, | ||
EntityUrl: "https://unittest.cdo.cisco.com/api/rest/v1/msp/tenants/" + managedTenantUid, | ||
PollingUrl: "https://unittest.cdo.cisco.com/api/rest/v1/transactions/" + transactionUid, | ||
SubmissionTime: "2024-09-10T20:10:00Z", | ||
LastUpdatedTime: "2024-10-10T20:10:00Z", | ||
Type: transactiontype.MSP_ADD_USERS_TO_TENANT, | ||
Status: transactionstatus.IN_PROGRESS, | ||
} | ||
var doneTransaction = transaction.Type{ | ||
TransactionUid: transactionUid, | ||
TenantUid: uuid.New().String(), | ||
EntityUid: managedTenantUid, | ||
EntityUrl: "https://unittest.cdo.cisco.com/api/rest/v1/msp/tenants/" + managedTenantUid, | ||
PollingUrl: "https://unittest.cdo.cisco.com/api/rest/v1/transactions/" + transactionUid, | ||
SubmissionTime: "2024-09-10T20:10:00Z", | ||
LastUpdatedTime: "2024-10-10T20:10:00Z", | ||
Type: transactiontype.MSP_ADD_USERS_TO_TENANT, | ||
Status: transactionstatus.DONE, | ||
} | ||
|
||
httpmock.RegisterResponder( | ||
netHttp.MethodPost, | ||
fmt.Sprintf("/api/rest/v1/msp/tenants/%s/users", managedTenantUid), | ||
httpmock.NewJsonResponderOrPanic(200, inProgressTransaction), | ||
) | ||
httpmock.RegisterResponder( | ||
netHttp.MethodGet, | ||
inProgressTransaction.PollingUrl, | ||
httpmock.NewJsonResponderOrPanic(200, doneTransaction), | ||
) | ||
|
||
actual, err := users.Create(context.Background(), *http.MustNewWithConfig(baseUrl, "valid_token", 0, 0, time.Minute), createInp) | ||
|
||
assert.NotNil(t, actual, "Created users should have not been nil") | ||
assert.Nil(t, err, "Created users operation should have not been an error") | ||
assert.Equal(t, createInp.Users, *actual, "Created users operation should have been the same as the created tenant") | ||
}) | ||
|
||
t.Run("user creation transaction fails", func(t *testing.T) { | ||
httpmock.Reset() | ||
var managedTenantUid = uuid.New().String() | ||
var createInp = users.MspCreateUsersInput{ | ||
TenantUid: managedTenantUid, | ||
Users: []users.UserDetails{ | ||
{Username: "[email protected]", Role: string(role.SuperAdmin), ApiOnlyUser: false}, | ||
{Username: "api-only-user", Role: string(role.ReadOnly), ApiOnlyUser: true}, | ||
}, | ||
} | ||
var transactionUid = uuid.New().String() | ||
var inProgressTransaction = transaction.Type{ | ||
TransactionUid: transactionUid, | ||
TenantUid: uuid.New().String(), | ||
EntityUid: managedTenantUid, | ||
EntityUrl: "https://unittest.cdo.cisco.com/api/rest/v1/msp/tenants/" + managedTenantUid, | ||
PollingUrl: "https://unittest.cdo.cisco.com/api/rest/v1/transactions/" + transactionUid, | ||
SubmissionTime: "2024-09-10T20:10:00Z", | ||
LastUpdatedTime: "2024-10-10T20:10:00Z", | ||
Type: transactiontype.MSP_ADD_USERS_TO_TENANT, | ||
Status: transactionstatus.IN_PROGRESS, | ||
} | ||
var errorTransaction = transaction.Type{ | ||
TransactionUid: transactionUid, | ||
TenantUid: uuid.New().String(), | ||
EntityUid: managedTenantUid, | ||
EntityUrl: "https://unittest.cdo.cisco.com/api/rest/v1/msp/tenants/" + managedTenantUid, | ||
PollingUrl: "https://unittest.cdo.cisco.com/api/rest/v1/transactions/" + transactionUid, | ||
SubmissionTime: "2024-09-10T20:10:00Z", | ||
LastUpdatedTime: "2024-10-10T20:10:00Z", | ||
Type: transactiontype.MSP_ADD_USERS_TO_TENANT, | ||
Status: transactionstatus.ERROR, | ||
} | ||
|
||
httpmock.RegisterResponder( | ||
netHttp.MethodPost, | ||
fmt.Sprintf("/api/rest/v1/msp/tenants/%s/users", managedTenantUid), | ||
httpmock.NewJsonResponderOrPanic(200, inProgressTransaction), | ||
) | ||
httpmock.RegisterResponder( | ||
netHttp.MethodGet, | ||
inProgressTransaction.PollingUrl, | ||
httpmock.NewJsonResponderOrPanic(200, errorTransaction), | ||
) | ||
|
||
actual, err := users.Create(context.Background(), *http.MustNewWithConfig(baseUrl, "valid_token", 0, 0, time.Minute), createInp) | ||
|
||
assert.Nil(t, actual, "Created users should be nil") | ||
assert.NotNil(t, err, "Created users in tenant operation should have an error") | ||
assert.Equal(t, users.CreateError{ | ||
Err: publicapi.NewTransactionErrorFromTransaction(errorTransaction), | ||
CreatedResourceId: &managedTenantUid, | ||
}, *err, "created transaction error does not match") | ||
}) | ||
|
||
t.Run("user creation API call fails", func(t *testing.T) { | ||
httpmock.Reset() | ||
var managedTenantUid = uuid.New().String() | ||
var createInp = users.MspCreateUsersInput{ | ||
TenantUid: managedTenantUid, | ||
Users: []users.UserDetails{ | ||
{Username: "[email protected]", Role: string(role.SuperAdmin), ApiOnlyUser: false}, | ||
{Username: "api-only-user", Role: string(role.ReadOnly), ApiOnlyUser: true}, | ||
}, | ||
} | ||
var transactionUid = uuid.New().String() | ||
var errorTransaction = transaction.Type{ | ||
TransactionUid: transactionUid, | ||
TenantUid: uuid.New().String(), | ||
EntityUid: managedTenantUid, | ||
EntityUrl: "https://unittest.cdo.cisco.com/api/rest/v1/msp/tenants/" + managedTenantUid, | ||
PollingUrl: "https://unittest.cdo.cisco.com/api/rest/v1/transactions/" + transactionUid, | ||
SubmissionTime: "2024-09-10T20:10:00Z", | ||
LastUpdatedTime: "2024-10-10T20:10:00Z", | ||
Type: transactiontype.MSP_ADD_USERS_TO_TENANT, | ||
Status: transactionstatus.ERROR, | ||
} | ||
|
||
httpmock.RegisterResponder( | ||
netHttp.MethodPost, | ||
fmt.Sprintf("/api/rest/v1/msp/tenants/%s/users", managedTenantUid), | ||
httpmock.NewJsonResponderOrPanic(200, errorTransaction), | ||
) | ||
actual, err := users.Create(context.Background(), *http.MustNewWithConfig(baseUrl, "valid_token", 0, 0, time.Minute), createInp) | ||
|
||
assert.Nil(t, actual, "Created users in tenant should have not been nil") | ||
assert.NotNil(t, err, "Created users in tenant operation should have not been an error") | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package users | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/internal/http" | ||
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/internal/publicapi" | ||
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/internal/url" | ||
) | ||
|
||
func Delete(ctx context.Context, client http.Client, deleteInp MspDeleteUsersInput) (interface{}, error) { | ||
client.Logger.Printf("Deleting %d users in %s\n", len(deleteInp.Usernames), deleteInp.TenantUid) | ||
deleteUrl := url.DeleteUsersInMspManagedTenant(client.BaseUrl(), deleteInp.TenantUid) | ||
transaction, err := publicapi.TriggerTransaction( | ||
ctx, | ||
client, | ||
deleteUrl, | ||
deleteInp, | ||
) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
transaction, err = publicapi.WaitForTransactionToFinishWithDefaults( | ||
ctx, | ||
client, | ||
transaction, | ||
fmt.Sprintf("Waiting for users to be deleted from MSP-managed tenant %s...", deleteInp.TenantUid), | ||
) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return nil, nil | ||
} |
Oops, something went wrong.