diff --git a/cmd/harbor/root/artifact/delete.go b/cmd/harbor/root/artifact/delete.go index 215233528..a0c36f404 100644 --- a/cmd/harbor/root/artifact/delete.go +++ b/cmd/harbor/root/artifact/delete.go @@ -42,7 +42,10 @@ func DeleteArtifactCommand() *cobra.Command { log.Errorf("failed to get project name: %v", utils.ParseHarborErrorMsg(err)) } repoName = prompt.GetRepoNameFromUser(projectName) - reference = prompt.GetReferenceFromUser(repoName, projectName) + reference, err = prompt.GetReferenceFromUser(repoName, projectName) + if err != nil { + return fmt.Errorf("failed to list artifacts: %v", err) + } } err = api.DeleteArtifact(projectName, repoName, reference) if err != nil { diff --git a/cmd/harbor/root/artifact/label/add.go b/cmd/harbor/root/artifact/label/add.go index 5b457da0b..6b023bd27 100644 --- a/cmd/harbor/root/artifact/label/add.go +++ b/cmd/harbor/root/artifact/label/add.go @@ -60,7 +60,10 @@ Examples: return fmt.Errorf("failed to get project name: %v", utils.ParseHarborErrorMsg(err)) } repoName = prompt.GetRepoNameFromUser(projectName) - reference = prompt.GetReferenceFromUser(repoName, projectName) + reference, err = prompt.GetReferenceFromUser(repoName, projectName) + if err != nil { + return fmt.Errorf("failed to list artifacts: %v", err) + } } if len(args) == 2 { diff --git a/cmd/harbor/root/artifact/label/delete.go b/cmd/harbor/root/artifact/label/delete.go index 0cd56cee7..4709ff228 100644 --- a/cmd/harbor/root/artifact/label/delete.go +++ b/cmd/harbor/root/artifact/label/delete.go @@ -61,7 +61,10 @@ Examples: return fmt.Errorf("failed to get project name: %v", utils.ParseHarborErrorMsg(err)) } repoName = prompt.GetRepoNameFromUser(projectName) - reference = prompt.GetReferenceFromUser(repoName, projectName) + reference, err = prompt.GetReferenceFromUser(repoName, projectName) + if err != nil { + return fmt.Errorf("failed to list artifacts: %v", err) + } } if len(args) == 2 { diff --git a/cmd/harbor/root/artifact/label/list.go b/cmd/harbor/root/artifact/label/list.go index 6f3279dd4..13feb8c5e 100644 --- a/cmd/harbor/root/artifact/label/list.go +++ b/cmd/harbor/root/artifact/label/list.go @@ -63,7 +63,10 @@ Supports output formatting such as JSON or YAML using the --output (-o) flag.`, return fmt.Errorf("failed to get project name: %v", utils.ParseHarborErrorMsg(err)) } repoName = prompt.GetRepoNameFromUser(projectName) - reference = prompt.GetReferenceFromUser(repoName, projectName) + reference, err = prompt.GetReferenceFromUser(repoName, projectName) + if err != nil { + return fmt.Errorf("failed to list artifacts: %v", err) + } } if reference == "" { diff --git a/cmd/harbor/root/artifact/scan/scan.go b/cmd/harbor/root/artifact/scan/scan.go index 949fa200a..dfefd5d04 100644 --- a/cmd/harbor/root/artifact/scan/scan.go +++ b/cmd/harbor/root/artifact/scan/scan.go @@ -45,7 +45,10 @@ func parseArgs(args []string) (string, string, string, error) { return "", "", "", err } repoName := prompt.GetRepoNameFromUser(projectName) - reference := prompt.GetReferenceFromUser(repoName, projectName) + reference, err := prompt.GetReferenceFromUser(repoName, projectName) + if err != nil { + return "", "", "", err + } return projectName, repoName, reference, nil } diff --git a/cmd/harbor/root/artifact/tags/create.go b/cmd/harbor/root/artifact/tags/create.go index 9ebeb312e..e2b7bdd46 100644 --- a/cmd/harbor/root/artifact/tags/create.go +++ b/cmd/harbor/root/artifact/tags/create.go @@ -47,7 +47,10 @@ func CreateTagsCmd() *cobra.Command { } repoName = prompt.GetRepoNameFromUser(projectName) - reference = prompt.GetReferenceFromUser(repoName, projectName) + reference, err = prompt.GetReferenceFromUser(repoName, projectName) + if err != nil { + return fmt.Errorf("failed to list artifacts: %v", err) + } create.CreateTagView(&tagName) } err = api.CreateTag(projectName, repoName, reference, tagName) diff --git a/cmd/harbor/root/artifact/tags/delete.go b/cmd/harbor/root/artifact/tags/delete.go index 8d6090af2..692a1ff16 100644 --- a/cmd/harbor/root/artifact/tags/delete.go +++ b/cmd/harbor/root/artifact/tags/delete.go @@ -45,8 +45,14 @@ func DeleteTagsCmd() *cobra.Command { } repoName = prompt.GetRepoNameFromUser(projectName) - reference = prompt.GetReferenceFromUser(repoName, projectName) - tagName = prompt.GetTagFromUser(repoName, projectName, reference) + reference, err = prompt.GetReferenceFromUser(repoName, projectName) + if err != nil { + return fmt.Errorf("failed to list artifacts: %v", err) + } + tagName, err = prompt.GetTagFromUser(repoName, projectName, reference) + if err != nil { + return fmt.Errorf("failed to list tags: %v", err) + } } err = api.DeleteTag(projectName, repoName, reference, tagName) diff --git a/cmd/harbor/root/artifact/tags/list.go b/cmd/harbor/root/artifact/tags/list.go index 9d0574605..e4527c68b 100644 --- a/cmd/harbor/root/artifact/tags/list.go +++ b/cmd/harbor/root/artifact/tags/list.go @@ -51,7 +51,10 @@ func ListTagsCmd() *cobra.Command { if repoName == "" { return fmt.Errorf("invalid repository name provided") } - reference = prompt.GetReferenceFromUser(repoName, projectName) + reference, err = prompt.GetReferenceFromUser(repoName, projectName) + if err != nil { + return fmt.Errorf("failed to list artifacts: %v", err) + } } tags, err = api.ListTags(projectName, repoName, reference) diff --git a/cmd/harbor/root/artifact/view.go b/cmd/harbor/root/artifact/view.go index 0b5a4065d..0a062b54d 100644 --- a/cmd/harbor/root/artifact/view.go +++ b/cmd/harbor/root/artifact/view.go @@ -47,7 +47,11 @@ func ViewArtifactCommmand() *cobra.Command { return } repoName = prompt.GetRepoNameFromUser(projectName) - reference = prompt.GetReferenceFromUser(repoName, projectName) + reference, err = prompt.GetReferenceFromUser(repoName, projectName) + if err != nil { + log.Errorf("failed to list artifacts: %v", err) + return + } } if reference == "" { diff --git a/cmd/harbor/root/instance/delete.go b/cmd/harbor/root/instance/delete.go index 87ec63598..b47b3821b 100644 --- a/cmd/harbor/root/instance/delete.go +++ b/cmd/harbor/root/instance/delete.go @@ -43,7 +43,10 @@ If no argument is provided, you will be prompted to select an instance from a li } else if len(args) > 0 { instanceName = args[0] } else { - instanceName = prompt.GetInstanceFromUser() + instanceName, err = prompt.GetInstanceFromUser() + if err != nil { + return fmt.Errorf("failed to list instances: %v", err) + } } err = api.DeleteInstance(instanceName) if err != nil { diff --git a/cmd/harbor/root/project/member/delete.go b/cmd/harbor/root/project/member/delete.go index 0967ed589..e16f4d343 100644 --- a/cmd/harbor/root/project/member/delete.go +++ b/cmd/harbor/root/project/member/delete.go @@ -72,7 +72,10 @@ func DeleteMemberCommand() *cobra.Command { return nil } else if !delAllFlag { log.Println("Please provide a username or use --all flag to delete all members") - memID = prompt.GetMemberIDFromUser(project, username) + memID, err = prompt.GetMemberIDFromUser(project, username) + if err != nil { + return fmt.Errorf("failed to list members: %v", err) + } if memID == 0 { fmt.Println("No members found in project") return nil diff --git a/cmd/harbor/root/project/member/update.go b/cmd/harbor/root/project/member/update.go index 82f982327..8f87f2305 100644 --- a/cmd/harbor/root/project/member/update.go +++ b/cmd/harbor/root/project/member/update.go @@ -54,8 +54,10 @@ func UpdateMemberCommand() *cobra.Command { } if memberName == "" { - opts.ID = prompt.GetMemberIDFromUser(opts.ProjectNameOrID, memberName) - + opts.ID, err = prompt.GetMemberIDFromUser(opts.ProjectNameOrID, memberName) + if err != nil { + return fmt.Errorf("failed to list members: %v", err) + } if opts.ID == 0 { return fmt.Errorf("No members found in project") } diff --git a/cmd/harbor/root/quota/update.go b/cmd/harbor/root/quota/update.go index a3ef87cee..29d8d849f 100644 --- a/cmd/harbor/root/quota/update.go +++ b/cmd/harbor/root/quota/update.go @@ -95,7 +95,6 @@ func UpdateQuotaCommand() *cobra.Command { } func GetQuotaFromUser(args []string, opts api.ListQuotaFlags) (*models.Quota, error) { - var err error var quota *models.Quota if len(args) > 0 { @@ -133,7 +132,10 @@ func GetQuotaFromUser(args []string, opts api.ListQuotaFlags) (*models.Quota, er return nil, err } } else { - quotaID := prompt.GetQuotaIDFromUser() + quotaID, err := prompt.GetQuotaIDFromUser() + if err != nil { + return nil, fmt.Errorf("failed to list quotas: %v", err) + } if quotaID == 0 { err := fmt.Errorf("failed to get quotaID from user") return nil, err diff --git a/cmd/harbor/root/registry/delete.go b/cmd/harbor/root/registry/delete.go index 597846e5d..0a9b310ed 100644 --- a/cmd/harbor/root/registry/delete.go +++ b/cmd/harbor/root/registry/delete.go @@ -43,8 +43,11 @@ func DeleteRegistryCommand() *cobra.Command { }(registryID) } } else { - registryId := prompt.GetRegistryNameFromUser() - err := api.DeleteRegistry(registryId) + registryId, err := prompt.GetRegistryNameFromUser() + if err != nil { + return fmt.Errorf("failed to get registry: %v", err) + } + err = api.DeleteRegistry(registryId) if err != nil { return fmt.Errorf("failed to delete registry: %v", err) } diff --git a/cmd/harbor/root/registry/update.go b/cmd/harbor/root/registry/update.go index ac755625c..4e55da313 100644 --- a/cmd/harbor/root/registry/update.go +++ b/cmd/harbor/root/registry/update.go @@ -43,7 +43,10 @@ func UpdateRegistryCommand() *cobra.Command { return fmt.Errorf("failed to get registry id: %v", err) } } else { - registryId = prompt.GetRegistryNameFromUser() + registryId, err = prompt.GetRegistryNameFromUser() + if err != nil { + return fmt.Errorf("failed to get registry: %v", err) + } } existingRegistry, err := api.GetRegistryResponse(registryId) diff --git a/cmd/harbor/root/registry/view.go b/cmd/harbor/root/registry/view.go index 59d82ab2e..d3783432b 100644 --- a/cmd/harbor/root/registry/view.go +++ b/cmd/harbor/root/registry/view.go @@ -42,7 +42,10 @@ func ViewRegistryCommand() *cobra.Command { return fmt.Errorf("failed to get registry name by id: %v", err) } } else { - registryId = prompt.GetRegistryNameFromUser() + registryId, err = prompt.GetRegistryNameFromUser() + if err != nil { + return fmt.Errorf("failed to get registry: %v", err) + } } registry, err = api.ViewRegistry(registryId) diff --git a/cmd/harbor/root/replication/policies/create.go b/cmd/harbor/root/replication/policies/create.go index b72dce17e..ecf2ea78b 100644 --- a/cmd/harbor/root/replication/policies/create.go +++ b/cmd/harbor/root/replication/policies/create.go @@ -57,7 +57,10 @@ func CreateCommand() *cobra.Command { } else { opts = &create.CreateView{} create.CreateRPolicyView(opts, false) - registryID = prompt.GetRegistryNameFromUser() + registryID, err = prompt.GetRegistryNameFromUser() + if err != nil { + return fmt.Errorf("failed to get registry: %v", err) + } } registry, err := api.GetRegistryResponse(registryID) diff --git a/cmd/harbor/root/scanner/delete.go b/cmd/harbor/root/scanner/delete.go index 1f397f22a..c943723b3 100644 --- a/cmd/harbor/root/scanner/delete.go +++ b/cmd/harbor/root/scanner/delete.go @@ -51,7 +51,10 @@ Examples: } registrationID = scanner.UUID } else { - registrationID = prompt.GetScannerIdFromUser() + registrationID, err = prompt.GetScannerIdFromUser() + if err != nil { + return fmt.Errorf("failed to list scanners: %v", err) + } } err = api.DeleteScanner(registrationID) diff --git a/cmd/harbor/root/scanner/metadata.go b/cmd/harbor/root/scanner/metadata.go index a7bf2a625..c551ec3a1 100644 --- a/cmd/harbor/root/scanner/metadata.go +++ b/cmd/harbor/root/scanner/metadata.go @@ -48,6 +48,7 @@ Flags: Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { var registrationID string + var err error if len(args) > 0 { scanner, err := api.GetScannerByName(args[0]) if err != nil { @@ -55,7 +56,10 @@ Flags: } registrationID = scanner.UUID } else { - registrationID = prompt.GetScannerIdFromUser() + registrationID, err = prompt.GetScannerIdFromUser() + if err != nil { + return fmt.Errorf("failed to list scanners: %v", err) + } } meta, err := api.GetScannerMetadata(registrationID) diff --git a/cmd/harbor/root/scanner/set_default.go b/cmd/harbor/root/scanner/set_default.go index 57c1890ba..84f5a7d7f 100644 --- a/cmd/harbor/root/scanner/set_default.go +++ b/cmd/harbor/root/scanner/set_default.go @@ -41,7 +41,10 @@ func SetDefaultCommand() *cobra.Command { } registrationID = scanner.UUID } else { - registrationID = prompt.GetScannerIdFromUser() + registrationID, err = prompt.GetScannerIdFromUser() + if err != nil { + return fmt.Errorf("failed to list scanners: %v", err) + } } err = api.SetDefaultScanner(registrationID) if err != nil { diff --git a/cmd/harbor/root/scanner/update.go b/cmd/harbor/root/scanner/update.go index a79d250dd..f061970f8 100644 --- a/cmd/harbor/root/scanner/update.go +++ b/cmd/harbor/root/scanner/update.go @@ -53,6 +53,7 @@ Only the fields passed through flags will be updated; other fields will retain t Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { var registrationID string + var err error if len(args) > 0 { scanner, err := api.GetScannerByName(args[0]) if err != nil { @@ -60,7 +61,10 @@ Only the fields passed through flags will be updated; other fields will retain t } registrationID = scanner.UUID } else { - registrationID = prompt.GetScannerIdFromUser() + registrationID, err = prompt.GetScannerIdFromUser() + if err != nil { + return fmt.Errorf("failed to list scanners: %v", err) + } } resp, err := api.GetScanner(registrationID) diff --git a/cmd/harbor/root/scanner/view.go b/cmd/harbor/root/scanner/view.go index 5dfe664f1..31410b5dd 100644 --- a/cmd/harbor/root/scanner/view.go +++ b/cmd/harbor/root/scanner/view.go @@ -56,7 +56,10 @@ Examples: } scanner = &resp } else { - id := prompt.GetScannerIdFromUser() + id, err := prompt.GetScannerIdFromUser() + if err != nil { + return fmt.Errorf("failed to list scanners: %v", err) + } resp, err := api.GetScanner(id) if err != nil { return fmt.Errorf("failed to get scanner by ID %q: %v", id, err) diff --git a/cmd/harbor/root/tag/immutable/delete.go b/cmd/harbor/root/tag/immutable/delete.go index 608301bc0..ecfd503e3 100644 --- a/cmd/harbor/root/tag/immutable/delete.go +++ b/cmd/harbor/root/tag/immutable/delete.go @@ -33,13 +33,19 @@ func DeleteImmutableCommand() *cobra.Command { var immutableId int64 if len(args) > 0 { projectName = args[0] - immutableId = prompt.GetImmutableTagRule(args[0]) + immutableId, err = prompt.GetImmutableTagRule(args[0]) + if err != nil { + return fmt.Errorf("failed to list immutable tag rules: %v", err) + } } else { projectName, err = prompt.GetProjectNameFromUser() if err != nil { return fmt.Errorf("failed to get project name: %v", utils.ParseHarborErrorMsg(err)) } - immutableId = prompt.GetImmutableTagRule(projectName) + immutableId, err = prompt.GetImmutableTagRule(projectName) + if err != nil { + return fmt.Errorf("failed to list immutable tag rules: %v", err) + } } err = api.DeleteImmutable(projectName, immutableId) if err != nil { diff --git a/pkg/prompt/prompt.go b/pkg/prompt/prompt.go index 2ed2e2890..ffac491e2 100644 --- a/pkg/prompt/prompt.go +++ b/pkg/prompt/prompt.go @@ -45,14 +45,35 @@ import ( log "github.com/sirupsen/logrus" ) -func GetRegistryNameFromUser() int64 { - registryId := make(chan int64) +var ( + listRegistriesFunc = api.ListRegistries + listArtifactFunc = api.ListArtifact + listImmutableFunc = api.ListImmutable + listTagsFunc = api.ListTags + listScannersFunc = api.ListScanners + listInstanceFunc = api.ListInstance + listMembersForPromptFunc = api.ListMembers + listQuotaFunc = api.ListQuota +) + +func GetRegistryNameFromUser() (int64, error) { + type result struct { + id int64 + err error + } + resultChan := make(chan result) go func() { - response, _ := api.ListRegistries() - rview.RegistryList(response.Payload, registryId) + response, err := listRegistriesFunc() + if err != nil { + resultChan <- result{0, err} + return + } + idChan := make(chan int64) + rview.RegistryList(response.Payload, idChan) + resultChan <- result{<-idChan, nil} }() - - return <-registryId + res := <-resultChan + return res.id, res.err } func GetProjectIDFromUser() (int64, error) { @@ -154,13 +175,24 @@ func GetRepoNameFromUser(projectName string) string { } // complete the function -func GetReferenceFromUser(repositoryName string, projectName string) string { - reference := make(chan string) +func GetReferenceFromUser(repositoryName string, projectName string) (string, error) { + type result struct { + ref string + err error + } + resultChan := make(chan result) go func() { - response, _ := api.ListArtifact(projectName, repositoryName) - aview.ListArtifacts(response.Payload, reference) + response, err := listArtifactFunc(projectName, repositoryName) + if err != nil { + resultChan <- result{"", err} + return + } + refChan := make(chan string) + aview.ListArtifacts(response.Payload, refChan) + resultChan <- result{<-refChan, nil} }() - return <-reference + res := <-resultChan + return res.ref, res.err } func GetUserIdFromUser() (int64, error) { @@ -177,33 +209,64 @@ func GetUserIdFromUser() (int64, error) { return id, nil } -func GetImmutableTagRule(projectName string) int64 { - immutableid := make(chan int64) +func GetImmutableTagRule(projectName string) (int64, error) { + type result struct { + id int64 + err error + } + resultChan := make(chan result) go func() { - response, _ := api.ListImmutable(projectName) - immview.ImmutableList(response.Payload, immutableid) + response, err := listImmutableFunc(projectName) + if err != nil { + resultChan <- result{0, err} + return + } + idChan := make(chan int64) + immview.ImmutableList(response.Payload, idChan) + resultChan <- result{<-idChan, nil} }() - return <-immutableid + res := <-resultChan + return res.id, res.err } -func GetTagFromUser(repoName, projectName, reference string) string { - tag := make(chan string) +func GetTagFromUser(repoName, projectName, reference string) (string, error) { + type result struct { + tag string + err error + } + resultChan := make(chan result) go func() { - response, _ := api.ListTags(projectName, repoName, reference) - tview.ListTags(response.Payload, tag) + response, err := listTagsFunc(projectName, repoName, reference) + if err != nil { + resultChan <- result{"", err} + return + } + tagChan := make(chan string) + tview.ListTags(response.Payload, tagChan) + resultChan <- result{<-tagChan, nil} }() - return <-tag + res := <-resultChan + return res.tag, res.err } -func GetScannerIdFromUser() string { - scannerId := make(chan string) - +func GetScannerIdFromUser() (string, error) { + type result struct { + id string + err error + } + resultChan := make(chan result) go func() { - response, _ := api.ListScanners() - sview.ScannerList(response.Payload, scannerId) + response, err := listScannersFunc() + if err != nil { + resultChan <- result{"", err} + return + } + idChan := make(chan string) + sview.ScannerList(response.Payload, idChan) + resultChan <- result{<-idChan, nil} }() - - return <-scannerId + res := <-resultChan + return res.id, res.err } func GetWebhookFromUser(projectName string) (models.WebhookPolicy, error) { @@ -266,29 +329,44 @@ func GetLabelIdFromUser(opts api.ListFlags) (int64, error) { return res.id, res.err } -func GetInstanceFromUser() string { - instanceName := make(chan string) - +func GetInstanceFromUser() (string, error) { + type result struct { + name string + err error + } + resultChan := make(chan result) go func() { - response, _ := api.ListInstance() - instview.InstanceList(response.Payload, instanceName) + response, err := listInstanceFunc() + if err != nil { + resultChan <- result{"", err} + return + } + nameChan := make(chan string) + instview.InstanceList(response.Payload, nameChan) + resultChan <- result{<-nameChan, nil} }() - - return <-instanceName + res := <-resultChan + return res.name, res.err } -func GetQuotaIDFromUser() int64 { - QuotaID := make(chan int64) - +func GetQuotaIDFromUser() (int64, error) { + type result struct { + id int64 + err error + } + resultChan := make(chan result) go func() { - response, err := api.ListQuota(*&api.ListQuotaFlags{}) + response, err := listQuotaFunc(*&api.ListQuotaFlags{}) if err != nil { - log.Errorf("failed to list quota: %v", err) + resultChan <- result{0, err} + return } - qview.QuotaList(response.Payload, QuotaID) + idChan := make(chan int64) + qview.QuotaList(response.Payload, idChan) + resultChan <- result{<-idChan, nil} }() - - return <-QuotaID + res := <-resultChan + return res.id, res.err } func GetActiveContextFromUser() (string, error) { @@ -405,22 +483,28 @@ func GetReplicationTaskIDFromUser(execID int64) int64 { } // Get GetMemberIDFromUser choosing from list of members -func GetMemberIDFromUser(projectName, memberName string) int64 { - memberId := make(chan int64) - length := make(chan int) +func GetMemberIDFromUser(projectName, memberName string) (int64, error) { + type result struct { + id int64 + err error + } + resultChan := make(chan result) go func() { - response, _ := api.ListMembers(projectName, memberName, true) - length <- len(response.Payload) - mview.MemberList(response.Payload, memberId) + response, err := listMembersForPromptFunc(projectName, memberName, true) + if err != nil { + resultChan <- result{0, err} + return + } + if len(response.Payload) == 0 { + resultChan <- result{0, nil} + return + } + idChan := make(chan int64) + mview.MemberList(response.Payload, idChan) + resultChan <- result{<-idChan, nil} }() - - // if no members found, return 0 - l := <-length - if l == 0 { - return 0 - } - - return <-memberId + res := <-resultChan + return res.id, res.err } // Get Member Role ID selection from user diff --git a/pkg/prompt/prompt_test.go b/pkg/prompt/prompt_test.go new file mode 100644 index 000000000..b32e317a4 --- /dev/null +++ b/pkg/prompt/prompt_test.go @@ -0,0 +1,155 @@ +// Copyright Project Harbor Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package prompt + +import ( + "errors" + "testing" + + "github.com/goharbor/go-client/pkg/sdk/v2.0/client/artifact" + "github.com/goharbor/go-client/pkg/sdk/v2.0/client/immutable" + "github.com/goharbor/go-client/pkg/sdk/v2.0/client/member" + "github.com/goharbor/go-client/pkg/sdk/v2.0/client/preheat" + "github.com/goharbor/go-client/pkg/sdk/v2.0/client/quota" + "github.com/goharbor/go-client/pkg/sdk/v2.0/client/registry" + "github.com/goharbor/go-client/pkg/sdk/v2.0/client/scanner" + "github.com/goharbor/go-client/pkg/sdk/v2.0/models" + "github.com/goharbor/harbor-cli/pkg/api" + "github.com/stretchr/testify/assert" +) + +func TestGetRegistryNameFromUser_APIFailure(t *testing.T) { + original := listRegistriesFunc + defer func() { listRegistriesFunc = original }() + + listRegistriesFunc = func(opts ...api.ListFlags) (*registry.ListRegistriesOK, error) { + return nil, errors.New("connection refused") + } + + id, err := GetRegistryNameFromUser() + assert.Error(t, err) + assert.Contains(t, err.Error(), "connection refused") + assert.Equal(t, int64(0), id) +} + +func TestGetReferenceFromUser_APIFailure(t *testing.T) { + original := listArtifactFunc + defer func() { listArtifactFunc = original }() + + listArtifactFunc = func(projectName, repoName string, opts ...api.ListFlags) (artifact.ListArtifactsOK, error) { + return artifact.ListArtifactsOK{}, errors.New("server error") + } + + ref, err := GetReferenceFromUser("repo", "project") + assert.Error(t, err) + assert.Contains(t, err.Error(), "server error") + assert.Empty(t, ref) +} + +func TestGetImmutableTagRule_APIFailure(t *testing.T) { + original := listImmutableFunc + defer func() { listImmutableFunc = original }() + + listImmutableFunc = func(projectName string) (immutable.ListImmuRulesOK, error) { + return immutable.ListImmuRulesOK{}, errors.New("not found") + } + + id, err := GetImmutableTagRule("test-project") + assert.Error(t, err) + assert.Contains(t, err.Error(), "not found") + assert.Equal(t, int64(0), id) +} + +func TestGetTagFromUser_APIFailure(t *testing.T) { + original := listTagsFunc + defer func() { listTagsFunc = original }() + + listTagsFunc = func(projectName, repoName, reference string) (*artifact.ListTagsOK, error) { + return nil, errors.New("timeout") + } + + tagName, err := GetTagFromUser("repo", "project", "ref") + assert.Error(t, err) + assert.Contains(t, err.Error(), "timeout") + assert.Empty(t, tagName) +} + +func TestGetScannerIdFromUser_APIFailure(t *testing.T) { + original := listScannersFunc + defer func() { listScannersFunc = original }() + + listScannersFunc = func() (scanner.ListScannersOK, error) { + return scanner.ListScannersOK{}, errors.New("unauthorized") + } + + id, err := GetScannerIdFromUser() + assert.Error(t, err) + assert.Contains(t, err.Error(), "unauthorized") + assert.Empty(t, id) +} + +func TestGetInstanceFromUser_APIFailure(t *testing.T) { + original := listInstanceFunc + defer func() { listInstanceFunc = original }() + + listInstanceFunc = func(opts ...api.ListFlags) (*preheat.ListInstancesOK, error) { + return nil, errors.New("connection refused") + } + + name, err := GetInstanceFromUser() + assert.Error(t, err) + assert.Contains(t, err.Error(), "connection refused") + assert.Empty(t, name) +} + +func TestGetMemberIDFromUser_APIFailure(t *testing.T) { + original := listMembersForPromptFunc + defer func() { listMembersForPromptFunc = original }() + + listMembersForPromptFunc = func(projectNameOrID, memberName string, isName bool) (*member.ListProjectMembersOK, error) { + return nil, errors.New("server down") + } + + id, err := GetMemberIDFromUser("project", "member") + assert.Error(t, err) + assert.Contains(t, err.Error(), "server down") + assert.Equal(t, int64(0), id) +} + +func TestGetMemberIDFromUser_EmptyList(t *testing.T) { + original := listMembersForPromptFunc + defer func() { listMembersForPromptFunc = original }() + + listMembersForPromptFunc = func(projectNameOrID, memberName string, isName bool) (*member.ListProjectMembersOK, error) { + return &member.ListProjectMembersOK{Payload: []*models.ProjectMemberEntity{}}, nil + } + + id, err := GetMemberIDFromUser("project", "member") + assert.NoError(t, err) + assert.Equal(t, int64(0), id) +} + +func TestGetQuotaIDFromUser_APIFailure(t *testing.T) { + original := listQuotaFunc + defer func() { listQuotaFunc = original }() + + listQuotaFunc = func(opts api.ListQuotaFlags) (*quota.ListQuotasOK, error) { + return nil, errors.New("quota service unavailable") + } + + id, err := GetQuotaIDFromUser() + assert.Error(t, err) + assert.Contains(t, err.Error(), "quota service unavailable") + assert.Equal(t, int64(0), id) +}