From 63000113ee4d67d2ff6151a8d1ca857d051ef650 Mon Sep 17 00:00:00 2001 From: Gabriel Adrian Samfira Date: Sat, 28 Sep 2024 18:59:23 +0000 Subject: [PATCH] Add --format command line option This change adds a --format command line option to the GARM cli. This option accepts either json or table as a value. Signed-off-by: Gabriel Adrian Samfira --- cmd/garm-cli/cmd/controller.go | 5 +++++ cmd/garm-cli/cmd/enterprise.go | 9 +++++++++ cmd/garm-cli/cmd/github_credentials.go | 9 +++++++++ cmd/garm-cli/cmd/github_endpoints.go | 9 +++++++++ cmd/garm-cli/cmd/jobs.go | 5 +++++ cmd/garm-cli/cmd/organization.go | 9 +++++++++ cmd/garm-cli/cmd/pool.go | 9 +++++++++ cmd/garm-cli/cmd/profile.go | 4 ++++ cmd/garm-cli/cmd/provider.go | 5 +++++ cmd/garm-cli/cmd/repository.go | 9 +++++++++ cmd/garm-cli/cmd/root.go | 17 ++++++++++++++++ cmd/garm-cli/cmd/runner.go | 9 +++++++++ cmd/garm-cli/common/cobra.go | 28 ++++++++++++++++++++++++++ 13 files changed, 127 insertions(+) create mode 100644 cmd/garm-cli/common/cobra.go diff --git a/cmd/garm-cli/cmd/controller.go b/cmd/garm-cli/cmd/controller.go index 708a03f3..c1326943 100644 --- a/cmd/garm-cli/cmd/controller.go +++ b/cmd/garm-cli/cmd/controller.go @@ -22,6 +22,7 @@ import ( apiClientController "github.com/cloudbase/garm/client/controller" apiClientControllerInfo "github.com/cloudbase/garm/client/controller_info" + "github.com/cloudbase/garm/cmd/garm-cli/common" "github.com/cloudbase/garm/params" ) @@ -164,6 +165,10 @@ func renderControllerInfoTable(info params.ControllerInfo) string { } func formatInfo(info params.ControllerInfo) error { + if outputFormat == common.OutputFormatJSON { + printAsJSON(info) + return nil + } fmt.Println(renderControllerInfoTable(info)) return nil } diff --git a/cmd/garm-cli/cmd/enterprise.go b/cmd/garm-cli/cmd/enterprise.go index dc9000d8..fd2f45e1 100644 --- a/cmd/garm-cli/cmd/enterprise.go +++ b/cmd/garm-cli/cmd/enterprise.go @@ -21,6 +21,7 @@ import ( "github.com/spf13/cobra" apiClientEnterprises "github.com/cloudbase/garm/client/enterprises" + "github.com/cloudbase/garm/cmd/garm-cli/common" "github.com/cloudbase/garm/params" ) @@ -200,6 +201,10 @@ func init() { } func formatEnterprises(enterprises []params.Enterprise) { + if outputFormat == common.OutputFormatJSON { + printAsJSON(enterprises) + return + } t := table.NewWriter() header := table.Row{"ID", "Name", "Endpoint", "Credentials name", "Pool Balancer Type", "Pool mgr running"} t.AppendHeader(header) @@ -211,6 +216,10 @@ func formatEnterprises(enterprises []params.Enterprise) { } func formatOneEnterprise(enterprise params.Enterprise) { + if outputFormat == common.OutputFormatJSON { + printAsJSON(enterprise) + return + } t := table.NewWriter() rowConfigAutoMerge := table.RowConfig{AutoMerge: true} header := table.Row{"Field", "Value"} diff --git a/cmd/garm-cli/cmd/github_credentials.go b/cmd/garm-cli/cmd/github_credentials.go index db2c8846..8d75e33b 100644 --- a/cmd/garm-cli/cmd/github_credentials.go +++ b/cmd/garm-cli/cmd/github_credentials.go @@ -25,6 +25,7 @@ import ( "github.com/spf13/cobra" apiClientCreds "github.com/cloudbase/garm/client/credentials" + "github.com/cloudbase/garm/cmd/garm-cli/common" "github.com/cloudbase/garm/params" ) @@ -342,6 +343,10 @@ func parseCredentialsUpdateParams() (params.UpdateGithubCredentialsParams, error } func formatGithubCredentials(creds []params.GithubCredentials) { + if outputFormat == common.OutputFormatJSON { + printAsJSON(creds) + return + } t := table.NewWriter() header := table.Row{"ID", "Name", "Description", "Base URL", "API URL", "Upload URL", "Type"} t.AppendHeader(header) @@ -353,6 +358,10 @@ func formatGithubCredentials(creds []params.GithubCredentials) { } func formatOneGithubCredential(cred params.GithubCredentials) { + if outputFormat == common.OutputFormatJSON { + printAsJSON(cred) + return + } t := table.NewWriter() header := table.Row{"Field", "Value"} t.AppendHeader(header) diff --git a/cmd/garm-cli/cmd/github_endpoints.go b/cmd/garm-cli/cmd/github_endpoints.go index b12ba2e7..c2f611e7 100644 --- a/cmd/garm-cli/cmd/github_endpoints.go +++ b/cmd/garm-cli/cmd/github_endpoints.go @@ -10,6 +10,7 @@ import ( "github.com/spf13/cobra" apiClientEndpoints "github.com/cloudbase/garm/client/endpoints" + "github.com/cloudbase/garm/cmd/garm-cli/common" "github.com/cloudbase/garm/params" ) @@ -250,6 +251,10 @@ func parseCreateParams() (params.CreateGithubEndpointParams, error) { } func formatEndpoints(endpoints params.GithubEndpoints) { + if outputFormat == common.OutputFormatJSON { + printAsJSON(endpoints) + return + } t := table.NewWriter() header := table.Row{"Name", "Base URL", "Description"} t.AppendHeader(header) @@ -261,6 +266,10 @@ func formatEndpoints(endpoints params.GithubEndpoints) { } func formatOneEndpoint(endpoint params.GithubEndpoint) { + if outputFormat == common.OutputFormatJSON { + printAsJSON(endpoint) + return + } t := table.NewWriter() header := table.Row{"Field", "Value"} t.AppendHeader(header) diff --git a/cmd/garm-cli/cmd/jobs.go b/cmd/garm-cli/cmd/jobs.go index c8505222..1ce372cb 100644 --- a/cmd/garm-cli/cmd/jobs.go +++ b/cmd/garm-cli/cmd/jobs.go @@ -23,6 +23,7 @@ import ( "github.com/spf13/cobra" apiClientJobs "github.com/cloudbase/garm/client/jobs" + "github.com/cloudbase/garm/cmd/garm-cli/common" "github.com/cloudbase/garm/params" ) @@ -57,6 +58,10 @@ var jobsListCmd = &cobra.Command{ } func formatJobs(jobs []params.Job) { + if outputFormat == common.OutputFormatJSON { + printAsJSON(jobs) + return + } t := table.NewWriter() header := table.Row{"ID", "Name", "Status", "Conclusion", "Runner Name", "Repository", "Requested Labels", "Locked by"} t.AppendHeader(header) diff --git a/cmd/garm-cli/cmd/organization.go b/cmd/garm-cli/cmd/organization.go index 4e5e5360..7b96e0fa 100644 --- a/cmd/garm-cli/cmd/organization.go +++ b/cmd/garm-cli/cmd/organization.go @@ -22,6 +22,7 @@ import ( "github.com/cloudbase/garm-provider-common/util" apiClientOrgs "github.com/cloudbase/garm/client/organizations" + "github.com/cloudbase/garm/cmd/garm-cli/common" "github.com/cloudbase/garm/params" ) @@ -340,6 +341,10 @@ func init() { } func formatOrganizations(orgs []params.Organization) { + if outputFormat == common.OutputFormatJSON { + printAsJSON(orgs) + return + } t := table.NewWriter() header := table.Row{"ID", "Name", "Endpoint", "Credentials name", "Pool Balancer Type", "Pool mgr running"} t.AppendHeader(header) @@ -351,6 +356,10 @@ func formatOrganizations(orgs []params.Organization) { } func formatOneOrganization(org params.Organization) { + if outputFormat == common.OutputFormatJSON { + printAsJSON(org) + return + } t := table.NewWriter() rowConfigAutoMerge := table.RowConfig{AutoMerge: true} header := table.Row{"Field", "Value"} diff --git a/cmd/garm-cli/cmd/pool.go b/cmd/garm-cli/cmd/pool.go index 089409a1..407f9eb9 100644 --- a/cmd/garm-cli/cmd/pool.go +++ b/cmd/garm-cli/cmd/pool.go @@ -29,6 +29,7 @@ import ( apiClientOrgs "github.com/cloudbase/garm/client/organizations" apiClientPools "github.com/cloudbase/garm/client/pools" apiClientRepos "github.com/cloudbase/garm/client/repositories" + "github.com/cloudbase/garm/cmd/garm-cli/common" "github.com/cloudbase/garm/params" ) @@ -466,6 +467,10 @@ func asRawMessage(data []byte) (json.RawMessage, error) { } func formatPools(pools []params.Pool) { + if outputFormat == common.OutputFormatJSON { + printAsJSON(pools) + return + } t := table.NewWriter() header := table.Row{"ID", "Image", "Flavor", "Tags", "Belongs to", "Level", "Enabled", "Runner Prefix", "Priority"} t.AppendHeader(header) @@ -496,6 +501,10 @@ func formatPools(pools []params.Pool) { } func formatOnePool(pool params.Pool) { + if outputFormat == common.OutputFormatJSON { + printAsJSON(pool) + return + } t := table.NewWriter() rowConfigAutoMerge := table.RowConfig{AutoMerge: true} diff --git a/cmd/garm-cli/cmd/profile.go b/cmd/garm-cli/cmd/profile.go index 70d5176e..7e3e4d5b 100644 --- a/cmd/garm-cli/cmd/profile.go +++ b/cmd/garm-cli/cmd/profile.go @@ -239,6 +239,10 @@ func init() { } func formatProfiles(profiles []config.Manager) { + if outputFormat == common.OutputFormatJSON { + printAsJSON(profiles) + return + } t := table.NewWriter() header := table.Row{"Name", "Base URL"} t.AppendHeader(header) diff --git a/cmd/garm-cli/cmd/provider.go b/cmd/garm-cli/cmd/provider.go index eef6a421..b4f05401 100644 --- a/cmd/garm-cli/cmd/provider.go +++ b/cmd/garm-cli/cmd/provider.go @@ -21,6 +21,7 @@ import ( "github.com/spf13/cobra" apiClientProviders "github.com/cloudbase/garm/client/providers" + "github.com/cloudbase/garm/cmd/garm-cli/common" "github.com/cloudbase/garm/params" ) @@ -64,6 +65,10 @@ func init() { } func formatProviders(providers []params.Provider) { + if outputFormat == common.OutputFormatJSON { + printAsJSON(providers) + return + } t := table.NewWriter() header := table.Row{"Name", "Description", "Type"} t.AppendHeader(header) diff --git a/cmd/garm-cli/cmd/repository.go b/cmd/garm-cli/cmd/repository.go index 3fa75560..9c02a021 100644 --- a/cmd/garm-cli/cmd/repository.go +++ b/cmd/garm-cli/cmd/repository.go @@ -22,6 +22,7 @@ import ( "github.com/cloudbase/garm-provider-common/util" apiClientRepos "github.com/cloudbase/garm/client/repositories" + "github.com/cloudbase/garm/cmd/garm-cli/common" "github.com/cloudbase/garm/params" ) @@ -346,6 +347,10 @@ func init() { } func formatRepositories(repos []params.Repository) { + if outputFormat == common.OutputFormatJSON { + printAsJSON(repos) + return + } t := table.NewWriter() header := table.Row{"ID", "Owner", "Name", "Endpoint", "Credentials name", "Pool Balancer Type", "Pool mgr running"} t.AppendHeader(header) @@ -357,6 +362,10 @@ func formatRepositories(repos []params.Repository) { } func formatOneRepository(repo params.Repository) { + if outputFormat == common.OutputFormatJSON { + printAsJSON(repo) + return + } t := table.NewWriter() rowConfigAutoMerge := table.RowConfig{AutoMerge: true} header := table.Row{"Field", "Value"} diff --git a/cmd/garm-cli/cmd/root.go b/cmd/garm-cli/cmd/root.go index 544911f9..eae964cd 100644 --- a/cmd/garm-cli/cmd/root.go +++ b/cmd/garm-cli/cmd/root.go @@ -15,6 +15,7 @@ package cmd import ( + "encoding/json" "fmt" "net/url" "os" @@ -25,6 +26,7 @@ import ( "github.com/spf13/cobra" apiClient "github.com/cloudbase/garm/client" + "github.com/cloudbase/garm/cmd/garm-cli/common" "github.com/cloudbase/garm/cmd/garm-cli/config" "github.com/cloudbase/garm/params" ) @@ -37,6 +39,7 @@ var ( needsInit bool debug bool poolBalancerType string + outputFormat common.OutputFormat errNeedsInitError = fmt.Errorf("please log into a garm installation first") ) @@ -51,6 +54,11 @@ var rootCmd = &cobra.Command{ // This is called by main.main(). It only needs to happen once to the rootCmd. func Execute() { rootCmd.PersistentFlags().BoolVar(&debug, "debug", false, "Enable debug on all API calls") + rootCmd.PersistentFlags().VarP(&outputFormat, "format", "f", "Output format (table, json)") + if outputFormat.String() == "" { + outputFormat = common.OutputFormatTable + } + cobra.OnInitialize(initConfig) err := rootCmd.Execute() @@ -113,3 +121,12 @@ func formatOneHookInfo(hook params.HookInfo) { }) fmt.Println(t.Render()) } + +func printAsJSON(value interface{}) { + asJs, err := json.Marshal(value) + if err != nil { + fmt.Printf("Failed to marshal value to json: %s", err) + os.Exit(1) + } + fmt.Println(string(asJs)) +} diff --git a/cmd/garm-cli/cmd/runner.go b/cmd/garm-cli/cmd/runner.go index eafdf4ef..aeb9bbf2 100644 --- a/cmd/garm-cli/cmd/runner.go +++ b/cmd/garm-cli/cmd/runner.go @@ -25,6 +25,7 @@ import ( apiClientInstances "github.com/cloudbase/garm/client/instances" apiClientOrgs "github.com/cloudbase/garm/client/organizations" apiClientRepos "github.com/cloudbase/garm/client/repositories" + "github.com/cloudbase/garm/cmd/garm-cli/common" "github.com/cloudbase/garm/params" ) @@ -222,6 +223,10 @@ func init() { } func formatInstances(param []params.Instance, detailed bool) { + if outputFormat == common.OutputFormatJSON { + printAsJSON(param) + return + } t := table.NewWriter() header := table.Row{"Nr", "Name", "Status", "Runner Status", "Pool ID"} if detailed { @@ -242,6 +247,10 @@ func formatInstances(param []params.Instance, detailed bool) { } func formatSingleInstance(instance params.Instance) { + if outputFormat == common.OutputFormatJSON { + printAsJSON(instance) + return + } t := table.NewWriter() header := table.Row{"Field", "Value"} diff --git a/cmd/garm-cli/common/cobra.go b/cmd/garm-cli/common/cobra.go new file mode 100644 index 00000000..adb13a97 --- /dev/null +++ b/cmd/garm-cli/common/cobra.go @@ -0,0 +1,28 @@ +package common + +import "fmt" + +type OutputFormat string + +const ( + OutputFormatTable OutputFormat = "table" + OutputFormatJSON OutputFormat = "json" +) + +func (o OutputFormat) String() string { + return string(o) +} + +func (o *OutputFormat) Set(value string) error { + switch value { + case "table", "json": + *o = OutputFormat(value) + default: + return fmt.Errorf("allowed formats are: json, table") + } + return nil +} + +func (o OutputFormat) Type() string { + return "string" +}