diff --git a/CHANGELOG.md b/CHANGELOG.md index 60c858957..aa48e6a18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ ## Enhancements * Adds the `ProviderType` field to `AdminSAMLSetting` and `AdminSAMLSettingsUpdateOptions` to support the `provider-type` SAML setting by @skj-skj [#1303](https://github.com/hashicorp/go-tfe/pull/1303) * Adds `AdminSCIMSetting` to support managing site-level SCIM settings by @skj-skj [#1307](https://github.com/hashicorp/go-tfe/pull/1307) +* Adds `AdminSCIMToken` to support managing site-level SCIM tokens by @skj-skj [#1310](https://github.com/hashicorp/go-tfe/pull/1310) # v1.103.0 diff --git a/admin_setting.go b/admin_setting.go index a7cf5e166..684356a1a 100644 --- a/admin_setting.go +++ b/admin_setting.go @@ -3,6 +3,12 @@ package tfe +// SCIMResource groups the SCIM related resources together. +type SCIMResource struct { + SCIMSettings + Tokens AdminSCIMTokens +} + // AdminSettings describes all the admin settings related methods that the Terraform Enterprise API supports. // Note that admin settings are only available in Terraform Enterprise. // @@ -15,7 +21,7 @@ type AdminSettings struct { Twilio TwilioSettings Customization CustomizationSettings OIDC OIDCSettings - SCIM SCIMSettings + SCIM *SCIMResource } func newAdminSettings(client *Client) *AdminSettings { @@ -27,6 +33,9 @@ func newAdminSettings(client *Client) *AdminSettings { Twilio: &adminTwilioSettings{client: client}, Customization: &adminCustomizationSettings{client: client}, OIDC: &adminOIDCSettings{client: client}, - SCIM: &adminSCIMSettings{client: client}, + SCIM: &SCIMResource{ + SCIMSettings: &adminSCIMSettings{client: client}, + Tokens: &adminSCIMTokens{client: client}, + }, } } diff --git a/admin_setting_scim_integration_test.go b/admin_setting_scim_integration_test.go index 5809a63ac..6e13efb73 100644 --- a/admin_setting_scim_integration_test.go +++ b/admin_setting_scim_integration_test.go @@ -6,7 +6,6 @@ package tfe import ( "context" "testing" - "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -87,8 +86,10 @@ func TestAdminSettings_SCIM_Update(t *testing.T) { _, err = scimClient.Update(ctx, AdminSCIMSettingUpdateOptions{Enabled: Bool(true)}) require.NoError(t, err) - scimToken := generateSCIMToken(ctx, t, client) - scimGroupID := createSCIMGroup(ctx, t, client, "foo", scimToken) + scimToken, err := scimClient.Tokens.Create(ctx, "scim integration test token") + require.NoError(t, err) + require.NotEmpty(t, scimToken.Token) + scimGroupID := createSCIMGroup(ctx, t, client, "foo", scimToken.Token) testCases := []struct { name string @@ -169,28 +170,3 @@ func cleanupSCIMSettings(ctx context.Context, t *testing.T, client *Client) { err = setSAMLProviderType(ctx, t, client, false) require.NoErrorf(t, err, "failed to set SAML provider type") } - -// generate a SCIM token for testing -func generateSCIMToken(ctx context.Context, t *testing.T, client *Client) string { - t.Helper() - // TFE requires a minimum of 30 days for SCIM token expiration - expiredAt := time.Now().Add(30 * 24 * time.Hour) - - options := struct { - Description *string `jsonapi:"attr,description"` - ExpiredAt *time.Time `jsonapi:"attr,expired-at,iso8601"` - }{ - Description: String("test-scim-token"), - ExpiredAt: &expiredAt, - } - req, err := client.NewRequest("POST", "admin/scim-tokens", &options) - require.NoError(t, err) - - var res struct { - Token string `jsonapi:"attr,token"` - } - err = req.Do(ctx, &res) - require.NoError(t, err) - - return res.Token -} diff --git a/admin_setting_scim_token.go b/admin_setting_scim_token.go new file mode 100644 index 000000000..793af7e3d --- /dev/null +++ b/admin_setting_scim_token.go @@ -0,0 +1,135 @@ +// Copyright IBM Corp. 2018, 2026 +// SPDX-License-Identifier: MPL-2.0 + +package tfe + +import ( + "context" + "fmt" + "net/url" + "time" +) + +var _ AdminSCIMTokens = (*adminSCIMTokens)(nil) + +// AdminSCIMTokens describes all the Admin SCIM token related methods that the Terraform +// Enterprise API supports +// +// TFE API docs: https://developer.hashicorp.com/terraform/enterprise/api-docs/admin/scim-tokens +type AdminSCIMTokens interface { + // List all Admin SCIM tokens. + List(ctx context.Context) (*AdminSCIMTokenList, error) + + // Create an Admin SCIM token. + Create(ctx context.Context, description string) (*AdminSCIMToken, error) + + // Create an Admin SCIM token with options. + CreateWithOptions(ctx context.Context, options AdminSCIMTokenCreateOptions) (*AdminSCIMToken, error) + + // Read an Admin SCIM token by its ID. + Read(ctx context.Context, scimTokenID string) (*AdminSCIMToken, error) + + // Delete an Admin SCIM token. + Delete(ctx context.Context, scimTokenID string) error +} + +// adminSCIMTokens implements AdminSCIMTokens +type adminSCIMTokens struct { + client *Client +} + +// AdminSCIMTokenList represents a list of Admin SCIM tokens +type AdminSCIMTokenList struct { + Items []*AdminSCIMToken +} + +// AdminSCIMToken represents a Terraform Enterprise Admin SCIM token. +type AdminSCIMToken struct { + ID string `jsonapi:"primary,authentication-tokens"` + CreatedAt time.Time `jsonapi:"attr,created-at,iso8601"` + LastUsedAt time.Time `jsonapi:"attr,last-used-at,iso8601"` + ExpiredAt time.Time `jsonapi:"attr,expired-at,iso8601"` + Description string `jsonapi:"attr,description"` + Token string `jsonapi:"attr,token,omitempty"` +} + +// AdminSCIMTokenCreateOptions represents the options for creating an Admin SCIM token +type AdminSCIMTokenCreateOptions struct { + // Required: A human-readable description of the token's purpose + // (for example, Okta SCIM Integration). + Description *string `jsonapi:"attr,description"` + + // Optional: Optional ISO-8601 timestamp for token expiration. + // Defaults to 365 days in the future. Must be between 29 and 365 days in the future. + ExpiredAt *time.Time `jsonapi:"attr,expired-at,iso8601,omitempty"` +} + +// List all Admin SCIM tokens. +func (a *adminSCIMTokens) List(ctx context.Context) (*AdminSCIMTokenList, error) { + req, err := a.client.NewRequest("GET", AdminSCIMTokensPath, nil) + if err != nil { + return nil, err + } + + scimTokens := &AdminSCIMTokenList{} + err = req.Do(ctx, scimTokens) + if err != nil { + return nil, err + } + return scimTokens, nil +} + +// Create an Admin SCIM token. +func (a *adminSCIMTokens) Create(ctx context.Context, description string) (*AdminSCIMToken, error) { + return a.CreateWithOptions(ctx, AdminSCIMTokenCreateOptions{ + Description: &description, + }) +} + +// Create an Admin SCIM token with options. +func (a *adminSCIMTokens) CreateWithOptions(ctx context.Context, options AdminSCIMTokenCreateOptions) (*AdminSCIMToken, error) { + if !validString(options.Description) { + return nil, ErrSCIMTokenDescription + } + req, err := a.client.NewRequest("POST", AdminSCIMTokensPath, &options) + if err != nil { + return nil, err + } + scimToken := &AdminSCIMToken{} + err = req.Do(ctx, scimToken) + if err != nil { + return nil, err + } + return scimToken, nil +} + +// Read an Admin SCIM token by its ID. +func (a *adminSCIMTokens) Read(ctx context.Context, scimTokenID string) (*AdminSCIMToken, error) { + if !validStringID(&scimTokenID) { + return nil, ErrInvalidTokenID + } + u := fmt.Sprintf("%s/%s", AdminSCIMTokensPath, url.PathEscape(scimTokenID)) + req, err := a.client.NewRequest("GET", u, nil) + if err != nil { + return nil, err + } + scimToken := &AdminSCIMToken{} + err = req.Do(ctx, scimToken) + if err != nil { + return nil, err + } + return scimToken, nil +} + +// Delete an Admin SCIM token. +func (a *adminSCIMTokens) Delete(ctx context.Context, scimTokenID string) error { + if !validStringID(&scimTokenID) { + return ErrInvalidTokenID + } + u := fmt.Sprintf(AuthenticationTokensPath, url.PathEscape(scimTokenID)) + req, err := a.client.NewRequest("DELETE", u, nil) + if err != nil { + return err + } + return req.Do(ctx, nil) +} diff --git a/admin_setting_scim_token_integration_test.go b/admin_setting_scim_token_integration_test.go new file mode 100644 index 000000000..10d29dde2 --- /dev/null +++ b/admin_setting_scim_token_integration_test.go @@ -0,0 +1,343 @@ +// Copyright IBM Corp. 2018, 2026 +// SPDX-License-Identifier: MPL-2.0 + +package tfe + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestAdminSCIMTokens_Create(t *testing.T) { + skipUnlessEnterprise(t) + client := testClient(t) + ctx := context.Background() + + enableSCIM(ctx, t, client, true) + defer enableSCIM(ctx, t, client, false) + + scimTokenClient := client.Admin.Settings.SCIM.Tokens + + t.Run("create token", func(t *testing.T) { + testCases := []struct { + name string + description string + raiseError bool + }{ + {"with valid description", "Test Description", false}, + {"with empty description", "", true}, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + scimToken, err := scimTokenClient.Create(ctx, tc.description) + + if tc.raiseError { + require.Error(t, err) + return + } + + t.Cleanup(func() { + err := scimTokenClient.Delete(ctx, scimToken.ID) + if err != nil && err != ErrResourceNotFound { + t.Logf("failed to cleanup SCIM token %q: %v", scimToken.ID, err) + } + }) + require.NoError(t, err) + require.NotNil(t, scimToken) + assert.NotEmpty(t, scimToken) + assert.NotEmpty(t, scimToken.ID) + assert.NotEmpty(t, scimToken.Token) + assert.NotEmpty(t, scimToken.Description) + + assert.Equal(t, tc.description, scimToken.Description) + assert.WithinDuration(t, time.Now(), scimToken.CreatedAt, 10*time.Second) + assert.WithinDuration(t, time.Now().Add(365*24*time.Hour), scimToken.ExpiredAt, 10*time.Second) + }) + } + }) +} + +func TestAdminSCIMTokens_CreateWithOptions(t *testing.T) { + skipUnlessEnterprise(t) + client := testClient(t) + ctx := context.Background() + + enableSCIM(ctx, t, client, true) + defer enableSCIM(ctx, t, client, false) + + scimTokenClient := client.Admin.Settings.SCIM.Tokens + + t.Run("create token", func(t *testing.T) { + testCases := []struct { + name string + options AdminSCIMTokenCreateOptions + raiseError bool + }{ + {"with no options - should fail", AdminSCIMTokenCreateOptions{}, true}, + { + "with nil description - should fail`", + AdminSCIMTokenCreateOptions{ + Description: nil, + }, + true, + }, + { + "with empty description - should fail`", + AdminSCIMTokenCreateOptions{ + Description: String(""), + }, + true, + }, + { + "with description", + AdminSCIMTokenCreateOptions{ + Description: String("Test Description"), + }, + false, + }, + { + "with only expiration - should fail", + AdminSCIMTokenCreateOptions{ + ExpiredAt: Ptr(time.Now().Add(30 * 24 * time.Hour)), + }, + true, + }, + { + "with description and expiration", + AdminSCIMTokenCreateOptions{ + Description: String("Test Description"), + ExpiredAt: Ptr(time.Now().Add(60 * 24 * time.Hour)), + }, + false, + }, + { + "with expiration in 20 days - should fail", + AdminSCIMTokenCreateOptions{ + ExpiredAt: Ptr(time.Now().Add(20 * 24 * time.Hour)), + }, + true, + }, + { + "with expiration in 400 days - should fail", + AdminSCIMTokenCreateOptions{ + ExpiredAt: Ptr(time.Now().Add(400 * 24 * time.Hour)), + }, + true, + }, + { + "with expiration in 29 days", + AdminSCIMTokenCreateOptions{ + Description: String("Test Description"), + ExpiredAt: Ptr(time.Now().Add(29*24*time.Hour + 10*time.Second)), // adding 10 sec to account for any delays in test execution + }, + false, + }, + { + "with expiration in 365 days", + AdminSCIMTokenCreateOptions{ + Description: String("Test Description"), + ExpiredAt: Ptr(time.Now().Add(365 * 24 * time.Hour)), + }, + false, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + var scimToken *AdminSCIMToken + var err error + + scimToken, err = scimTokenClient.CreateWithOptions(ctx, tc.options) + + if tc.raiseError { + require.Error(t, err) + return + } + require.NoError(t, err) + require.NotNil(t, scimToken) + assert.NotEmpty(t, scimToken) + assert.NotEmpty(t, scimToken.ID) + + t.Cleanup(func() { + err := scimTokenClient.Delete(ctx, scimToken.ID) + if err != nil && err != ErrResourceNotFound { + t.Logf("failed to cleanup SCIM token %q: %v", scimToken.ID, err) + } + }) + + if tc.options.ExpiredAt != nil { + assert.WithinDuration(t, *tc.options.ExpiredAt, scimToken.ExpiredAt, 10*time.Second) + } else { + expectedExpiredAt := scimToken.CreatedAt.Add(365 * 24 * time.Hour) + assert.WithinDuration(t, expectedExpiredAt, scimToken.ExpiredAt, 10*time.Second) + } + }) + } + }) +} + +func TestAdminSCIMTokens_List(t *testing.T) { + skipUnlessEnterprise(t) + client := testClient(t) + ctx := context.Background() + + enableSCIM(ctx, t, client, true) + defer enableSCIM(ctx, t, client, false) + + scimTokenClient := client.Admin.Settings.SCIM.Tokens + + t.Run("list tokens", func(t *testing.T) { + // create tokens to ensure there is data to list + var scimTokens []*AdminSCIMToken + for i := 0; i < 3; i++ { + scimToken, err := scimTokenClient.Create(ctx, fmt.Sprintf("foo token %d", i)) + require.NoError(t, err) + tokenID := scimToken.ID + t.Cleanup(func() { + err := scimTokenClient.Delete(ctx, tokenID) + if err != nil && err != ErrResourceNotFound { + t.Logf("failed to cleanup SCIM token %q: %v", tokenID, err) + } + }) + scimTokens = append(scimTokens, scimToken) + } + + tokenList, err := scimTokenClient.List(ctx) + require.NoError(t, err) + require.NotNil(t, tokenList) + assert.NotEmpty(t, tokenList.Items) + + var expectedIDs []string + var actualIDs []string + for _, listedToken := range tokenList.Items { + actualIDs = append(actualIDs, listedToken.ID) + } + + for _, token := range scimTokens { + expectedIDs = append(expectedIDs, token.ID) + assert.Contains(t, actualIDs, token.ID) + } + + assert.Subset(t, actualIDs, expectedIDs) + }) +} + +func TestAdminSCIMTokens_Read(t *testing.T) { + skipUnlessEnterprise(t) + client := testClient(t) + ctx := context.Background() + + enableSCIM(ctx, t, client, true) + defer enableSCIM(ctx, t, client, false) + + scimTokenClient := client.Admin.Settings.SCIM.Tokens + + t.Run("read token", func(t *testing.T) { + // create a token to ensure there is data to read + scimToken, err := scimTokenClient.CreateWithOptions(ctx, AdminSCIMTokenCreateOptions{ + Description: String("Test Desc"), + ExpiredAt: Ptr(time.Now().Add(60 * 24 * time.Hour)), + }) + require.NoError(t, err) + require.NotNil(t, scimToken) + + t.Cleanup(func() { + err := scimTokenClient.Delete(ctx, scimToken.ID) + if err != nil && err != ErrResourceNotFound { + t.Logf("failed to cleanup SCIM token %q: %v", scimToken.ID, err) + } + }) + + testCases := []struct { + name string + tokenID string + raiseError bool + }{ + {"with valid token ID", scimToken.ID, false}, + {"with invalid token ID", "invalid id", true}, + {"with empty token ID", "", true}, + {"with non-existent token ID", "this-does-not-exist", true}, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + token, err := scimTokenClient.Read(ctx, tc.tokenID) + if tc.raiseError { + require.Error(t, err) + return + } + require.NoError(t, err) + require.NotNil(t, token) + assert.Equal(t, tc.tokenID, token.ID) + + // Verify specific field properties for the valid token + if !tc.raiseError { + assert.Equal(t, scimToken.Description, token.Description) + assert.WithinDuration(t, scimToken.ExpiredAt, token.ExpiredAt, time.Second) + assert.NotEmpty(t, scimToken.Token) + assert.Empty(t, token.Token) + } + }) + } + }) +} + +func TestAdminSCIMTokens_Delete(t *testing.T) { + skipUnlessEnterprise(t) + client := testClient(t) + ctx := context.Background() + + enableSCIM(ctx, t, client, true) + defer enableSCIM(ctx, t, client, false) + + scimTokenClient := client.Admin.Settings.SCIM.Tokens + + t.Run("delete token", func(t *testing.T) { + // create a token to ensure there is data to delete + scimToken, err := scimTokenClient.Create(ctx, "foo token") + require.NoError(t, err) + require.NotNil(t, scimToken) + t.Cleanup(func() { + err := scimTokenClient.Delete(ctx, scimToken.ID) + if err != nil && err != ErrResourceNotFound { + t.Logf("failed to cleanup SCIM token %q: %v", scimToken.ID, err) + } + }) + + testCases := []struct { + name string + tokenID string + raiseError bool + }{ + {"with valid token ID", scimToken.ID, false}, + {"with invalid token ID", "invalid id", true}, + {"with empty token ID", "", true}, + {"with non-existent token ID", "this-does-not-exist", true}, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + err = scimTokenClient.Delete(ctx, tc.tokenID) + if tc.raiseError { + require.Error(t, err) + if tc.tokenID == "this-does-not-exist" { + assert.ErrorIs(t, err, ErrResourceNotFound) + } else { + assert.ErrorIs(t, err, ErrInvalidTokenID) + } + return + } + require.NoError(t, err) + + // verify deletion + _, err = scimTokenClient.Read(ctx, tc.tokenID) + require.Error(t, err) + }) + } + }) +} diff --git a/const.go b/const.go index f424dba45..063a0ed4b 100644 --- a/const.go +++ b/const.go @@ -4,5 +4,9 @@ package tfe const ( + // AuthenticationTokensPath is the API path for authentication tokens. AuthenticationTokensPath = "authentication-tokens/%s" + + // AdminSCIMTokensPath is the API path for admin SCIM tokens. + AdminSCIMTokensPath = "admin/scim-tokens" ) diff --git a/errors.go b/errors.go index 7e9c8a0f1..7700c06ce 100644 --- a/errors.go +++ b/errors.go @@ -456,4 +456,6 @@ var ( ErrRequiredKMSOptionsKeyLocation = errors.New("kms-options.key-location is required for HYOK configuration with GCP OIDC") ErrRequiredKMSOptionsKeyRingID = errors.New("kms-options.key-ring-id is required for HYOK configuration with GCP OIDC") + + ErrSCIMTokenDescription = errors.New("SCIM token description can't be blank") ) diff --git a/generate_mocks.sh b/generate_mocks.sh index aa74492a2..cf955874b 100755 --- a/generate_mocks.sh +++ b/generate_mocks.sh @@ -15,6 +15,7 @@ mockgen -source=admin_setting_general.go -destination=mocks/admin_setting_genera mockgen -source=admin_setting_oidc.go -destination=mocks/admin_setting_oidc_mocks.go -package=mocks mockgen -source=admin_setting_saml.go -destination=mocks/admin_setting_saml_mocks.go -package=mocks mockgen -source=admin_setting_scim.go -destination=mocks/admin_setting_scim_mocks.go -package=mocks +mockgen -source=admin_setting_scim_token.go -destination=mocks/admin_setting_scim_token_mocks.go -package=mocks mockgen -source=admin_setting_smtp.go -destination=mocks/admin_setting_smtp_mocks.go -package=mocks mockgen -source=admin_setting_twilio.go -destination=mocks/admin_setting_twilio_mocks.go -package=mocks mockgen -source=admin_terraform_version.go -destination=mocks/admin_terraform_version_mocks.go -package=mocks diff --git a/helper_test.go b/helper_test.go index 16d0c4954..4e36481d6 100644 --- a/helper_test.go +++ b/helper_test.go @@ -3452,6 +3452,30 @@ func enableSAML(ctx context.Context, t *testing.T, client *Client, enable bool) require.NoError(t, err) } +func enableSCIM(ctx context.Context, t *testing.T, client *Client, enable bool) { + t.Helper() + + if enable { + enableSAML(ctx, t, client, true) + + err := setSAMLProviderType(ctx, t, client, true) + require.NoError(t, err, "error setting SAML provider type") + + _, err = client.Admin.Settings.SCIM.Update(ctx, AdminSCIMSettingUpdateOptions{ + Enabled: Bool(true), + }) + require.NoError(t, err, "error enabling SCIM") + } else { + err := client.Admin.Settings.SCIM.Delete(ctx) + require.NoError(t, err, "error disabling SCIM") + + err = setSAMLProviderType(ctx, t, client, false) + require.NoError(t, err, "error clearing SAML provider type") + + enableSAML(ctx, t, client, false) + } +} + func setSAMLProviderType(ctx context.Context, t *testing.T, client *Client, setProvider bool) error { t.Helper() var provider SAMLProviderType diff --git a/mocks/admin_setting_scim_token_mocks.go b/mocks/admin_setting_scim_token_mocks.go new file mode 100644 index 000000000..ad2a7df7c --- /dev/null +++ b/mocks/admin_setting_scim_token_mocks.go @@ -0,0 +1,115 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: admin_setting_scim_token.go +// +// Generated by this command: +// +// mockgen -source=admin_setting_scim_token.go -destination=mocks/admin_setting_scim_token_mocks.go -package=mocks +// + +// Package mocks is a generated GoMock package. +package mocks + +import ( + context "context" + reflect "reflect" + + tfe "github.com/hashicorp/go-tfe" + gomock "go.uber.org/mock/gomock" +) + +// MockAdminSCIMTokens is a mock of AdminSCIMTokens interface. +type MockAdminSCIMTokens struct { + ctrl *gomock.Controller + recorder *MockAdminSCIMTokensMockRecorder +} + +// MockAdminSCIMTokensMockRecorder is the mock recorder for MockAdminSCIMTokens. +type MockAdminSCIMTokensMockRecorder struct { + mock *MockAdminSCIMTokens +} + +// NewMockAdminSCIMTokens creates a new mock instance. +func NewMockAdminSCIMTokens(ctrl *gomock.Controller) *MockAdminSCIMTokens { + mock := &MockAdminSCIMTokens{ctrl: ctrl} + mock.recorder = &MockAdminSCIMTokensMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockAdminSCIMTokens) EXPECT() *MockAdminSCIMTokensMockRecorder { + return m.recorder +} + +// Create mocks base method. +func (m *MockAdminSCIMTokens) Create(ctx context.Context, description string) (*tfe.AdminSCIMToken, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Create", ctx, description) + ret0, _ := ret[0].(*tfe.AdminSCIMToken) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Create indicates an expected call of Create. +func (mr *MockAdminSCIMTokensMockRecorder) Create(ctx, description any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockAdminSCIMTokens)(nil).Create), ctx, description) +} + +// CreateWithOptions mocks base method. +func (m *MockAdminSCIMTokens) CreateWithOptions(ctx context.Context, options tfe.AdminSCIMTokenCreateOptions) (*tfe.AdminSCIMToken, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateWithOptions", ctx, options) + ret0, _ := ret[0].(*tfe.AdminSCIMToken) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CreateWithOptions indicates an expected call of CreateWithOptions. +func (mr *MockAdminSCIMTokensMockRecorder) CreateWithOptions(ctx, options any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateWithOptions", reflect.TypeOf((*MockAdminSCIMTokens)(nil).CreateWithOptions), ctx, options) +} + +// Delete mocks base method. +func (m *MockAdminSCIMTokens) Delete(ctx context.Context, scimTokenID string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", ctx, scimTokenID) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockAdminSCIMTokensMockRecorder) Delete(ctx, scimTokenID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockAdminSCIMTokens)(nil).Delete), ctx, scimTokenID) +} + +// List mocks base method. +func (m *MockAdminSCIMTokens) List(ctx context.Context) (*tfe.AdminSCIMTokenList, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "List", ctx) + ret0, _ := ret[0].(*tfe.AdminSCIMTokenList) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// List indicates an expected call of List. +func (mr *MockAdminSCIMTokensMockRecorder) List(ctx any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockAdminSCIMTokens)(nil).List), ctx) +} + +// Read mocks base method. +func (m *MockAdminSCIMTokens) Read(ctx context.Context, scimTokenID string) (*tfe.AdminSCIMToken, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Read", ctx, scimTokenID) + ret0, _ := ret[0].(*tfe.AdminSCIMToken) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Read indicates an expected call of Read. +func (mr *MockAdminSCIMTokensMockRecorder) Read(ctx, scimTokenID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Read", reflect.TypeOf((*MockAdminSCIMTokens)(nil).Read), ctx, scimTokenID) +} diff --git a/type_helpers.go b/type_helpers.go index ccf2be05c..616ca5f50 100644 --- a/type_helpers.go +++ b/type_helpers.go @@ -153,3 +153,8 @@ func NullableTime(v time.Time) jsonapi.NullableAttr[time.Time] { func NullTime() jsonapi.NullableAttr[time.Time] { return jsonapi.NewNullNullableAttr[time.Time]() } + +// Ptr returns a pointer to the given value of any type. +func Ptr[T any](v T) *T { + return &v +}