From e48400338c107b27a0780672fb3a8f68e22f8dbe Mon Sep 17 00:00:00 2001 From: JianMinTang Date: Sun, 3 Nov 2024 09:17:54 +0800 Subject: [PATCH 01/12] Support yaml output for 'registry list' Signed-off-by: JianMinTang --- cmd/harbor/root/registry/list.go | 6 +++++- pkg/utils/utils.go | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/cmd/harbor/root/registry/list.go b/cmd/harbor/root/registry/list.go index 21862779..f0e7a501 100644 --- a/cmd/harbor/root/registry/list.go +++ b/cmd/harbor/root/registry/list.go @@ -23,9 +23,13 @@ func ListRegistryCommand() *cobra.Command { log.Fatalf("failed to get projects list: %v", err) } FormatFlag := viper.GetString("output-format") - if FormatFlag != "" { + if FormatFlag == "json" { utils.PrintPayloadInJSONFormat(registry) return + } + if FormatFlag == "yaml" { + utils.PrintPayloadInYAMLFormat(registry) + return } list.ListRegistry(registry.Payload) }, diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index a64a67c7..313ac462 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -6,6 +6,7 @@ import ( "strings" log "github.com/sirupsen/logrus" + "gopkg.in/yaml.v3" ) // Returns Harbor v2 client for given clientConfig @@ -23,6 +24,20 @@ func PrintPayloadInJSONFormat(payload any) { fmt.Println(string(jsonStr)) } + +func PrintPayloadInYAMLFormat(payload any) { + if payload == nil { + return + } + + yamlStr, err := yaml.Marshal(payload) + if err != nil { + panic(err) + } + + fmt.Println(string(yamlStr)) +} + func ParseProjectRepo(projectRepo string) (string, string) { split := strings.Split(projectRepo, "/") if len(split) != 2 { From 60f6c227de3d403bc255ebd301857419e7526abf Mon Sep 17 00:00:00 2001 From: JianMinTang Date: Sun, 3 Nov 2024 15:38:13 +0800 Subject: [PATCH 02/12] Use gofmt to format all code Signed-off-by: JianMinTang --- cmd/harbor/root/registry/list.go | 2 +- dagger/main.go | 22 +++++++++++----------- pkg/utils/utils.go | 1 - 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/cmd/harbor/root/registry/list.go b/cmd/harbor/root/registry/list.go index f0e7a501..29008c4d 100644 --- a/cmd/harbor/root/registry/list.go +++ b/cmd/harbor/root/registry/list.go @@ -26,7 +26,7 @@ func ListRegistryCommand() *cobra.Command { if FormatFlag == "json" { utils.PrintPayloadInJSONFormat(registry) return - } + } if FormatFlag == "yaml" { utils.PrintPayloadInYAMLFormat(registry) return diff --git a/dagger/main.go b/dagger/main.go index a99871ca..1dff591c 100644 --- a/dagger/main.go +++ b/dagger/main.go @@ -16,9 +16,9 @@ const ( ) func New( -// Local or remote directory with source code, defaults to "./" -// +optional -// +defaultPath="./" + // Local or remote directory with source code, defaults to "./" + // +optional + // +defaultPath="./" source *dagger.Directory, ) *HarborCli { return &HarborCli{Source: source} @@ -122,8 +122,8 @@ func (m *HarborCli) lint(ctx context.Context) *dagger.Container { func (m *HarborCli) PublishImage( ctx context.Context, registry, registryUsername string, -// +optional -// +default=["latest"] + // +optional + // +default=["latest"] imageTags []string, registryPassword *dagger.Secret) []string { builders := m.build(ctx) @@ -254,11 +254,11 @@ func (m *HarborCli) PublishImageAndSign( registryUsername string, registryPassword *dagger.Secret, imageTags []string, -// +optional + // +optional githubToken *dagger.Secret, -// +optional + // +optional actionsIdTokenRequestToken *dagger.Secret, -// +optional + // +optional actionsIdTokenRequestUrl string, ) (string, error) { @@ -282,11 +282,11 @@ func (m *HarborCli) PublishImageAndSign( // Sign signs a container image using Cosign, works also with GitHub Actions func (m *HarborCli) Sign(ctx context.Context, -// +optional + // +optional githubToken *dagger.Secret, -// +optional + // +optional actionsIdTokenRequestUrl string, -// +optional + // +optional actionsIdTokenRequestToken *dagger.Secret, registryUsername string, registryPassword *dagger.Secret, diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index 313ac462..7de40796 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -24,7 +24,6 @@ func PrintPayloadInJSONFormat(payload any) { fmt.Println(string(jsonStr)) } - func PrintPayloadInYAMLFormat(payload any) { if payload == nil { return From 693dacc102fb2132466d1e754a2dfb6eb6eca0d2 Mon Sep 17 00:00:00 2001 From: JianMinTang Date: Wed, 6 Nov 2024 09:36:39 +0800 Subject: [PATCH 03/12] fix: Support YAML output for additional commands Signed-off-by: JianMinTang --- cmd/harbor/root/project/list.go | 11 +++++++++-- cmd/harbor/root/project/logs.go | 12 ++++++++++-- cmd/harbor/root/registry/list.go | 16 ++++++++++------ cmd/harbor/root/user/list.go | 14 +++++++++++--- 4 files changed, 40 insertions(+), 13 deletions(-) diff --git a/cmd/harbor/root/project/list.go b/cmd/harbor/root/project/list.go index e8a5594b..460e3a4e 100644 --- a/cmd/harbor/root/project/list.go +++ b/cmd/harbor/root/project/list.go @@ -23,10 +23,17 @@ func ListProjectCommand() *cobra.Command { } FormatFlag := viper.GetString("output-format") if FormatFlag != "" { - utils.PrintPayloadInJSONFormat(projects) + if FormatFlag == "json" { + utils.PrintPayloadInJSONFormat(projects) + return + } + if FormatFlag == "yaml" { + utils.PrintPayloadInYAMLFormat(projects) + return + } + log.Errorf("Unable to output in the specified '%s' format", FormatFlag) return } - list.ListProjects(projects.Payload) }, } diff --git a/cmd/harbor/root/project/logs.go b/cmd/harbor/root/project/logs.go index 6ee330db..fd945e6c 100644 --- a/cmd/harbor/root/project/logs.go +++ b/cmd/harbor/root/project/logs.go @@ -30,13 +30,21 @@ func LogsProjectCommmand() *cobra.Command { if err != nil { log.Fatalf("failed to get project logs: %v", err) } - auditLog.LogsProject(resp.Payload) FormatFlag := viper.GetString("output-format") if FormatFlag != "" { - utils.PrintPayloadInJSONFormat(resp) + if FormatFlag == "json" { + utils.PrintPayloadInJSONFormat(resp) + return + } + if FormatFlag == "yaml" { + utils.PrintPayloadInYAMLFormat(resp) + return + } + log.Errorf("Unable to output in the specified '%s' format", FormatFlag) return } + auditLog.LogsProject(resp.Payload) }, } diff --git a/cmd/harbor/root/registry/list.go b/cmd/harbor/root/registry/list.go index 29008c4d..c73dd457 100644 --- a/cmd/harbor/root/registry/list.go +++ b/cmd/harbor/root/registry/list.go @@ -23,12 +23,16 @@ func ListRegistryCommand() *cobra.Command { log.Fatalf("failed to get projects list: %v", err) } FormatFlag := viper.GetString("output-format") - if FormatFlag == "json" { - utils.PrintPayloadInJSONFormat(registry) - return - } - if FormatFlag == "yaml" { - utils.PrintPayloadInYAMLFormat(registry) + if FormatFlag != "" { + if FormatFlag == "json" { + utils.PrintPayloadInJSONFormat(registry) + return + } + if FormatFlag == "yaml" { + utils.PrintPayloadInYAMLFormat(registry) + return + } + log.Errorf("Unable to output in the specified '%s' format", FormatFlag) return } list.ListRegistry(registry.Payload) diff --git a/cmd/harbor/root/user/list.go b/cmd/harbor/root/user/list.go index b9f356e9..037c5e05 100644 --- a/cmd/harbor/root/user/list.go +++ b/cmd/harbor/root/user/list.go @@ -23,10 +23,18 @@ func UserListCmd() *cobra.Command { } FormatFlag := viper.GetString("output-format") if FormatFlag != "" { - utils.PrintPayloadInJSONFormat(response.Payload) - } else { - list.ListUsers(response.Payload) + if FormatFlag == "json" { + utils.PrintPayloadInJSONFormat(response.Payload) + return + } + if FormatFlag == "yaml" { + utils.PrintPayloadInYAMLFormat(response.Payload) + return + } + log.Errorf("Unable to output in the specified '%s' format", FormatFlag) + return } + list.ListUsers(response.Payload) }, } From eb2d1535c275108981ad306e9691b45df1f2ba3b Mon Sep 17 00:00:00 2001 From: JianMinTang Date: Thu, 7 Nov 2024 08:53:49 +0800 Subject: [PATCH 04/12] fix: Support YAML format on artiface and repo command Signed-off-by: JianMinTang --- cmd/harbor/root/artifact/list.go | 31 +++++++++++++++++++++++------- cmd/harbor/root/repository/list.go | 28 ++++++++++++++++++++++----- 2 files changed, 47 insertions(+), 12 deletions(-) diff --git a/cmd/harbor/root/artifact/list.go b/cmd/harbor/root/artifact/list.go index 22be9278..17bfc7b8 100644 --- a/cmd/harbor/root/artifact/list.go +++ b/cmd/harbor/root/artifact/list.go @@ -8,6 +8,7 @@ import ( artifactViews "github.com/goharbor/harbor-cli/pkg/views/artifact/list" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" + "github.com/spf13/viper" ) func ListArtifactCommand() *cobra.Command { @@ -17,21 +18,37 @@ func ListArtifactCommand() *cobra.Command { Args: cobra.MaximumNArgs(1), Run: func(cmd *cobra.Command, args []string) { var err error - var resp artifact.ListArtifactsOK + var artifacts artifact.ListArtifactsOK + var projectName, repoName string if len(args) > 0 { - projectName, repoName := utils.ParseProjectRepo(args[0]) - resp, err = api.ListArtifact(projectName, repoName) + projectName, repoName = utils.ParseProjectRepo(args[0]) } else { - projectName := prompt.GetProjectNameFromUser() - repoName := prompt.GetRepoNameFromUser(projectName) - resp, err = api.ListArtifact(projectName, repoName) + projectName = prompt.GetProjectNameFromUser() + repoName = prompt.GetRepoNameFromUser(projectName) } + artifacts, err = api.ListArtifact(projectName, repoName) + if err != nil { log.Errorf("failed to list artifacts: %v", err) } - artifactViews.ListArtifacts(resp.Payload) + + FormatFlag := viper.GetString("output-format") + if FormatFlag != "" { + if FormatFlag == "json" { + utils.PrintPayloadInJSONFormat(artifacts) + return + } + if FormatFlag == "yaml" { + utils.PrintPayloadInYAMLFormat(artifacts) + return + } + log.Errorf("Unable to output in the specified '%s' format", FormatFlag) + return + } + + artifactViews.ListArtifacts(artifacts.Payload) }, } diff --git a/cmd/harbor/root/repository/list.go b/cmd/harbor/root/repository/list.go index e9f1126c..47c4a39c 100644 --- a/cmd/harbor/root/repository/list.go +++ b/cmd/harbor/root/repository/list.go @@ -4,9 +4,11 @@ import ( "github.com/goharbor/go-client/pkg/sdk/v2.0/client/repository" "github.com/goharbor/harbor-cli/pkg/api" "github.com/goharbor/harbor-cli/pkg/prompt" + "github.com/goharbor/harbor-cli/pkg/utils" "github.com/goharbor/harbor-cli/pkg/views/repository/list" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" + "github.com/spf13/viper" ) func ListRepositoryCommand() *cobra.Command { @@ -16,20 +18,36 @@ func ListRepositoryCommand() *cobra.Command { Args: cobra.MaximumNArgs(1), Run: func(cmd *cobra.Command, args []string) { var err error - var resp repository.ListRepositoriesOK + var repos repository.ListRepositoriesOK + var projectName string if len(args) > 0 { - resp, err = api.ListRepository(args[0]) + projectName = args[0] } else { - projectName := prompt.GetProjectNameFromUser() - resp, err = api.ListRepository(projectName) + projectName = prompt.GetProjectNameFromUser() } + repos, err = api.ListRepository(projectName) + if err != nil { log.Errorf("failed to list repositories: %v", err) } + + FormatFlag := viper.GetString("output-format") + if FormatFlag != "" { + if FormatFlag == "json" { + utils.PrintPayloadInJSONFormat(repos) + return + } + if FormatFlag == "yaml" { + utils.PrintPayloadInYAMLFormat(repos) + return + } + log.Errorf("Unable to output in the specified '%s' format", FormatFlag) + return + } - list.ListRepositories(resp.Payload) + list.ListRepositories(repos.Payload) }, } From f50e4715ec6c6f56d3f843dfb70299193d85bb61 Mon Sep 17 00:00:00 2001 From: JianMinTang Date: Thu, 7 Nov 2024 09:29:33 +0800 Subject: [PATCH 05/12] fix: Implement a generic function to format output Signed-off-by: JianMinTang --- cmd/harbor/root/artifact/list.go | 16 +++++----------- cmd/harbor/root/project/list.go | 15 +++++---------- cmd/harbor/root/project/logs.go | 15 +++++---------- cmd/harbor/root/registry/list.go | 15 +++++---------- cmd/harbor/root/repository/list.go | 19 ++++++------------- cmd/harbor/root/user/list.go | 15 +++++---------- pkg/utils/helper.go | 12 ++++++++++++ 7 files changed, 43 insertions(+), 64 deletions(-) diff --git a/cmd/harbor/root/artifact/list.go b/cmd/harbor/root/artifact/list.go index 17bfc7b8..243a1a9c 100644 --- a/cmd/harbor/root/artifact/list.go +++ b/cmd/harbor/root/artifact/list.go @@ -36,19 +36,13 @@ func ListArtifactCommand() *cobra.Command { FormatFlag := viper.GetString("output-format") if FormatFlag != "" { - if FormatFlag == "json" { - utils.PrintPayloadInJSONFormat(artifacts) - return + err = utils.PrintFormat(artifacts, FormatFlag) + if err != nil { + log.Error(err) } - if FormatFlag == "yaml" { - utils.PrintPayloadInYAMLFormat(artifacts) - return - } - log.Errorf("Unable to output in the specified '%s' format", FormatFlag) - return + } else { + artifactViews.ListArtifacts(artifacts.Payload) } - - artifactViews.ListArtifacts(artifacts.Payload) }, } diff --git a/cmd/harbor/root/project/list.go b/cmd/harbor/root/project/list.go index 460e3a4e..51a1a3fc 100644 --- a/cmd/harbor/root/project/list.go +++ b/cmd/harbor/root/project/list.go @@ -23,18 +23,13 @@ func ListProjectCommand() *cobra.Command { } FormatFlag := viper.GetString("output-format") if FormatFlag != "" { - if FormatFlag == "json" { - utils.PrintPayloadInJSONFormat(projects) - return + err = utils.PrintFormat(projects, FormatFlag) + if err != nil { + log.Error(err) } - if FormatFlag == "yaml" { - utils.PrintPayloadInYAMLFormat(projects) - return - } - log.Errorf("Unable to output in the specified '%s' format", FormatFlag) - return + } else { + list.ListProjects(projects.Payload) } - list.ListProjects(projects.Payload) }, } diff --git a/cmd/harbor/root/project/logs.go b/cmd/harbor/root/project/logs.go index fd945e6c..8e4cac54 100644 --- a/cmd/harbor/root/project/logs.go +++ b/cmd/harbor/root/project/logs.go @@ -33,18 +33,13 @@ func LogsProjectCommmand() *cobra.Command { FormatFlag := viper.GetString("output-format") if FormatFlag != "" { - if FormatFlag == "json" { - utils.PrintPayloadInJSONFormat(resp) - return + err = utils.PrintFormat(resp, FormatFlag) + if err != nil { + log.Error(err) } - if FormatFlag == "yaml" { - utils.PrintPayloadInYAMLFormat(resp) - return - } - log.Errorf("Unable to output in the specified '%s' format", FormatFlag) - return + } else { + auditLog.LogsProject(resp.Payload) } - auditLog.LogsProject(resp.Payload) }, } diff --git a/cmd/harbor/root/registry/list.go b/cmd/harbor/root/registry/list.go index c73dd457..78598511 100644 --- a/cmd/harbor/root/registry/list.go +++ b/cmd/harbor/root/registry/list.go @@ -24,18 +24,13 @@ func ListRegistryCommand() *cobra.Command { } FormatFlag := viper.GetString("output-format") if FormatFlag != "" { - if FormatFlag == "json" { - utils.PrintPayloadInJSONFormat(registry) - return + err = utils.PrintFormat(registry, FormatFlag) + if err != nil { + log.Error(err) } - if FormatFlag == "yaml" { - utils.PrintPayloadInYAMLFormat(registry) - return - } - log.Errorf("Unable to output in the specified '%s' format", FormatFlag) - return + } else { + list.ListRegistry(registry.Payload) } - list.ListRegistry(registry.Payload) }, } diff --git a/cmd/harbor/root/repository/list.go b/cmd/harbor/root/repository/list.go index 47c4a39c..d9c803f5 100644 --- a/cmd/harbor/root/repository/list.go +++ b/cmd/harbor/root/repository/list.go @@ -32,23 +32,16 @@ func ListRepositoryCommand() *cobra.Command { if err != nil { log.Errorf("failed to list repositories: %v", err) } - + FormatFlag := viper.GetString("output-format") if FormatFlag != "" { - if FormatFlag == "json" { - utils.PrintPayloadInJSONFormat(repos) - return - } - if FormatFlag == "yaml" { - utils.PrintPayloadInYAMLFormat(repos) - return + err = utils.PrintFormat(repos, FormatFlag) + if err != nil { + log.Error(err) } - log.Errorf("Unable to output in the specified '%s' format", FormatFlag) - return + } else { + list.ListRepositories(repos.Payload) } - - list.ListRepositories(repos.Payload) - }, } diff --git a/cmd/harbor/root/user/list.go b/cmd/harbor/root/user/list.go index 037c5e05..28731a30 100644 --- a/cmd/harbor/root/user/list.go +++ b/cmd/harbor/root/user/list.go @@ -23,18 +23,13 @@ func UserListCmd() *cobra.Command { } FormatFlag := viper.GetString("output-format") if FormatFlag != "" { - if FormatFlag == "json" { - utils.PrintPayloadInJSONFormat(response.Payload) - return + err = utils.PrintFormat(response, FormatFlag) + if err != nil { + log.Error(err) } - if FormatFlag == "yaml" { - utils.PrintPayloadInYAMLFormat(response.Payload) - return - } - log.Errorf("Unable to output in the specified '%s' format", FormatFlag) - return + } else { + list.ListUsers(response.Payload) } - list.ListUsers(response.Payload) }, } diff --git a/pkg/utils/helper.go b/pkg/utils/helper.go index 31f06c9b..d7dca0af 100644 --- a/pkg/utils/helper.go +++ b/pkg/utils/helper.go @@ -122,3 +122,15 @@ func ValidateRegistryName(rn string) bool { return re.MatchString(rn) } + +func PrintFormat[T any](resp T, format string) error { + if format == "json" { + PrintPayloadInJSONFormat(resp) + return nil + } + if format == "yaml" { + PrintPayloadInYAMLFormat(resp) + return nil + } + return errors.New(fmt.Sprintf("Unable to output in the specified '%s' format", format)) +} From 2e2a7bd92a78176a2f8b6e71b24d2f1c279d682c Mon Sep 17 00:00:00 2001 From: JianMinTang Date: Thu, 7 Nov 2024 09:46:20 +0800 Subject: [PATCH 06/12] chore: fix the problem about golangci-lint Signed-off-by: JianMinTang --- pkg/utils/helper.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/utils/helper.go b/pkg/utils/helper.go index d7dca0af..2c6b3e53 100644 --- a/pkg/utils/helper.go +++ b/pkg/utils/helper.go @@ -132,5 +132,5 @@ func PrintFormat[T any](resp T, format string) error { PrintPayloadInYAMLFormat(resp) return nil } - return errors.New(fmt.Sprintf("Unable to output in the specified '%s' format", format)) + return fmt.Errorf("unable to output in the specified '%s' format", format) } From 406f1d358e35a46e70facd8e453f2bde5522b9ad Mon Sep 17 00:00:00 2001 From: Prasanth B <89722848+bupd@users.noreply.github.com> Date: Thu, 14 Nov 2024 23:40:03 +0530 Subject: [PATCH 07/12] AutoGenerate credential name in login (#250) * generate credential name Signed-off-by: bupd * feat: add support for the password-stdin flag in login flow Signed-off-by: karanngi * fix deps - fixes dependencies Signed-off-by: bupd * return stdout for tests Signed-off-by: bupd * update workflow Signed-off-by: bupd --------- Signed-off-by: bupd Signed-off-by: karanngi Co-authored-by: karanngi Signed-off-by: JianMinTang --- .github/workflows/default.yaml | 4 ++-- cmd/harbor/root/login.go | 41 +++++++++++++++++----------------- dagger.json | 2 +- dagger/main.go | 2 +- go.mod | 1 + go.sum | 2 ++ pkg/utils/utils.go | 9 ++++++++ pkg/views/login/create.go | 17 +++++++++++--- 8 files changed, 51 insertions(+), 27 deletions(-) diff --git a/.github/workflows/default.yaml b/.github/workflows/default.yaml index 0e0a742c..59800436 100644 --- a/.github/workflows/default.yaml +++ b/.github/workflows/default.yaml @@ -49,14 +49,14 @@ jobs: with: version: ${{ steps.dagger_version.outputs.version }} verb: call - args: test + args: test export --path=./testResults - name: Build Binary uses: dagger/dagger-for-github@v6 with: version: ${{ steps.dagger_version.outputs.version }} verb: call - args: build-dev --platform linux/amd64 + args: build-dev --platform linux/amd64 export --path=./harbor-dev push-latest-images: if: github.event.pull_request == null && !startsWith(github.ref, 'refs/tags/v') diff --git a/cmd/harbor/root/login.go b/cmd/harbor/root/login.go index ec727c22..316ded87 100644 --- a/cmd/harbor/root/login.go +++ b/cmd/harbor/root/login.go @@ -3,13 +3,14 @@ package root import ( "context" "fmt" - "strings" + "os" "github.com/goharbor/go-client/pkg/harbor" "github.com/goharbor/go-client/pkg/sdk/v2.0/client/user" "github.com/goharbor/harbor-cli/pkg/utils" "github.com/goharbor/harbor-cli/pkg/views/login" "github.com/spf13/cobra" + "golang.org/x/term" ) var ( @@ -17,6 +18,7 @@ var ( Username string Password string Name string + passwordStdin bool ) // LoginCommand creates a new `harbor login` command @@ -31,6 +33,16 @@ func LoginCommand() *cobra.Command { serverAddress = args[0] } + if passwordStdin { + fmt.Print("Password: ") + passwordBytes, err := term.ReadPassword(int(os.Stdin.Fd())) + if err != nil { + return fmt.Errorf("failed to read password from stdin: %v", err) + } + fmt.Println() + Password = string(passwordBytes) + } + loginView := login.LoginView{ Server: serverAddress, Username: Username, @@ -38,10 +50,14 @@ func LoginCommand() *cobra.Command { Name: Name, } + // autogenerate name + if loginView.Name == "" && loginView.Server != "" && loginView.Username != "" { + loginView.Name = fmt.Sprintf("%s@%s", loginView.Username, utils.SanitizeServerAddress(loginView.Server)) + } + var err error - if loginView.Server != "" && loginView.Username != "" && loginView.Password != "" && - loginView.Name != "" { + if loginView.Server != "" && loginView.Username != "" && loginView.Password != "" { err = runLogin(loginView) } else { err = createLoginView(&loginView) @@ -58,24 +74,11 @@ func LoginCommand() *cobra.Command { flags.StringVarP(&Name, "name", "", "", "name for the set of credentials") flags.StringVarP(&Username, "username", "u", "", "Username") flags.StringVarP(&Password, "password", "p", "", "Password") + flags.BoolVar(&passwordStdin, "password-stdin", false, "Take the password from stdin") return cmd } -// generateCredentialName creates a default credential name based on server and username -func generateCredentialName(server, username string) string { - if strings.HasPrefix(server, "http://") { - server = strings.ReplaceAll(server, "http://", "") - } - if strings.HasPrefix(server, "https://") { - server = strings.ReplaceAll(server, "https://", "") - } - if username != "" { - return fmt.Sprintf("%s@%s", username, server) - } - return server -} - func createLoginView(loginView *login.LoginView) error { if loginView == nil { loginView = &login.LoginView{ @@ -86,6 +89,7 @@ func createLoginView(loginView *login.LoginView) error { } } login.CreateView(loginView) + return runLogin(*loginView) } @@ -104,9 +108,6 @@ func runLogin(opts login.LoginView) error { if err != nil { return fmt.Errorf("login failed, please check your credentials: %s", err) } - if opts.Name == "" { - opts.Name = generateCredentialName(opts.Server, opts.Username) - } cred := utils.Credential{ Name: opts.Name, diff --git a/dagger.json b/dagger.json index 87feeb60..fa623ae3 100644 --- a/dagger.json +++ b/dagger.json @@ -9,5 +9,5 @@ } ], "source": "dagger", - "engineVersion": "v0.13.6" + "engineVersion": "v0.14.0" } diff --git a/dagger/main.go b/dagger/main.go index 1dff591c..762f1344 100644 --- a/dagger/main.go +++ b/dagger/main.go @@ -234,7 +234,7 @@ func (m *HarborCli) Test(ctx context.Context) *dagger.Directory { WithEnvVariable("GOCACHE", "/go/build-cache"). WithMountedDirectory("/src", m.Source). WithWorkdir("/src"). - WithExec([]string{"go", "test", "-v", "./..."}). + WithExec([]string{"go", "test", "./..."}). Directory("/src") } diff --git a/go.mod b/go.mod index 9e37e8ce..14b1fa00 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/spf13/cobra v1.8.1 github.com/spf13/viper v1.19.0 github.com/stretchr/testify v1.9.0 + golang.org/x/term v0.6.0 ) require ( diff --git a/go.sum b/go.sum index a2802a44..a9cd7625 100644 --- a/go.sum +++ b/go.sum @@ -179,6 +179,8 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index 7de40796..5bff7837 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -3,6 +3,7 @@ package utils import ( "encoding/json" "fmt" + "regexp" "strings" log "github.com/sirupsen/logrus" @@ -52,3 +53,11 @@ func ParseProjectRepoReference(projectRepoReference string) (string, string, str } return split[0], split[1], split[2] } + +func SanitizeServerAddress(server string) string { + re := regexp.MustCompile(`^https?://`) + server = re.ReplaceAllString(server, "") + re = regexp.MustCompile(`[^a-zA-Z0-9]`) + server = re.ReplaceAllString(server, "-") + return server +} diff --git a/pkg/views/login/create.go b/pkg/views/login/create.go index b0b9a4e9..0838845d 100644 --- a/pkg/views/login/create.go +++ b/pkg/views/login/create.go @@ -2,6 +2,7 @@ package login import ( "errors" + "fmt" "net/url" "strings" @@ -19,10 +20,12 @@ type LoginView struct { func CreateView(loginView *LoginView) { theme := huh.ThemeCharm() + err := huh.NewForm( huh.NewGroup( huh.NewInput(). Title("Server"). + Description("Server address eg. demo.goharbor.io"). Value(&loginView.Server). Validate(func(str string) error { if strings.TrimSpace(str) == "" { @@ -62,17 +65,25 @@ func CreateView(loginView *LoginView) { huh.NewInput(). Title("Name of Credential"). Value(&loginView.Name). + Description("Name of credential to be stored in the harbor config file."). + PlaceholderFunc(func() string { + return fmt.Sprintf("%s@%s", loginView.Username, utils.SanitizeServerAddress(loginView.Server)) + }, &loginView). + SuggestionsFunc(func() []string { + return []string{ + fmt.Sprintf("%s@%s", loginView.Username, utils.SanitizeServerAddress(loginView.Server)), + } + }, &loginView). Validate(func(str string) error { if str == "" { - return errors.New("credential name cannot be empty") + loginView.Name = fmt.Sprintf("%s@%s", loginView.Username, utils.SanitizeServerAddress(loginView.Server)) + return nil } return nil }), ), ).WithTheme(theme).Run() - if err != nil { log.Fatal(err) } - } From bc40a4219c4cd5c86b25601a9152bb9b35984f93 Mon Sep 17 00:00:00 2001 From: Vadim Bauer Date: Thu, 14 Nov 2024 19:30:29 +0100 Subject: [PATCH 08/12] print test output to screen (#254) print test output to screen Signed-off-by: JianMinTang --- .github/actions/publish-and-sign/action.yaml | 2 +- .github/workflows/default.yaml | 10 +++++----- dagger/main.go | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/actions/publish-and-sign/action.yaml b/.github/actions/publish-and-sign/action.yaml index 6422743d..73a613fd 100644 --- a/.github/actions/publish-and-sign/action.yaml +++ b/.github/actions/publish-and-sign/action.yaml @@ -34,7 +34,7 @@ runs: run: cosign env - name: Publish and Sign Snapshot Image - uses: dagger/dagger-for-github@v6 + uses: dagger/dagger-for-github@v7 env: GITHUB_TOKEN: ${{ inputs.GITHUB_TOKEN }} REGISTRY_ADDRESS: ${{ inputs.REGISTRY_ADDRESS }} diff --git a/.github/workflows/default.yaml b/.github/workflows/default.yaml index 59800436..c1953237 100644 --- a/.github/workflows/default.yaml +++ b/.github/workflows/default.yaml @@ -23,7 +23,7 @@ jobs: uses: sagikazarmark/dagger-version-action@v0.0.1 - name: Run Dagger golangci-lint - uses: dagger/dagger-for-github@v6 + uses: dagger/dagger-for-github@v7 with: version: ${{ steps.dagger_version.outputs.version }} verb: call @@ -45,14 +45,14 @@ jobs: fetch-depth: 0 - name: Run Tests - uses: dagger/dagger-for-github@v6 + uses: dagger/dagger-for-github@v7 with: version: ${{ steps.dagger_version.outputs.version }} verb: call - args: test export --path=./testResults + args: test - name: Build Binary - uses: dagger/dagger-for-github@v6 + uses: dagger/dagger-for-github@v7 with: version: ${{ steps.dagger_version.outputs.version }} verb: call @@ -99,7 +99,7 @@ jobs: with: fetch-depth: 0 - name: Create Release - uses: dagger/dagger-for-github@v6 + uses: dagger/dagger-for-github@v7 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: diff --git a/dagger/main.go b/dagger/main.go index 762f1344..1035123f 100644 --- a/dagger/main.go +++ b/dagger/main.go @@ -225,8 +225,8 @@ func (m *HarborCli) RunDoc(ctx context.Context) *dagger.Directory { } // Test Executes Go tests and returns the directory containing the test results -func (m *HarborCli) Test(ctx context.Context) *dagger.Directory { - return dag.Container(). +func (m *HarborCli) Test(ctx context.Context) (string, error) { + test := dag.Container(). From("golang:"+GO_VERSION+"-alpine"). WithMountedCache("/go/pkg/mod", dag.CacheVolume("go-mod-"+GO_VERSION)). WithEnvVariable("GOMODCACHE", "/go/pkg/mod"). @@ -234,8 +234,8 @@ func (m *HarborCli) Test(ctx context.Context) *dagger.Directory { WithEnvVariable("GOCACHE", "/go/build-cache"). WithMountedDirectory("/src", m.Source). WithWorkdir("/src"). - WithExec([]string{"go", "test", "./..."}). - Directory("/src") + WithExec([]string{"go", "test", "-v", "./..."}) + return test.Stdout(ctx) } // Parse the platform string into os and arch From bc44301ff47f29afe35c256d8a9c408b40c829e1 Mon Sep 17 00:00:00 2001 From: JianMinTang Date: Tue, 19 Nov 2024 14:12:10 +0800 Subject: [PATCH 09/12] Support table format for repo view and add some comments on repo list Signed-off-by: JianMinTang Add more detail on repo view Signed-off-by: JianMinTang Support table format on registry view Signed-off-by: JianMinTang Support table format on project view Signed-off-by: JianMinTang Fixed tags list Signed-off-by: JianMinTang Support table format and YAML/JSON output on artifact view Signed-off-by: JianMinTang Fixed alignment problem Signed-off-by: JianMinTang Fixed the code format Signed-off-by: JianMinTang --- cmd/harbor/root/artifact/cmd.go | 2 +- cmd/harbor/root/artifact/info.go | 39 ------------------- cmd/harbor/root/artifact/list.go | 8 ++++ cmd/harbor/root/artifact/tags.go | 31 +++++++++++---- cmd/harbor/root/artifact/view.go | 55 +++++++++++++++++++++++++++ cmd/harbor/root/project/list.go | 23 ++++++++++-- cmd/harbor/root/project/view.go | 25 +++++++++++-- cmd/harbor/root/registry/cmd.go | 2 +- cmd/harbor/root/registry/info.go | 34 ----------------- cmd/harbor/root/registry/view.go | 56 ++++++++++++++++++++++++++++ cmd/harbor/root/repository/cmd.go | 2 +- cmd/harbor/root/repository/info.go | 35 ----------------- cmd/harbor/root/repository/list.go | 8 ++-- cmd/harbor/root/repository/view.go | 54 +++++++++++++++++++++++++++ cmd/harbor/root/user/delete.go | 6 +-- cmd/harbor/root/user/elevate.go | 4 +- cmd/harbor/root/user/list.go | 10 ++++- pkg/api/artifact_handler.go | 32 ++++++++++------ pkg/api/project_handler.go | 29 +++++++++++--- pkg/api/registry_handler.go | 15 ++++---- pkg/api/repository_handler.go | 12 +++--- pkg/api/user_handler.go | 31 +++++++++++++-- pkg/prompt/prompt.go | 2 +- pkg/views/artifact/tags/list/view.go | 39 +++++++++++++++++++ pkg/views/artifact/view/view.go | 47 +++++++++++++++++++++++ pkg/views/project/list/view.go | 4 +- pkg/views/project/view/view.go | 52 ++++++++++++++++++++++++++ pkg/views/registry/view/view.go | 43 +++++++++++++++++++++ pkg/views/repository/view/view.go | 47 +++++++++++++++++++++++ 29 files changed, 574 insertions(+), 173 deletions(-) delete mode 100644 cmd/harbor/root/artifact/info.go create mode 100644 cmd/harbor/root/artifact/view.go delete mode 100644 cmd/harbor/root/registry/info.go create mode 100644 cmd/harbor/root/registry/view.go delete mode 100644 cmd/harbor/root/repository/info.go create mode 100644 cmd/harbor/root/repository/view.go create mode 100644 pkg/views/artifact/tags/list/view.go create mode 100644 pkg/views/artifact/view/view.go create mode 100644 pkg/views/project/view/view.go create mode 100644 pkg/views/registry/view/view.go create mode 100644 pkg/views/repository/view/view.go diff --git a/cmd/harbor/root/artifact/cmd.go b/cmd/harbor/root/artifact/cmd.go index 9ae56ba1..8f9c66d2 100644 --- a/cmd/harbor/root/artifact/cmd.go +++ b/cmd/harbor/root/artifact/cmd.go @@ -15,7 +15,7 @@ func Artifact() *cobra.Command { cmd.AddCommand( ListArtifactCommand(), - InfoArtifactCommmand(), + ViewArtifactCommmand(), DeleteArtifactCommand(), ScanArtifactCommand(), ArtifactTagsCmd(), diff --git a/cmd/harbor/root/artifact/info.go b/cmd/harbor/root/artifact/info.go deleted file mode 100644 index b215d91a..00000000 --- a/cmd/harbor/root/artifact/info.go +++ /dev/null @@ -1,39 +0,0 @@ -package artifact - -import ( - "github.com/goharbor/harbor-cli/pkg/api" - "github.com/goharbor/harbor-cli/pkg/prompt" - "github.com/goharbor/harbor-cli/pkg/utils" - log "github.com/sirupsen/logrus" - "github.com/spf13/cobra" -) - -func InfoArtifactCommmand() *cobra.Command { - - cmd := &cobra.Command{ - Use: "info", - Short: "Get info of an artifact", - Long: `Get info of an artifact`, - Example: `harbor artifact info //`, - Run: func(cmd *cobra.Command, args []string) { - var err error - - if len(args) > 0 { - projectName, repoName, reference := utils.ParseProjectRepoReference(args[0]) - err = api.InfoArtifact(projectName, repoName, reference) - } else { - projectName := prompt.GetProjectNameFromUser() - repoName := prompt.GetRepoNameFromUser(projectName) - reference := prompt.GetReferenceFromUser(repoName, projectName) - err = api.InfoArtifact(projectName, repoName, reference) - } - - if err != nil { - log.Errorf("failed to get info of an artifact: %v", err) - } - - }, - } - - return cmd -} diff --git a/cmd/harbor/root/artifact/list.go b/cmd/harbor/root/artifact/list.go index 243a1a9c..26bb5af2 100644 --- a/cmd/harbor/root/artifact/list.go +++ b/cmd/harbor/root/artifact/list.go @@ -12,6 +12,8 @@ import ( ) func ListArtifactCommand() *cobra.Command { + var opts api.ListFlags + cmd := &cobra.Command{ Use: "list", Short: "list artifacts within a repository", @@ -46,5 +48,11 @@ func ListArtifactCommand() *cobra.Command { }, } + flags := cmd.Flags() + flags.Int64VarP(&opts.Page, "page", "p", 1, "Page number") + flags.Int64VarP(&opts.PageSize, "page-size", "n", 10, "Size of per page") + flags.StringVarP(&opts.Q, "query", "q", "", "Query string to query resources") + flags.StringVarP(&opts.Sort, "sort", "s", "", "Sort the resource list in ascending or descending order") + return cmd } diff --git a/cmd/harbor/root/artifact/tags.go b/cmd/harbor/root/artifact/tags.go index f5b582d2..a213b3c7 100644 --- a/cmd/harbor/root/artifact/tags.go +++ b/cmd/harbor/root/artifact/tags.go @@ -6,8 +6,10 @@ import ( "github.com/goharbor/harbor-cli/pkg/prompt" "github.com/goharbor/harbor-cli/pkg/utils" "github.com/goharbor/harbor-cli/pkg/views/artifact/tags/create" + "github.com/goharbor/harbor-cli/pkg/views/artifact/tags/list" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" + "github.com/spf13/viper" ) func ArtifactTagsCmd() *cobra.Command { @@ -62,22 +64,35 @@ func ListTagsCmd() *cobra.Command { Example: `harbor artifact tags list //`, Run: func(cmd *cobra.Command, args []string) { var err error + var tags *artifact.ListTagsOK + var projectName, repoName, reference string - var resp artifact.ListTagsOK if len(args) > 0 { - projectName, repoName, reference := utils.ParseProjectRepoReference(args[0]) - resp, err = api.ListTags(projectName, repoName, reference) + projectName, repoName, reference = utils.ParseProjectRepoReference(args[0]) } else { - projectName := prompt.GetProjectNameFromUser() - repoName := prompt.GetRepoNameFromUser(projectName) - reference := prompt.GetReferenceFromUser(repoName, projectName) - resp, err = api.ListTags(projectName, repoName, reference) + projectName = prompt.GetProjectNameFromUser() + repoName = prompt.GetRepoNameFromUser(projectName) + reference = prompt.GetReferenceFromUser(repoName, projectName) } + + tags, err = api.ListTags(projectName, repoName, reference) + if err != nil { log.Errorf("failed to list tags: %v", err) + return + } + + FormatFlag := viper.GetString("output-format") + if FormatFlag != "" { + err = utils.PrintFormat(tags, FormatFlag) + if err != nil { + log.Error(err) + return + } + } else { + list.ListTags(tags.Payload) } - log.Info(resp.Payload) }, } diff --git a/cmd/harbor/root/artifact/view.go b/cmd/harbor/root/artifact/view.go new file mode 100644 index 00000000..7d13c0f6 --- /dev/null +++ b/cmd/harbor/root/artifact/view.go @@ -0,0 +1,55 @@ +package artifact + +import ( + "github.com/goharbor/go-client/pkg/sdk/v2.0/client/artifact" + "github.com/goharbor/harbor-cli/pkg/api" + "github.com/goharbor/harbor-cli/pkg/prompt" + "github.com/goharbor/harbor-cli/pkg/utils" + "github.com/goharbor/harbor-cli/pkg/views/artifact/view" + log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +func ViewArtifactCommmand() *cobra.Command { + + cmd := &cobra.Command{ + Use: "view", + Short: "Get information of an artifact", + Long: `Get information of an artifact`, + Example: `harbor artifact view //`, + Run: func(cmd *cobra.Command, args []string) { + var err error + var projectName, repoName, reference string + var artifact *artifact.GetArtifactOK + + if len(args) > 0 { + projectName, repoName, reference = utils.ParseProjectRepoReference(args[0]) + } else { + projectName = prompt.GetProjectNameFromUser() + repoName = prompt.GetRepoNameFromUser(projectName) + reference = prompt.GetReferenceFromUser(repoName, projectName) + } + + artifact, err = api.ViewArtifact(projectName, repoName, reference) + + if err != nil { + log.Errorf("failed to get info of an artifact: %v", err) + } + + FormatFlag := viper.GetString("output-format") + if FormatFlag != "" { + err = utils.PrintFormat(artifact, FormatFlag) + if err != nil { + log.Error(err) + return + } + } else { + view.ViewArtifact(artifact.Payload) + } + + }, + } + + return cmd +} diff --git a/cmd/harbor/root/project/list.go b/cmd/harbor/root/project/list.go index 51a1a3fc..3a908b42 100644 --- a/cmd/harbor/root/project/list.go +++ b/cmd/harbor/root/project/list.go @@ -1,6 +1,7 @@ package project import ( + "github.com/goharbor/go-client/pkg/sdk/v2.0/client/project" "github.com/goharbor/harbor-cli/pkg/api" "github.com/goharbor/harbor-cli/pkg/utils" list "github.com/goharbor/harbor-cli/pkg/views/project/list" @@ -9,15 +10,28 @@ import ( "github.com/spf13/viper" ) -// NewListProjectCommand creates a new `harbor list project` command func ListProjectCommand() *cobra.Command { var opts api.ListFlags - + var private bool + var public bool + var projects project.ListProjectsOK + var err error cmd := &cobra.Command{ Use: "list", Short: "list project", Run: func(cmd *cobra.Command, args []string) { - projects, err := api.ListProject(opts) + if private && public { + log.Fatal("Cannot specify both --private and --public flags") + } else if private { + opts.Public = false + projects, err = api.ListProject(opts) + } else if public { + opts.Public = true + projects, err = api.ListProject(opts) + } else { + projects, err = api.ListAllProjects(opts) + } + if err != nil { log.Fatalf("failed to get projects list: %v", err) } @@ -37,7 +51,8 @@ func ListProjectCommand() *cobra.Command { flags.StringVarP(&opts.Name, "name", "", "", "Name of the project") flags.Int64VarP(&opts.Page, "page", "", 1, "Page number") flags.Int64VarP(&opts.PageSize, "page-size", "", 10, "Size of per page") - flags.BoolVarP(&opts.Public, "public", "", false, "Project is public or private") + flags.BoolVarP(&private, "private", "", false, "Show only private projects") + flags.BoolVarP(&public, "public", "", false, "Show only public projects") flags.StringVarP(&opts.Q, "query", "q", "", "Query string to query resources") flags.StringVarP(&opts.Sort, "sort", "", "", "Sort the resource list in ascending or descending order") diff --git a/cmd/harbor/root/project/view.go b/cmd/harbor/root/project/view.go index 908d51d8..7d7addc4 100644 --- a/cmd/harbor/root/project/view.go +++ b/cmd/harbor/root/project/view.go @@ -1,10 +1,14 @@ package project import ( + "github.com/goharbor/go-client/pkg/sdk/v2.0/client/project" "github.com/goharbor/harbor-cli/pkg/api" "github.com/goharbor/harbor-cli/pkg/prompt" + "github.com/goharbor/harbor-cli/pkg/utils" + "github.com/goharbor/harbor-cli/pkg/views/project/view" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" + "github.com/spf13/viper" ) // GetProjectCommand creates a new `harbor get project` command @@ -16,16 +20,31 @@ func ViewCommand() *cobra.Command { Args: cobra.MaximumNArgs(1), Run: func(cmd *cobra.Command, args []string) { var err error + var projectName string + var project *project.GetProjectOK if len(args) > 0 { - err = api.GetProject(args[0]) + projectName = args[0] } else { - projectName := prompt.GetProjectNameFromUser() - err = api.GetProject(projectName) + projectName = prompt.GetProjectNameFromUser() } + project, err = api.GetProject(projectName) + if err != nil { log.Errorf("failed to get project: %v", err) + return + } + + FormatFlag := viper.GetString("output-format") + if FormatFlag != "" { + err = utils.PrintFormat(project, FormatFlag) + if err != nil { + log.Error(err) + return + } + } else { + view.ViewProjects(project.Payload) } }, diff --git a/cmd/harbor/root/registry/cmd.go b/cmd/harbor/root/registry/cmd.go index 9f42d761..3f9d2e26 100644 --- a/cmd/harbor/root/registry/cmd.go +++ b/cmd/harbor/root/registry/cmd.go @@ -13,7 +13,7 @@ func Registry() *cobra.Command { } cmd.AddCommand( CreateRegistryCommand(), - InfoRegistryCommand(), + ViewRegistryCommand(), DeleteRegistryCommand(), ListRegistryCommand(), UpdateRegistryCommand(), diff --git a/cmd/harbor/root/registry/info.go b/cmd/harbor/root/registry/info.go deleted file mode 100644 index 97a16799..00000000 --- a/cmd/harbor/root/registry/info.go +++ /dev/null @@ -1,34 +0,0 @@ -package registry - -import ( - "github.com/goharbor/harbor-cli/pkg/api" - "github.com/goharbor/harbor-cli/pkg/prompt" - log "github.com/sirupsen/logrus" - "github.com/spf13/cobra" -) - -func InfoRegistryCommand() *cobra.Command { - cmd := &cobra.Command{ - Use: "info", - Short: "get registry info", - Example: "harbor registry info [registryname]", - Args: cobra.MaximumNArgs(1), - Run: func(cmd *cobra.Command, args []string) { - var err error - - if len(args) > 0 { - registryName, _ := api.GetRegistryIdByName(args[0]) - err = api.InfoRegistry(registryName) - } else { - registryId := prompt.GetRegistryNameFromUser() - err = api.InfoRegistry(registryId) - } - if err != nil { - log.Errorf("failed to get registry info: %v", err) - } - - }, - } - - return cmd -} diff --git a/cmd/harbor/root/registry/view.go b/cmd/harbor/root/registry/view.go new file mode 100644 index 00000000..f7910971 --- /dev/null +++ b/cmd/harbor/root/registry/view.go @@ -0,0 +1,56 @@ +package registry + +import ( + "github.com/goharbor/go-client/pkg/sdk/v2.0/client/registry" + "github.com/goharbor/harbor-cli/pkg/api" + "github.com/goharbor/harbor-cli/pkg/prompt" + "github.com/goharbor/harbor-cli/pkg/utils" + "github.com/goharbor/harbor-cli/pkg/views/registry/view" + log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +func ViewRegistryCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "view", + Short: "get registry information", + Example: "harbor registry view [registryName]", + Args: cobra.MaximumNArgs(1), + Run: func(cmd *cobra.Command, args []string) { + var err error + var registryId int64 + var registry *registry.GetRegistryOK + + if len(args) > 0 { + registryId, err = api.GetRegistryIdByName(args[0]) + if err != nil { + log.Errorf("failed to get registry name by id: %v", err) + return + } + } else { + registryId = prompt.GetRegistryNameFromUser() + } + + registry, err = api.ViewRegistry(registryId) + + if err != nil { + log.Errorf("failed to get registry info: %v", err) + return + } + + FormatFlag := viper.GetString("output-format") + if FormatFlag != "" { + err = utils.PrintFormat(registry, FormatFlag) + if err != nil { + log.Error(err) + } + } else { + view.ViewRegistry(registry.Payload) + } + + }, + } + + return cmd +} diff --git a/cmd/harbor/root/repository/cmd.go b/cmd/harbor/root/repository/cmd.go index 3efa30b6..38fd5f57 100644 --- a/cmd/harbor/root/repository/cmd.go +++ b/cmd/harbor/root/repository/cmd.go @@ -10,7 +10,7 @@ func Repository() *cobra.Command { } cmd.AddCommand( ListRepositoryCommand(), - RepoInfoCmd(), + RepoViewCmd(), RepoDeleteCmd(), ) diff --git a/cmd/harbor/root/repository/info.go b/cmd/harbor/root/repository/info.go deleted file mode 100644 index 6a54da71..00000000 --- a/cmd/harbor/root/repository/info.go +++ /dev/null @@ -1,35 +0,0 @@ -package repository - -import ( - "github.com/goharbor/harbor-cli/pkg/api" - "github.com/goharbor/harbor-cli/pkg/prompt" - "github.com/goharbor/harbor-cli/pkg/utils" - log "github.com/sirupsen/logrus" - "github.com/spf13/cobra" -) - -func RepoInfoCmd() *cobra.Command { - cmd := &cobra.Command{ - Use: "info", - Short: "Get repository information", - Example: ` harbor repo info /`, - Long: `Get information of a particular repository in a project`, - Run: func(cmd *cobra.Command, args []string) { - var err error - if len(args) > 0 { - projectName, repoName := utils.ParseProjectRepo(args[0]) - err = api.RepoInfo(projectName, repoName) - } else { - projectName := prompt.GetProjectNameFromUser() - repoName := prompt.GetRepoNameFromUser(projectName) - err = api.RepoInfo(projectName, repoName) - } - if err != nil { - log.Errorf("failed to get repository information: %v", err) - } - - }, - } - - return cmd -} diff --git a/cmd/harbor/root/repository/list.go b/cmd/harbor/root/repository/list.go index d9c803f5..41ca0492 100644 --- a/cmd/harbor/root/repository/list.go +++ b/cmd/harbor/root/repository/list.go @@ -13,9 +13,11 @@ import ( func ListRepositoryCommand() *cobra.Command { cmd := &cobra.Command{ - Use: "list", - Short: "list repositories within a project", - Args: cobra.MaximumNArgs(1), + Use: "list", + Short: "list repositories within a project", + Example: ` harbor repo list `, + Long: `Get information of all repositories in a project`, + Args: cobra.MaximumNArgs(1), Run: func(cmd *cobra.Command, args []string) { var err error var repos repository.ListRepositoriesOK diff --git a/cmd/harbor/root/repository/view.go b/cmd/harbor/root/repository/view.go new file mode 100644 index 00000000..463387df --- /dev/null +++ b/cmd/harbor/root/repository/view.go @@ -0,0 +1,54 @@ +package repository + +import ( + "github.com/goharbor/go-client/pkg/sdk/v2.0/client/repository" + "github.com/goharbor/harbor-cli/pkg/api" + "github.com/goharbor/harbor-cli/pkg/prompt" + "github.com/goharbor/harbor-cli/pkg/utils" + "github.com/goharbor/harbor-cli/pkg/views/repository/view" + log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +func RepoViewCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "view", + Short: "Get repository information", + Example: ` harbor repo view /`, + Long: `Get information of a particular repository in a project`, + Run: func(cmd *cobra.Command, args []string) { + var err error + var projectName, repoName string + var repo *repository.GetRepositoryOK + + if len(args) > 0 { + projectName, repoName = utils.ParseProjectRepo(args[0]) + } else { + projectName = prompt.GetProjectNameFromUser() + repoName = prompt.GetRepoNameFromUser(projectName) + } + + repo, err = api.RepoView(projectName, repoName) + + if err != nil { + log.Errorf("failed to get repository information: %v", err) + return + } + + FormatFlag := viper.GetString("output-format") + if FormatFlag != "" { + err = utils.PrintFormat(repo, FormatFlag) + if err != nil { + log.Error(err) + return + } + } else { + view.ViewRepository(repo.Payload) + } + + }, + } + + return cmd +} diff --git a/cmd/harbor/root/user/delete.go b/cmd/harbor/root/user/delete.go index 1b5afc8a..43c24528 100644 --- a/cmd/harbor/root/user/delete.go +++ b/cmd/harbor/root/user/delete.go @@ -1,8 +1,6 @@ package user import ( - "strconv" - "github.com/goharbor/harbor-cli/pkg/api" "github.com/goharbor/harbor-cli/pkg/prompt" log "github.com/sirupsen/logrus" @@ -17,8 +15,8 @@ func UserDeleteCmd() *cobra.Command { Run: func(cmd *cobra.Command, args []string) { var err error if len(args) > 0 { - userId, _ := strconv.ParseInt(args[0], 10, 64) - err = api.DeleteUser(userId) + userName, _ := api.GetUsersIdByName(args[0]) + err = api.DeleteUser(userName) } else { userId := prompt.GetUserIdFromUser() diff --git a/cmd/harbor/root/user/elevate.go b/cmd/harbor/root/user/elevate.go index 25cc7299..66a38567 100644 --- a/cmd/harbor/root/user/elevate.go +++ b/cmd/harbor/root/user/elevate.go @@ -1,8 +1,6 @@ package user import ( - "strconv" - "github.com/goharbor/harbor-cli/pkg/api" "github.com/goharbor/harbor-cli/pkg/prompt" "github.com/goharbor/harbor-cli/pkg/views" @@ -20,7 +18,7 @@ func ElevateUserCmd() *cobra.Command { var err error var userId int64 if len(args) > 0 { - userId, _ = strconv.ParseInt(args[0], 10, 64) + userId, _ = api.GetUsersIdByName(args[0]) } else { userId = prompt.GetUserIdFromUser() diff --git a/cmd/harbor/root/user/list.go b/cmd/harbor/root/user/list.go index 28731a30..9a7999e9 100644 --- a/cmd/harbor/root/user/list.go +++ b/cmd/harbor/root/user/list.go @@ -10,13 +10,15 @@ import ( ) func UserListCmd() *cobra.Command { + var opts api.ListFlags + cmd := &cobra.Command{ Use: "list", Short: "list users", Args: cobra.NoArgs, Aliases: []string{"ls"}, Run: func(cmd *cobra.Command, args []string) { - response, err := api.ListUsers() + response, err := api.ListUsers(opts) if err != nil { log.Errorf("failed to list users: %v", err) return @@ -33,6 +35,12 @@ func UserListCmd() *cobra.Command { }, } + flags := cmd.Flags() + flags.Int64VarP(&opts.Page, "page", "p", 1, "Page number") + flags.Int64VarP(&opts.PageSize, "page-size", "n", 10, "Size of per page") + flags.StringVarP(&opts.Q, "query", "q", "", "Query string to query resources") + flags.StringVarP(&opts.Sort, "sort", "s", "", "Sort the resource list in ascending or descending order") + return cmd } diff --git a/pkg/api/artifact_handler.go b/pkg/api/artifact_handler.go index cdfc6764..d79eba44 100644 --- a/pkg/api/artifact_handler.go +++ b/pkg/api/artifact_handler.go @@ -30,36 +30,45 @@ func DeleteArtifact(projectName, repoName, reference string) error { } // InfoArtifact retrieves information about a specific artifact. -func InfoArtifact(projectName, repoName, reference string) error { +func ViewArtifact(projectName, repoName, reference string) (*artifact.GetArtifactOK, error) { ctx, client, err := utils.ContextWithClient() + var response = &artifact.GetArtifactOK{} if err != nil { - return err + return response, err } - response, err := client.Artifact.GetArtifact(ctx, &artifact.GetArtifactParams{ + response, err = client.Artifact.GetArtifact(ctx, &artifact.GetArtifactParams{ ProjectName: projectName, RepositoryName: repoName, Reference: reference, }) + if err != nil { log.Errorf("Failed to get artifact info: %v", err) - return err + return response, err } - utils.PrintPayloadInJSONFormat(response.Payload) - return nil + return response, nil } // RunListArtifact lists all artifacts in a repository. -func ListArtifact(projectName, repoName string) (artifact.ListArtifactsOK, error) { +func ListArtifact(projectName, repoName string, opts ...ListFlags) (artifact.ListArtifactsOK, error) { ctx, client, err := utils.ContextWithClient() if err != nil { return artifact.ListArtifactsOK{}, err } + var listFlags ListFlags + if len(opts) > 0 { + listFlags = opts[0] + } response, err := client.Artifact.ListArtifacts(ctx, &artifact.ListArtifactsParams{ ProjectName: projectName, RepositoryName: repoName, + Page: &listFlags.Page, + PageSize: &listFlags.PageSize, + Q: &listFlags.Q, + Sort: &listFlags.Sort, }) if err != nil { return artifact.ListArtifactsOK{}, err @@ -133,10 +142,10 @@ func DeleteTag(projectName, repoName, reference, tag string) error { } // ListTags lists all tags of a specific artifact. -func ListTags(projectName, repoName, reference string) (artifact.ListTagsOK, error) { +func ListTags(projectName, repoName, reference string) (*artifact.ListTagsOK, error) { ctx, client, err := utils.ContextWithClient() if err != nil { - return artifact.ListTagsOK{}, err + return &artifact.ListTagsOK{}, err } resp, err := client.Artifact.ListTags(ctx, &artifact.ListTagsParams{ @@ -144,12 +153,13 @@ func ListTags(projectName, repoName, reference string) (artifact.ListTagsOK, err RepositoryName: repoName, Reference: reference, }) + if err != nil { log.Errorf("Failed to list tags: %v", err) - return artifact.ListTagsOK{}, err + return &artifact.ListTagsOK{}, err } - return *resp, nil + return resp, nil } // CreateTag creates a tag for a specific artifact. diff --git a/pkg/api/project_handler.go b/pkg/api/project_handler.go index 07824a30..bef918f6 100644 --- a/pkg/api/project_handler.go +++ b/pkg/api/project_handler.go @@ -38,20 +38,21 @@ func CreateProject(opts create.CreateView) error { return nil } -func GetProject(projectName string) error { +func GetProject(projectName string) (*project.GetProjectOK, error) { ctx, client, err := utils.ContextWithClient() + var response = &project.GetProjectOK{} + if err != nil { - return err + return response, err } - response, err := client.Project.GetProject(ctx, &project.GetProjectParams{ProjectNameOrID: projectName}) + response, err = client.Project.GetProject(ctx, &project.GetProjectParams{ProjectNameOrID: projectName}) if err != nil { - return err + return response, err } - utils.PrintPayloadInJSONFormat(response) - return nil + return response, nil } func DeleteProject(projectName string) error { @@ -86,6 +87,22 @@ func ListProject(opts ...ListFlags) (project.ListProjectsOK, error) { return *response, nil } +func ListAllProjects(opts ...ListFlags) (project.ListProjectsOK, error) { + ctx, client, err := utils.ContextWithClient() + if err != nil { + return project.ListProjectsOK{}, err + } + var listFlags ListFlags + if len(opts) > 0 { + listFlags = opts[0] + } + response, err := client.Project.ListProjects(ctx, &project.ListProjectsParams{Page: &listFlags.Page, PageSize: &listFlags.PageSize, Q: &listFlags.Q, Sort: &listFlags.Sort, Name: &listFlags.Name}) + if err != nil { + return project.ListProjectsOK{}, err + } + return *response, nil +} + func LogsProject(projectName string) (*project.GetLogsOK, error) { ctx, client, err := utils.ContextWithClient() if err != nil { diff --git a/pkg/api/registry_handler.go b/pkg/api/registry_handler.go index e3a341cb..0df427fc 100644 --- a/pkg/api/registry_handler.go +++ b/pkg/api/registry_handler.go @@ -81,22 +81,23 @@ func DeleteRegistry(registryName int64) error { return nil } -func InfoRegistry(registryId int64) error { +func ViewRegistry(registryId int64) (*registry.GetRegistryOK, error) { ctx, client, err := utils.ContextWithClient() + var response = ®istry.GetRegistryOK{} if err != nil { - return err + return response, err } - response, err := client.Registry.GetRegistry(ctx, ®istry.GetRegistryParams{ID: registryId}) + response, err = client.Registry.GetRegistry(ctx, ®istry.GetRegistryParams{ID: registryId}) + if err != nil { - return err + return response, err } if response.Payload.ID == 0 { - return fmt.Errorf("registry is not found") + return response, fmt.Errorf("registry is not found") } - utils.PrintPayloadInJSONFormat(response.Payload) - return nil + return response, nil } func UpdateRegistry(updateView *CreateRegView, projectID int64) error { diff --git a/pkg/api/repository_handler.go b/pkg/api/repository_handler.go index 7e5662b4..c88109e6 100644 --- a/pkg/api/repository_handler.go +++ b/pkg/api/repository_handler.go @@ -21,20 +21,20 @@ func RepoDelete(projectName, repoName string) error { return nil } -func RepoInfo(projectName, repoName string) error { +func RepoView(projectName, repoName string) (*repository.GetRepositoryOK, error) { ctx, client, err := utils.ContextWithClient() + var response = &repository.GetRepositoryOK{} if err != nil { - return err + return response, err } - response, err := client.Repository.GetRepository(ctx, &repository.GetRepositoryParams{ProjectName: projectName, RepositoryName: repoName}) + response, err = client.Repository.GetRepository(ctx, &repository.GetRepositoryParams{ProjectName: projectName, RepositoryName: repoName}) if err != nil { - return err + return response, err } - utils.PrintPayloadInJSONFormat(response.Payload) - return nil + return response, nil } func ListRepository(projectName string) (repository.ListRepositoriesOK, error) { diff --git a/pkg/api/user_handler.go b/pkg/api/user_handler.go index 4b599420..b1e8a7d6 100644 --- a/pkg/api/user_handler.go +++ b/pkg/api/user_handler.go @@ -67,17 +67,42 @@ func ElevateUser(userId int64) error { return nil } -func ListUsers() (*user.ListUsersOK, error) { +func ListUsers(opts ...ListFlags) (*user.ListUsersOK, error) { ctx, client, err := utils.ContextWithClient() if err != nil { return nil, err } + var listFlags ListFlags + if len(opts) > 0 { + listFlags = opts[0] + } - response, err := client.User.ListUsers(ctx, &user.ListUsersParams{}) - + response, err := client.User.ListUsers(ctx, &user.ListUsersParams{ + Page: &listFlags.Page, + PageSize: &listFlags.PageSize, + Q: &listFlags.Q, + Sort: &listFlags.Sort, + }) if err != nil { return nil, err } return response, nil } + +func GetUsersIdByName(userName string) (int64, error) { + var opts ListFlags + + u, err := ListUsers(opts) + if err != nil { + return 0, err + } + + for _, user := range u.Payload { + if user.Username == userName { + return user.UserID, nil + } + } + + return 0, err +} diff --git a/pkg/prompt/prompt.go b/pkg/prompt/prompt.go index f67f9b94..ccf96a5c 100644 --- a/pkg/prompt/prompt.go +++ b/pkg/prompt/prompt.go @@ -26,7 +26,7 @@ func GetRegistryNameFromUser() int64 { func GetProjectNameFromUser() string { projectName := make(chan string) go func() { - response, _ := api.ListProject() + response, _ := api.ListAllProjects() pview.ProjectList(response.Payload, projectName) }() diff --git a/pkg/views/artifact/tags/list/view.go b/pkg/views/artifact/tags/list/view.go new file mode 100644 index 00000000..f20491b5 --- /dev/null +++ b/pkg/views/artifact/tags/list/view.go @@ -0,0 +1,39 @@ +package list + +import ( + "fmt" + "os" + + "github.com/charmbracelet/bubbles/table" + tea "github.com/charmbracelet/bubbletea" + "github.com/goharbor/go-client/pkg/sdk/v2.0/models" + "github.com/goharbor/harbor-cli/pkg/utils" + "github.com/goharbor/harbor-cli/pkg/views/base/tablelist" +) + +var columns = []table.Column{ + {Title: "Name", Width: 12}, + {Title: "Pull Time", Width: 30}, + {Title: "Push Time", Width: 30}, +} + +func ListTags(tags []*models.Tag) { + var rows []table.Row + for _, tag := range tags { + + pullTime, _ := utils.FormatCreatedTime(tag.PullTime.String()) + pushTime, _ := utils.FormatCreatedTime(tag.PushTime.String()) + rows = append(rows, table.Row{ + tag.Name, + pullTime, + pushTime, + }) + } + + m := tablelist.NewModel(columns, rows, len(rows)) + + if _, err := tea.NewProgram(m).Run(); err != nil { + fmt.Println("Error running program:", err) + os.Exit(1) + } +} diff --git a/pkg/views/artifact/view/view.go b/pkg/views/artifact/view/view.go new file mode 100644 index 00000000..0ab46ae7 --- /dev/null +++ b/pkg/views/artifact/view/view.go @@ -0,0 +1,47 @@ +package view + +import ( + "fmt" + "github.com/charmbracelet/bubbles/table" + tea "github.com/charmbracelet/bubbletea" + "github.com/goharbor/go-client/pkg/sdk/v2.0/models" + "github.com/goharbor/harbor-cli/pkg/utils" + "github.com/goharbor/harbor-cli/pkg/views/base/tablelist" + "os" + "strconv" +) + +var columns = []table.Column{ + {Title: "ID", Width: 6}, + {Title: "Artifact Digest", Width: 20}, + {Title: "Type", Width: 12}, + {Title: "Size", Width: 12}, + {Title: "Vulnerabilities", Width: 15}, + {Title: "Push Time", Width: 12}, +} + +func ViewArtifact(artifact *models.Artifact) { + var rows []table.Row + + pushTime, _ := utils.FormatCreatedTime(artifact.PushTime.String()) + artifactSize := utils.FormatSize(artifact.Size) + var totalVulnerabilities int64 + for _, scan := range artifact.ScanOverview { + totalVulnerabilities += scan.Summary.Total + } + rows = append(rows, table.Row{ + strconv.FormatInt(int64(artifact.ID), 10), + artifact.Digest[:16], + artifact.Type, + artifactSize, + strconv.FormatInt(totalVulnerabilities, 10), + pushTime, + }) + + m := tablelist.NewModel(columns, rows, len(rows)) + + if _, err := tea.NewProgram(m).Run(); err != nil { + fmt.Println("Error running program:", err) + os.Exit(1) + } +} diff --git a/pkg/views/project/list/view.go b/pkg/views/project/list/view.go index 5f979844..51dbb487 100644 --- a/pkg/views/project/list/view.go +++ b/pkg/views/project/list/view.go @@ -14,11 +14,11 @@ import ( var columns = []table.Column{ {Title: "ID", Width: 6}, - {Title: "Project Name", Width: 12}, + {Title: "Project Name", Width: 20}, {Title: "Access Level", Width: 12}, {Title: "Type", Width: 12}, {Title: "Repo Count", Width: 12}, - {Title: "Creation Time", Width: 30}, + {Title: "Creation Time", Width: 18}, } func ListProjects(projects []*models.Project) { diff --git a/pkg/views/project/view/view.go b/pkg/views/project/view/view.go new file mode 100644 index 00000000..66e2b937 --- /dev/null +++ b/pkg/views/project/view/view.go @@ -0,0 +1,52 @@ +package view + +import ( + "fmt" + "os" + "strconv" + + "github.com/charmbracelet/bubbles/table" + tea "github.com/charmbracelet/bubbletea" + "github.com/goharbor/go-client/pkg/sdk/v2.0/models" + "github.com/goharbor/harbor-cli/pkg/utils" + "github.com/goharbor/harbor-cli/pkg/views/base/tablelist" +) + +var columns = []table.Column{ + {Title: "Project ID", Width: 10}, + {Title: "Project Name", Width: 12}, + {Title: "Access Level", Width: 12}, + {Title: "Type", Width: 12}, + {Title: "Repo Count", Width: 12}, + {Title: "Creation Time", Width: 15}, +} + +func ViewProjects(project *models.Project) { + var rows []table.Row + accessLevel := "public" + if project.Metadata.Public != "true" { + accessLevel = "private" + } + + projectType := "project" + + if project.RegistryID != 0 { + projectType = "proxy cache" + } + createdTime, _ := utils.FormatCreatedTime(project.CreationTime.String()) + rows = append(rows, table.Row{ + strconv.FormatInt(int64(project.ProjectID), 10), // ProjectID + project.Name, // Project Name + accessLevel, // Access Level + projectType, // Type + strconv.FormatInt(project.RepoCount, 10), + createdTime, // Creation Time, + }) + + m := tablelist.NewModel(columns, rows, len(rows)) + + if _, err := tea.NewProgram(m).Run(); err != nil { + fmt.Println("Error running program:", err) + os.Exit(1) + } +} diff --git a/pkg/views/registry/view/view.go b/pkg/views/registry/view/view.go new file mode 100644 index 00000000..f792b930 --- /dev/null +++ b/pkg/views/registry/view/view.go @@ -0,0 +1,43 @@ +package view + +import ( + "fmt" + "os" + + "github.com/charmbracelet/bubbles/table" + tea "github.com/charmbracelet/bubbletea" + "github.com/goharbor/go-client/pkg/sdk/v2.0/models" + "github.com/goharbor/harbor-cli/pkg/utils" + "github.com/goharbor/harbor-cli/pkg/views/base/tablelist" +) + +var columns = []table.Column{ + {Title: "ID", Width: 5}, + {Title: "Name", Width: 10}, + {Title: "Status", Width: 10}, + {Title: "Endpoint URL", Width: 20}, + {Title: "Provider", Width: 15}, + {Title: "Creation Time", Width: 15}, + {Title: "Description", Width: 20}, +} + +func ViewRegistry(registry *models.Registry) { + var rows []table.Row + createdTime, _ := utils.FormatCreatedTime(registry.CreationTime.String()) + rows = append(rows, table.Row{ + fmt.Sprintf("%d", registry.ID), + registry.Name, + registry.Status, + registry.URL, + registry.Type, + createdTime, + registry.Description, + }) + + m := tablelist.NewModel(columns, rows, len(rows)) + + if _, err := tea.NewProgram(m).Run(); err != nil { + fmt.Println("Error running program:", err) + os.Exit(1) + } +} diff --git a/pkg/views/repository/view/view.go b/pkg/views/repository/view/view.go new file mode 100644 index 00000000..0b5944b5 --- /dev/null +++ b/pkg/views/repository/view/view.go @@ -0,0 +1,47 @@ +package view + +import ( + "fmt" + "os" + "strconv" + + "github.com/charmbracelet/bubbles/table" + tea "github.com/charmbracelet/bubbletea" + "github.com/goharbor/go-client/pkg/sdk/v2.0/models" + "github.com/goharbor/harbor-cli/pkg/utils" + "github.com/goharbor/harbor-cli/pkg/views/base/tablelist" +) + +var columns = []table.Column{ + {Title: "Name", Width: 20}, + {Title: "ID", Width: 10}, + {Title: "Project ID", Width: 10}, + {Title: "Artifacts", Width: 10}, + {Title: "Pulls", Width: 5}, + {Title: "Creation Time", Width: 20}, + {Title: "Last Modified Time", Width: 20}, + {Title: "Description", Width: 20}, +} + +func ViewRepository(repo *models.Repository) { + var rows []table.Row + + createdTime, _ := utils.FormatCreatedTime(repo.CreationTime.String()) + modifledTime, _ := utils.FormatCreatedTime(repo.UpdateTime.String()) + rows = append(rows, table.Row{ + repo.Name, + fmt.Sprintf("%d", repo.ID), + fmt.Sprintf("%d", repo.ProjectID), + fmt.Sprintf("%d", repo.ArtifactCount), + strconv.FormatInt(repo.PullCount, 10), + createdTime, + modifledTime, + repo.Description, + }) + + m := tablelist.NewModel(columns, rows, len(rows)) + if _, err := tea.NewProgram(m).Run(); err != nil { + fmt.Println("Error running program:", err) + os.Exit(1) + } +} From 2dba7b4df019f44e80047787ab78afe142b5cc50 Mon Sep 17 00:00:00 2001 From: Prasanth B <89722848+bupd@users.noreply.github.com> Date: Thu, 14 Nov 2024 23:40:03 +0530 Subject: [PATCH 10/12] AutoGenerate credential name in login (#250) * generate credential name Signed-off-by: bupd * feat: add support for the password-stdin flag in login flow Signed-off-by: karanngi * fix deps - fixes dependencies Signed-off-by: bupd * return stdout for tests Signed-off-by: bupd * update workflow Signed-off-by: bupd --------- Signed-off-by: bupd Signed-off-by: karanngi Co-authored-by: karanngi Signed-off-by: JianMinTang --- .github/workflows/default.yaml | 2 +- dagger/main.go | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/.github/workflows/default.yaml b/.github/workflows/default.yaml index c1953237..beba1d92 100644 --- a/.github/workflows/default.yaml +++ b/.github/workflows/default.yaml @@ -49,7 +49,7 @@ jobs: with: version: ${{ steps.dagger_version.outputs.version }} verb: call - args: test + args: test export --path=./testResults - name: Build Binary uses: dagger/dagger-for-github@v7 diff --git a/dagger/main.go b/dagger/main.go index 1035123f..009e8790 100644 --- a/dagger/main.go +++ b/dagger/main.go @@ -16,6 +16,9 @@ const ( ) func New( + // Local or remote directory with source code, defaults to "./" + // +optional + // +defaultPath="./" // Local or remote directory with source code, defaults to "./" // +optional // +defaultPath="./" @@ -124,6 +127,8 @@ func (m *HarborCli) PublishImage( registry, registryUsername string, // +optional // +default=["latest"] + // +optional + // +default=["latest"] imageTags []string, registryPassword *dagger.Secret) []string { builders := m.build(ctx) @@ -234,8 +239,8 @@ func (m *HarborCli) Test(ctx context.Context) (string, error) { WithEnvVariable("GOCACHE", "/go/build-cache"). WithMountedDirectory("/src", m.Source). WithWorkdir("/src"). - WithExec([]string{"go", "test", "-v", "./..."}) - return test.Stdout(ctx) + WithExec([]string{"go", "test", "./..."}). + Directory("/src") } // Parse the platform string into os and arch @@ -255,10 +260,13 @@ func (m *HarborCli) PublishImageAndSign( registryPassword *dagger.Secret, imageTags []string, // +optional + // +optional githubToken *dagger.Secret, // +optional + // +optional actionsIdTokenRequestToken *dagger.Secret, // +optional + // +optional actionsIdTokenRequestUrl string, ) (string, error) { @@ -282,11 +290,14 @@ func (m *HarborCli) PublishImageAndSign( // Sign signs a container image using Cosign, works also with GitHub Actions func (m *HarborCli) Sign(ctx context.Context, + // +optional // +optional githubToken *dagger.Secret, // +optional + // +optional actionsIdTokenRequestUrl string, // +optional + // +optional actionsIdTokenRequestToken *dagger.Secret, registryUsername string, registryPassword *dagger.Secret, From 0c5fc1a830912fed094fbbf42d96791432142743 Mon Sep 17 00:00:00 2001 From: Vadim Bauer Date: Thu, 14 Nov 2024 19:30:29 +0100 Subject: [PATCH 11/12] print test output to screen (#254) print test output to screen Signed-off-by: JianMinTang --- .github/workflows/default.yaml | 2 +- dagger/main.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/default.yaml b/.github/workflows/default.yaml index beba1d92..c1953237 100644 --- a/.github/workflows/default.yaml +++ b/.github/workflows/default.yaml @@ -49,7 +49,7 @@ jobs: with: version: ${{ steps.dagger_version.outputs.version }} verb: call - args: test export --path=./testResults + args: test - name: Build Binary uses: dagger/dagger-for-github@v7 diff --git a/dagger/main.go b/dagger/main.go index 009e8790..bbbd575a 100644 --- a/dagger/main.go +++ b/dagger/main.go @@ -239,8 +239,8 @@ func (m *HarborCli) Test(ctx context.Context) (string, error) { WithEnvVariable("GOCACHE", "/go/build-cache"). WithMountedDirectory("/src", m.Source). WithWorkdir("/src"). - WithExec([]string{"go", "test", "./..."}). - Directory("/src") + WithExec([]string{"go", "test", "-v", "./..."}) + return test.Stdout(ctx) } // Parse the platform string into os and arch From 92b09c886702d4a3c35eb3bcb5a08bb06b08424a Mon Sep 17 00:00:00 2001 From: JianMinTang Date: Sun, 3 Nov 2024 09:17:54 +0800 Subject: [PATCH 12/12] Support yaml output for 'registry list' Signed-off-by: JianMinTang Use gofmt to format all code Signed-off-by: JianMinTang fix: Support YAML output for additional commands Signed-off-by: JianMinTang fix: Implement a generic function to format output Signed-off-by: JianMinTang chore: fix the problem about golangci-lint Signed-off-by: JianMinTang --- dagger/main.go | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/dagger/main.go b/dagger/main.go index bbbd575a..1035123f 100644 --- a/dagger/main.go +++ b/dagger/main.go @@ -16,9 +16,6 @@ const ( ) func New( - // Local or remote directory with source code, defaults to "./" - // +optional - // +defaultPath="./" // Local or remote directory with source code, defaults to "./" // +optional // +defaultPath="./" @@ -127,8 +124,6 @@ func (m *HarborCli) PublishImage( registry, registryUsername string, // +optional // +default=["latest"] - // +optional - // +default=["latest"] imageTags []string, registryPassword *dagger.Secret) []string { builders := m.build(ctx) @@ -260,13 +255,10 @@ func (m *HarborCli) PublishImageAndSign( registryPassword *dagger.Secret, imageTags []string, // +optional - // +optional githubToken *dagger.Secret, // +optional - // +optional actionsIdTokenRequestToken *dagger.Secret, // +optional - // +optional actionsIdTokenRequestUrl string, ) (string, error) { @@ -290,14 +282,11 @@ func (m *HarborCli) PublishImageAndSign( // Sign signs a container image using Cosign, works also with GitHub Actions func (m *HarborCli) Sign(ctx context.Context, - // +optional // +optional githubToken *dagger.Secret, // +optional - // +optional actionsIdTokenRequestUrl string, // +optional - // +optional actionsIdTokenRequestToken *dagger.Secret, registryUsername string, registryPassword *dagger.Secret,