diff --git a/cli/cmd/mocks.go b/cli/cmd/mocks.go index 0aab4e6b..ea7610c5 100644 --- a/cli/cmd/mocks.go +++ b/cli/cmd/mocks.go @@ -9,13 +9,13 @@ import ( "io" ) -// NewMockUpdater creates a new instance of MockUpdater. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// NewMockOMSUpdater creates a new instance of MockOMSUpdater. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // The first argument is typically a *testing.T value. -func NewMockUpdater(t interface { +func NewMockOMSUpdater(t interface { mock.TestingT Cleanup(func()) -}) *MockUpdater { - mock := &MockUpdater{} +}) *MockOMSUpdater { + mock := &MockOMSUpdater{} mock.Mock.Test(t) t.Cleanup(func() { mock.AssertExpectations(t) }) @@ -23,21 +23,21 @@ func NewMockUpdater(t interface { return mock } -// MockUpdater is an autogenerated mock type for the Updater type -type MockUpdater struct { +// MockOMSUpdater is an autogenerated mock type for the OMSUpdater type +type MockOMSUpdater struct { mock.Mock } -type MockUpdater_Expecter struct { +type MockOMSUpdater_Expecter struct { mock *mock.Mock } -func (_m *MockUpdater) EXPECT() *MockUpdater_Expecter { - return &MockUpdater_Expecter{mock: &_m.Mock} +func (_m *MockOMSUpdater) EXPECT() *MockOMSUpdater_Expecter { + return &MockOMSUpdater_Expecter{mock: &_m.Mock} } -// Apply provides a mock function for the type MockUpdater -func (_mock *MockUpdater) Apply(update io.Reader) error { +// Apply provides a mock function for the type MockOMSUpdater +func (_mock *MockOMSUpdater) Apply(update io.Reader) error { ret := _mock.Called(update) if len(ret) == 0 { @@ -53,30 +53,30 @@ func (_mock *MockUpdater) Apply(update io.Reader) error { return r0 } -// MockUpdater_Apply_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Apply' -type MockUpdater_Apply_Call struct { +// MockOMSUpdater_Apply_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Apply' +type MockOMSUpdater_Apply_Call struct { *mock.Call } // Apply is a helper method to define mock.On call // - update -func (_e *MockUpdater_Expecter) Apply(update interface{}) *MockUpdater_Apply_Call { - return &MockUpdater_Apply_Call{Call: _e.mock.On("Apply", update)} +func (_e *MockOMSUpdater_Expecter) Apply(update interface{}) *MockOMSUpdater_Apply_Call { + return &MockOMSUpdater_Apply_Call{Call: _e.mock.On("Apply", update)} } -func (_c *MockUpdater_Apply_Call) Run(run func(update io.Reader)) *MockUpdater_Apply_Call { +func (_c *MockOMSUpdater_Apply_Call) Run(run func(update io.Reader)) *MockOMSUpdater_Apply_Call { _c.Call.Run(func(args mock.Arguments) { run(args[0].(io.Reader)) }) return _c } -func (_c *MockUpdater_Apply_Call) Return(err error) *MockUpdater_Apply_Call { +func (_c *MockOMSUpdater_Apply_Call) Return(err error) *MockOMSUpdater_Apply_Call { _c.Call.Return(err) return _c } -func (_c *MockUpdater_Apply_Call) RunAndReturn(run func(update io.Reader) error) *MockUpdater_Apply_Call { +func (_c *MockOMSUpdater_Apply_Call) RunAndReturn(run func(update io.Reader) error) *MockOMSUpdater_Apply_Call { _c.Call.Return(run) return _c } diff --git a/cli/cmd/root.go b/cli/cmd/root.go index 302a8885..7159a5e6 100644 --- a/cli/cmd/root.go +++ b/cli/cmd/root.go @@ -27,7 +27,7 @@ func GetRootCmd() *cobra.Command { like downloading new versions.`), } AddVersionCmd(rootCmd) - AddUpdateCmd(rootCmd) + AddUpdateCmd(rootCmd, opts) AddListCmd(rootCmd, opts) AddDownloadCmd(rootCmd, opts) AddBetaCmd(rootCmd, &opts) diff --git a/cli/cmd/update.go b/cli/cmd/update.go index 4310b712..7ab6500b 100644 --- a/cli/cmd/update.go +++ b/cli/cmd/update.go @@ -5,113 +5,34 @@ package cmd import ( "fmt" - "io" - "log" - "strings" - "golang.org/x/sync/errgroup" - - "github.com/blang/semver" - "github.com/inconshreveable/go-update" "github.com/spf13/cobra" - - "github.com/codesphere-cloud/oms/internal/portal" - "github.com/codesphere-cloud/oms/internal/util" - "github.com/codesphere-cloud/oms/internal/version" ) type UpdateCmd struct { - cmd *cobra.Command - Version version.Version - Updater Updater + cmd *cobra.Command } func (c *UpdateCmd) RunE(_ *cobra.Command, args []string) error { + fmt.Printf("running %s", c.cmd.Use) - p := portal.NewPortalClient() - - return c.SelfUpdate(p) + return nil } -func AddUpdateCmd(rootCmd *cobra.Command) { - update := UpdateCmd{ +func AddUpdateCmd(rootCmd *cobra.Command, opts GlobalOptions) { + updateCmd := UpdateCmd{ cmd: &cobra.Command{ Use: "update", - Short: "Update Codesphere OMS", - Long: `Updates the OMS to the latest release from OMS Portal.`, + Short: "Update OMS related resources", + Long: `Updates resources, e.g. OMS or OMS API keys.`, }, - Version: &version.Build{}, - Updater: &SelfUpdater{}, - } - rootCmd.AddCommand(update.cmd) - update.cmd.RunE = update.RunE -} - -func (c *UpdateCmd) SelfUpdate(p portal.Portal) error { - currentVersion := semver.MustParse(c.Version.Version()) - - latest, err := p.GetBuild(portal.OmsProduct, "", "") - if err != nil { - return fmt.Errorf("failed to query OMS Portal for latest version: %w", err) - } - latestVersion := semver.MustParse(strings.TrimPrefix(latest.Version, "oms-v")) - - log.Printf("Current version: %v\n", currentVersion) - log.Printf("Latest version: %v\n", latestVersion) - - if latestVersion.Equals(currentVersion) { - log.Println("Current OMS CLI is already the latest version", c.Version.Version()) - return nil - } - - // Need a build with a single artifact to download it - download, err := latest.GetBuildForDownload(fmt.Sprintf("%s_%s.tar.gz", c.Version.Os(), c.Version.Arch())) - if err != nil { - return fmt.Errorf("failed to find OMS CLI in package: %w", err) } - // Use a pipe to unzip the file while downloading without storing on the filesystem - reader, writer := io.Pipe() - defer func() { _ = reader.Close() }() - - eg := errgroup.Group{} - eg.Go(func() error { - defer func() { _ = writer.Close() }() - err = p.DownloadBuildArtifact(portal.OmsProduct, download, writer) - if err != nil { - return fmt.Errorf("failed to download latest OMS package: %w", err) - } - return nil - }) - - cliReader, err := util.StreamFileFromGzip(reader, "oms-cli") - if err != nil { - return fmt.Errorf("failed to extract binary from archive: %w", err) - } - - err = c.Updater.Apply(cliReader) - if err != nil { - return fmt.Errorf("failed to apply update: %w", err) - } - - _, _ = io.Copy(io.Discard, reader) - - // Wait for download to finish and handle any error from the go routine - err = eg.Wait() - if err != nil { - return err - } - - log.Println("Update finished successfully.") - return nil -} - -type Updater interface { - Apply(update io.Reader) error -} + updateCmd.cmd.RunE = updateCmd.RunE -type SelfUpdater struct{} + AddDownloadPackageCmd(updateCmd.cmd, opts) + AddOmsUpdateCmd(updateCmd.cmd) + AddApiKeyUpdateCmd(updateCmd.cmd) -func (s *SelfUpdater) Apply(r io.Reader) error { - return update.Apply(r, update.Options{}) + rootCmd.AddCommand(updateCmd.cmd) } diff --git a/cli/cmd/update_api_key.go b/cli/cmd/update_api_key.go new file mode 100644 index 00000000..dc2be180 --- /dev/null +++ b/cli/cmd/update_api_key.go @@ -0,0 +1,63 @@ +// Copyright (c) Codesphere Inc. +// SPDX-License-Identifier: Apache-2.0 + +package cmd + +import ( + "fmt" + "time" + + "github.com/codesphere-cloud/oms/internal/portal" + "github.com/codesphere-cloud/oms/internal/util" + "github.com/spf13/cobra" +) + +type UpdateAPIKeyCmd struct { + Opts UpdateAPIKeyOpts +} + +type UpdateAPIKeyOpts struct { + GlobalOptions + APIKeyID string + ExpiresAtStr string +} + +func AddApiKeyUpdateCmd(parentCmd *cobra.Command) { + cmdState := &UpdateAPIKeyCmd{ + Opts: UpdateAPIKeyOpts{}, + } + + apiKeyCmd := &cobra.Command{ + Use: "api-key", + Short: "Update an API key's expiration date", + Long: `Updates the expiration date for a given API key using the --id and --valid-to flags.`, + Args: cobra.ExactArgs(0), + RunE: func(cmd *cobra.Command, args []string) error { + p := portal.NewPortalClient() + return cmdState.UpdateAPIKey(p) + }, + } + + apiKeyCmd.Flags().StringVarP(&cmdState.Opts.APIKeyID, "id", "i", "", "The ID of the API key to update") + apiKeyCmd.Flags().StringVarP(&cmdState.Opts.ExpiresAtStr, "valid-to", "v", "", "The new expiration date in RFC3339 format (e.g., \"2025-12-31T23:59:59Z\")") + + util.MarkFlagRequired(apiKeyCmd, "id") + util.MarkFlagRequired(apiKeyCmd, "valid-to") + + parentCmd.AddCommand(apiKeyCmd) +} + +func (c *UpdateAPIKeyCmd) UpdateAPIKey(p portal.Portal) error { + expiresAt, err := time.Parse(time.RFC3339, c.Opts.ExpiresAtStr) + + if err != nil { + return fmt.Errorf("invalid date format for : %w", err) + } + + if err := p.UpdateAPIKey(c.Opts.APIKeyID, expiresAt); err != nil { + return fmt.Errorf("failed to update API key: %w", err) + } + + fmt.Printf("Successfully updated API key '%s' with new expiration date %s.\n", c.Opts.APIKeyID, expiresAt.Format(time.RFC1123)) + return nil +} diff --git a/cli/cmd/update_api_key_test.go b/cli/cmd/update_api_key_test.go new file mode 100644 index 00000000..4df50449 --- /dev/null +++ b/cli/cmd/update_api_key_test.go @@ -0,0 +1,71 @@ +// Copyright (c) Codesphere Inc. +// SPDX-License-Identifier: Apache-2.0 + +package cmd_test + +import ( + "fmt" + "time" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "github.com/codesphere-cloud/oms/cli/cmd" + "github.com/codesphere-cloud/oms/internal/portal" +) + +var _ = Describe("UpdateAPIKey", func() { + + var ( + mockPortal *portal.MockPortal + c cmd.UpdateAPIKeyCmd + ) + + BeforeEach(func() { + mockPortal = portal.NewMockPortal(GinkgoT()) + c = cmd.UpdateAPIKeyCmd{} + }) + + Describe("Run", func() { + It("successfully updates the API key when given valid input", func() { + apiKeyID := "aaaaaaaaaaaaaaaaaaaaaa" + expiresAtStr := "2027-12-31T23:59:59Z" + expectedExpiresAt, err := time.Parse(time.RFC3339, expiresAtStr) + Expect(err).NotTo(HaveOccurred()) + + c.Opts.APIKeyID = apiKeyID + c.Opts.ExpiresAtStr = expiresAtStr + + mockPortal.EXPECT().UpdateAPIKey(apiKeyID, expectedExpiresAt).Return(nil) + + err = c.UpdateAPIKey(mockPortal) + Expect(err).NotTo(HaveOccurred()) + }) + + It("returns an error for an invalid api key id format", func() { + apiKeyID := "not-a-valid-id" + expiresAtStr := "2027-12-31T23:59:59Z" + expectedExpiresAt, err := time.Parse(time.RFC3339, expiresAtStr) + Expect(err).NotTo(HaveOccurred()) + + c.Opts.APIKeyID = apiKeyID + c.Opts.ExpiresAtStr = expiresAtStr + + mockPortal.EXPECT().UpdateAPIKey(apiKeyID, expectedExpiresAt).Return(fmt.Errorf("invalid api key id format")) + + err = c.UpdateAPIKey(mockPortal) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("invalid api key id format")) + }) + + It("returns an error for an invalid date format", func() { + c.Opts.APIKeyID = "valid id" + c.Opts.ExpiresAtStr = "2025/123/123" + + err := c.UpdateAPIKey(mockPortal) + + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("invalid date format")) + }) + }) +}) diff --git a/cli/cmd/update_oms.go b/cli/cmd/update_oms.go new file mode 100644 index 00000000..8d14b26a --- /dev/null +++ b/cli/cmd/update_oms.go @@ -0,0 +1,110 @@ +// Copyright (c) Codesphere Inc. +// SPDX-License-Identifier: Apache-2.0 + +package cmd + +import ( + "fmt" + "io" + "strings" + + "github.com/blang/semver" + "github.com/inconshreveable/go-update" + "github.com/spf13/cobra" + "golang.org/x/sync/errgroup" + + "github.com/codesphere-cloud/oms/internal/portal" + "github.com/codesphere-cloud/oms/internal/util" + "github.com/codesphere-cloud/oms/internal/version" +) + +type OMSUpdater interface { + Apply(update io.Reader) error +} + +type OMSSelfUpdater struct{} + +func (s *OMSSelfUpdater) Apply(r io.Reader) error { + return update.Apply(r, update.Options{}) +} + +type UpdateOmsCmd struct { + Version version.Version + Updater OMSUpdater +} + +func AddOmsUpdateCmd(parentCmd *cobra.Command) { + cmdState := &UpdateOmsCmd{ + Version: &version.Build{}, + Updater: &OMSSelfUpdater{}, + } + + omsCmd := &cobra.Command{ + Use: "oms", + Short: "Update the OMS CLI", + Long: `Updates the OMS CLI to the latest release from OMS Portal.`, + RunE: func(_ *cobra.Command, args []string) error { + p := portal.NewPortalClient() + return cmdState.SelfUpdate(p) + }, + } + parentCmd.AddCommand(omsCmd) +} + +func (c *UpdateOmsCmd) SelfUpdate(p portal.Portal) error { + currentVersion := semver.MustParse(c.Version.Version()) + + latest, err := p.GetBuild(portal.OmsProduct, "", "") + if err != nil { + return fmt.Errorf("failed to query OMS Portal for latest version: %w", err) + } + latestVersion := semver.MustParse(strings.TrimPrefix(latest.Version, "oms-v")) + + fmt.Printf("current version: %v\n", currentVersion) + fmt.Printf("latest version: %v\n", latestVersion) + if latestVersion.Equals(currentVersion) { + fmt.Println("Current OMS CLI is already the latest version", c.Version.Version()) + return nil + } + + // Need a build with a single artifact to download it + download, err := latest.GetBuildForDownload(fmt.Sprintf("%s_%s.tar.gz", c.Version.Os(), c.Version.Arch())) + if err != nil { + return fmt.Errorf("failed to find OMS CLI in package: %w", err) + } + + // Use a pipe to unzip the file while downloading without storing on the filesystem + reader, writer := io.Pipe() + defer func() { _ = reader.Close() }() + + eg := errgroup.Group{} + eg.Go(func() error { + defer func() { _ = writer.Close() }() + err = p.DownloadBuildArtifact(portal.OmsProduct, download, writer) + if err != nil { + return fmt.Errorf("failed to download latest OMS package: %w", err) + } + return nil + }) + + cliReader, err := util.StreamFileFromGzip(reader, "oms-cli") + if err != nil { + return fmt.Errorf("failed to extract binary from archive: %w", err) + } + + err = c.Updater.Apply(cliReader) + if err != nil { + return fmt.Errorf("failed to apply update: %w", err) + } + + _, _ = io.Copy(io.Discard, reader) + + // Wait for download to finish and handle any error from the go routine + err = eg.Wait() + if err != nil { + return err + } + + fmt.Println("Update finished successfully.") + return nil +} diff --git a/cli/cmd/update_test.go b/cli/cmd/update_oms_test.go similarity index 95% rename from cli/cmd/update_test.go rename to cli/cmd/update_oms_test.go index c2be6898..0a895b82 100644 --- a/cli/cmd/update_test.go +++ b/cli/cmd/update_oms_test.go @@ -30,16 +30,16 @@ var _ = Describe("Update", func() { var ( mockPortal *portal.MockPortal mockVersion *version.MockVersion - mockUpdater *cmd.MockUpdater + mockUpdater *cmd.MockOMSUpdater latestBuild portal.Build buildToDownload portal.Build - c cmd.UpdateCmd + c cmd.UpdateOmsCmd ) BeforeEach(func() { mockPortal = portal.NewMockPortal(GinkgoT()) mockVersion = version.NewMockVersion(GinkgoT()) - mockUpdater = cmd.NewMockUpdater(GinkgoT()) + mockUpdater = cmd.NewMockOMSUpdater(GinkgoT()) latestBuild = portal.Build{ Version: "0.0.42", @@ -55,7 +55,7 @@ var _ = Describe("Update", func() { {Filename: "fakeos_fakearch.tar.gz"}, }, } - c = cmd.UpdateCmd{ + c = cmd.UpdateOmsCmd{ Version: mockVersion, Updater: mockUpdater, } diff --git a/internal/portal/api_key.go b/internal/portal/api_key.go index 0c0648c1..20de7892 100644 --- a/internal/portal/api_key.go +++ b/internal/portal/api_key.go @@ -3,12 +3,12 @@ package portal import "time" type ApiKey struct { - KeyID string `json:"key_id"` + KeyID string `json:"keyId"` Owner string `json:"owner"` Organization string `json:"organization"` Role string `json:"role"` CreatedAt time.Time `json:"createdAt"` ExpiresAt time.Time `json:"expiresAt"` // Temp - ApiKey string `json:"api_key"` + ApiKey string `json:"apiKey"` } diff --git a/internal/portal/http.go b/internal/portal/http.go index f755cf48..8f1a383f 100644 --- a/internal/portal/http.go +++ b/internal/portal/http.go @@ -25,6 +25,7 @@ type Portal interface { DownloadBuildArtifact(product Product, build Build, file io.Writer) error RegisterAPIKey(owner string, organization string, role string, expiresAt time.Time) error RevokeAPIKey(key string) error + UpdateAPIKey(key string, expiresAt time.Time) error ListAPIKeys() ([]ApiKey, error) } @@ -237,7 +238,7 @@ func (c *PortalClient) RegisterAPIKey(owner string, organization string, role st func (c *PortalClient) RevokeAPIKey(keyId string) error { req := struct { - KeyID string `json:"key_id"` + KeyID string `json:"keyId"` }{ KeyID: keyId, } @@ -258,6 +259,30 @@ func (c *PortalClient) RevokeAPIKey(keyId string) error { return nil } +func (c *PortalClient) UpdateAPIKey(key string, expiresAt time.Time) error { + req := struct { + Key string `json:"keyId"` + ExpiresAt time.Time `json:"expiresAt"` + }{ + Key: key, + ExpiresAt: expiresAt, + } + + reqBody, err := json.Marshal(req) + if err != nil { + return fmt.Errorf("failed to generate request body: %w", err) + } + + resp, err := c.HttpRequest(http.MethodPost, "/key/update", reqBody) + if err != nil { + return fmt.Errorf("POST request to update API key failed: %w", err) + } + defer func() { _ = resp.Body.Close() }() + + fmt.Println("API key updated successfully") + return nil +} + func (c *PortalClient) ListAPIKeys() ([]ApiKey, error) { res, _, err := c.GetBody("/keys") if err != nil { diff --git a/internal/portal/mocks.go b/internal/portal/mocks.go index 4181514a..6b85a82b 100644 --- a/internal/portal/mocks.go +++ b/internal/portal/mocks.go @@ -5,11 +5,10 @@ package portal import ( + mock "github.com/stretchr/testify/mock" "io" "net/http" "time" - - mock "github.com/stretchr/testify/mock" ) // NewMockPortal creates a new instance of MockPortal. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. @@ -142,32 +141,6 @@ func (_c *MockPortal_GetBuild_Call) RunAndReturn(run func(product Product, versi return _c } -// ListBuilds provides a mock function for the type MockPortal -func (_mock *MockPortal) ListBuilds(product Product) (Builds, error) { - ret := _mock.Called(product) - - if len(ret) == 0 { - panic("no return value specified for ListBuilds") - } - - var r0 Builds - var r1 error - if returnFunc, ok := ret.Get(0).(func(Product) (Builds, error)); ok { - return returnFunc(product) - } - if returnFunc, ok := ret.Get(0).(func(Product) Builds); ok { - r0 = returnFunc(product) - } else { - r0 = ret.Get(0).(Builds) - } - if returnFunc, ok := ret.Get(1).(func(Product) error); ok { - r1 = returnFunc(product) - } else { - r1 = ret.Error(1) - } - return r0, r1 -} - // ListAPIKeys provides a mock function for the type MockPortal func (_mock *MockPortal) ListAPIKeys() ([]ApiKey, error) { ret := _mock.Called() @@ -184,7 +157,9 @@ func (_mock *MockPortal) ListAPIKeys() ([]ApiKey, error) { if returnFunc, ok := ret.Get(0).(func() []ApiKey); ok { r0 = returnFunc() } else { - r0 = ret.Get(0).([]ApiKey) + if ret.Get(0) != nil { + r0 = ret.Get(0).([]ApiKey) + } } if returnFunc, ok := ret.Get(1).(func() error); ok { r1 = returnFunc() @@ -211,8 +186,8 @@ func (_c *MockPortal_ListAPIKeys_Call) Run(run func()) *MockPortal_ListAPIKeys_C return _c } -func (_c *MockPortal_ListAPIKeys_Call) Return(keys []ApiKey, err error) *MockPortal_ListAPIKeys_Call { - _c.Call.Return(keys, err) +func (_c *MockPortal_ListAPIKeys_Call) Return(apiKeys []ApiKey, err error) *MockPortal_ListAPIKeys_Call { + _c.Call.Return(apiKeys, err) return _c } @@ -221,6 +196,32 @@ func (_c *MockPortal_ListAPIKeys_Call) RunAndReturn(run func() ([]ApiKey, error) return _c } +// ListBuilds provides a mock function for the type MockPortal +func (_mock *MockPortal) ListBuilds(product Product) (Builds, error) { + ret := _mock.Called(product) + + if len(ret) == 0 { + panic("no return value specified for ListBuilds") + } + + var r0 Builds + var r1 error + if returnFunc, ok := ret.Get(0).(func(Product) (Builds, error)); ok { + return returnFunc(product) + } + if returnFunc, ok := ret.Get(0).(func(Product) Builds); ok { + r0 = returnFunc(product) + } else { + r0 = ret.Get(0).(Builds) + } + if returnFunc, ok := ret.Get(1).(func(Product) error); ok { + r1 = returnFunc(product) + } else { + r1 = ret.Error(1) + } + return r0, r1 +} + // MockPortal_ListBuilds_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListBuilds' type MockPortal_ListBuilds_Call struct { *mock.Call @@ -342,6 +343,52 @@ func (_c *MockPortal_RevokeAPIKey_Call) RunAndReturn(run func(key string) error) return _c } +// UpdateAPIKey provides a mock function for the type MockPortal +func (_mock *MockPortal) UpdateAPIKey(key string, expiresAt time.Time) error { + ret := _mock.Called(key, expiresAt) + + if len(ret) == 0 { + panic("no return value specified for UpdateAPIKey") + } + + var r0 error + if returnFunc, ok := ret.Get(0).(func(string, time.Time) error); ok { + r0 = returnFunc(key, expiresAt) + } else { + r0 = ret.Error(0) + } + return r0 +} + +// MockPortal_UpdateAPIKey_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateAPIKey' +type MockPortal_UpdateAPIKey_Call struct { + *mock.Call +} + +// UpdateAPIKey is a helper method to define mock.On call +// - key +// - expiresAt +func (_e *MockPortal_Expecter) UpdateAPIKey(key interface{}, expiresAt interface{}) *MockPortal_UpdateAPIKey_Call { + return &MockPortal_UpdateAPIKey_Call{Call: _e.mock.On("UpdateAPIKey", key, expiresAt)} +} + +func (_c *MockPortal_UpdateAPIKey_Call) Run(run func(key string, expiresAt time.Time)) *MockPortal_UpdateAPIKey_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string), args[1].(time.Time)) + }) + return _c +} + +func (_c *MockPortal_UpdateAPIKey_Call) Return(err error) *MockPortal_UpdateAPIKey_Call { + _c.Call.Return(err) + return _c +} + +func (_c *MockPortal_UpdateAPIKey_Call) RunAndReturn(run func(key string, expiresAt time.Time) error) *MockPortal_UpdateAPIKey_Call { + _c.Call.Return(run) + return _c +} + // NewMockHttpClient creates a new instance of MockHttpClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // The first argument is typically a *testing.T value. func NewMockHttpClient(t interface { diff --git a/internal/util/mocks.go b/internal/util/mocks.go index 23487339..c9fcabf6 100644 --- a/internal/util/mocks.go +++ b/internal/util/mocks.go @@ -5,9 +5,10 @@ package util import ( + "os" + "github.com/jedib0t/go-pretty/v6/table" mock "github.com/stretchr/testify/mock" - "os" ) // NewMockFileIO creates a new instance of MockFileIO. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.