Add additional info when listing resources

This change adds a --long option to most commands and includes the
CreateAt and UpdatedAt fields in the output.

Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
This commit is contained in:
Gabriel Adrian Samfira 2025-02-10 12:45:30 +00:00
parent 719bcd05aa
commit c0245a18f7
10 changed files with 121 additions and 18 deletions

View file

@ -183,6 +183,8 @@ func init() {
enterpriseAddCmd.Flags().StringVar(&enterpriseCreds, "credentials", "", "Credentials name. See credentials list.")
enterpriseAddCmd.Flags().StringVar(&poolBalancerType, "pool-balancer-type", string(params.PoolBalancerTypeRoundRobin), "The balancing strategy to use when creating runners in pools matching requested labels.")
enterpriseListCmd.Flags().BoolVarP(&long, "long", "l", false, "Include additional info.")
enterpriseAddCmd.MarkFlagRequired("credentials") //nolint
enterpriseAddCmd.MarkFlagRequired("name") //nolint
enterpriseUpdateCmd.Flags().StringVar(&enterpriseWebhookSecret, "webhook-secret", "", "The webhook secret for this enterprise")
@ -207,9 +209,16 @@ func formatEnterprises(enterprises []params.Enterprise) {
}
t := table.NewWriter()
header := table.Row{"ID", "Name", "Endpoint", "Credentials name", "Pool Balancer Type", "Pool mgr running"}
if long {
header = append(header, "Created At", "Updated At")
}
t.AppendHeader(header)
for _, val := range enterprises {
t.AppendRow(table.Row{val.ID, val.Name, val.Endpoint.Name, val.Credentials.Name, val.GetBalancerType(), val.PoolManagerStatus.IsRunning})
row := table.Row{val.ID, val.Name, val.Endpoint.Name, val.Credentials.Name, val.GetBalancerType(), val.PoolManagerStatus.IsRunning}
if long {
row = append(row, val.CreatedAt, val.UpdatedAt)
}
t.AppendRow(row)
t.AppendSeparator()
}
fmt.Println(t.Render())
@ -225,6 +234,8 @@ func formatOneEnterprise(enterprise params.Enterprise) {
header := table.Row{"Field", "Value"}
t.AppendHeader(header)
t.AppendRow(table.Row{"ID", enterprise.ID})
t.AppendRow(table.Row{"Created At", enterprise.CreatedAt})
t.AppendRow(table.Row{"Updated At", enterprise.UpdatedAt})
t.AppendRow(table.Row{"Name", enterprise.Name})
t.AppendRow(table.Row{"Endpoint", enterprise.Endpoint.Name})
t.AppendRow(table.Row{"Pool balancer type", enterprise.GetBalancerType()})

View file

@ -223,6 +223,8 @@ func init() {
githubCredentialsUpdateCmd.Flags().Int64Var(&credentialsAppID, "app-id", 0, "If the credential is an app, the app ID")
githubCredentialsUpdateCmd.Flags().StringVar(&credentialsPrivateKeyPath, "private-key-path", "", "If the credential is an app, the path to the private key file")
githubCredentialsListCmd.Flags().BoolVarP(&long, "long", "l", false, "Include additional info.")
githubCredentialsUpdateCmd.MarkFlagsMutuallyExclusive("pat-oauth-token", "app-installation-id")
githubCredentialsUpdateCmd.MarkFlagsMutuallyExclusive("pat-oauth-token", "app-id")
githubCredentialsUpdateCmd.MarkFlagsMutuallyExclusive("pat-oauth-token", "private-key-path")
@ -349,9 +351,16 @@ func formatGithubCredentials(creds []params.GithubCredentials) {
}
t := table.NewWriter()
header := table.Row{"ID", "Name", "Description", "Base URL", "API URL", "Upload URL", "Type"}
if long {
header = append(header, "Created At", "Updated At")
}
t.AppendHeader(header)
for _, val := range creds {
t.AppendRow(table.Row{val.ID, val.Name, val.Description, val.BaseURL, val.APIBaseURL, val.UploadBaseURL, val.AuthType})
row := table.Row{val.ID, val.Name, val.Description, val.BaseURL, val.APIBaseURL, val.UploadBaseURL, val.AuthType}
if long {
row = append(row, val.CreatedAt, val.UpdatedAt)
}
t.AppendRow(row)
t.AppendSeparator()
}
fmt.Println(t.Render())
@ -367,6 +376,8 @@ func formatOneGithubCredential(cred params.GithubCredentials) {
t.AppendHeader(header)
t.AppendRow(table.Row{"ID", cred.ID})
t.AppendRow(table.Row{"Created At", cred.CreatedAt})
t.AppendRow(table.Row{"Updated At", cred.UpdatedAt})
t.AppendRow(table.Row{"Name", cred.Name})
t.AppendRow(table.Row{"Description", cred.Description})
t.AppendRow(table.Row{"Base URL", cred.BaseURL})

View file

@ -189,6 +189,8 @@ func init() {
githubEndpointCreateCmd.Flags().StringVar(&endpointAPIBaseURL, "api-base-url", "", "API Base URL of the GitHub endpoint")
githubEndpointCreateCmd.Flags().StringVar(&endpointCACertPath, "ca-cert-path", "", "CA Cert Path of the GitHub endpoint")
githubEndpointListCmd.Flags().BoolVarP(&long, "long", "l", false, "Include additional info.")
githubEndpointCreateCmd.MarkFlagRequired("name")
githubEndpointCreateCmd.MarkFlagRequired("base-url")
githubEndpointCreateCmd.MarkFlagRequired("api-base-url")
@ -257,9 +259,16 @@ func formatEndpoints(endpoints params.GithubEndpoints) {
}
t := table.NewWriter()
header := table.Row{"Name", "Base URL", "Description"}
if long {
header = append(header, "Created At", "Updated At")
}
t.AppendHeader(header)
for _, val := range endpoints {
t.AppendRow([]interface{}{val.Name, val.BaseURL, val.Description})
row := table.Row{val.Name, val.BaseURL, val.Description}
if long {
row = append(row, val.CreatedAt, val.UpdatedAt)
}
t.AppendRow(row)
t.AppendSeparator()
}
fmt.Println(t.Render())
@ -274,6 +283,9 @@ func formatOneEndpoint(endpoint params.GithubEndpoint) {
header := table.Row{"Field", "Value"}
t.AppendHeader(header)
t.AppendRow([]interface{}{"Name", endpoint.Name})
t.AppendRow([]interface{}{"Description", endpoint.Description})
t.AppendRow([]interface{}{"Created At", endpoint.CreatedAt})
t.AppendRow([]interface{}{"Updated At", endpoint.UpdatedAt})
t.AppendRow([]interface{}{"Base URL", endpoint.BaseURL})
t.AppendRow([]interface{}{"Upload URL", endpoint.UploadBaseURL})
t.AppendRow([]interface{}{"API Base URL", endpoint.APIBaseURL})

View file

@ -311,6 +311,7 @@ func init() {
orgAddCmd.Flags().BoolVar(&installOrgWebhook, "install-webhook", false, "Install the webhook as part of the add operation.")
orgAddCmd.MarkFlagsMutuallyExclusive("webhook-secret", "random-webhook-secret")
orgAddCmd.MarkFlagsOneRequired("webhook-secret", "random-webhook-secret")
orgListCmd.Flags().BoolVarP(&long, "long", "l", false, "Include additional info.")
orgAddCmd.MarkFlagRequired("credentials") //nolint
orgAddCmd.MarkFlagRequired("name") //nolint
@ -347,9 +348,16 @@ func formatOrganizations(orgs []params.Organization) {
}
t := table.NewWriter()
header := table.Row{"ID", "Name", "Endpoint", "Credentials name", "Pool Balancer Type", "Pool mgr running"}
if long {
header = append(header, "Created At", "Updated At")
}
t.AppendHeader(header)
for _, val := range orgs {
t.AppendRow(table.Row{val.ID, val.Name, val.Endpoint.Name, val.CredentialsName, val.GetBalancerType(), val.PoolManagerStatus.IsRunning})
row := table.Row{val.ID, val.Name, val.Endpoint.Name, val.CredentialsName, val.GetBalancerType(), val.PoolManagerStatus.IsRunning}
if long {
row = append(row, val.CreatedAt, val.UpdatedAt)
}
t.AppendRow(row)
t.AppendSeparator()
}
fmt.Println(t.Render())
@ -365,10 +373,14 @@ func formatOneOrganization(org params.Organization) {
header := table.Row{"Field", "Value"}
t.AppendHeader(header)
t.AppendRow(table.Row{"ID", org.ID})
t.AppendRow(table.Row{"Created At", org.CreatedAt})
t.AppendRow(table.Row{"Updated At", org.UpdatedAt})
t.AppendRow(table.Row{"Name", org.Name})
t.AppendRow(table.Row{"Endpoint", org.Endpoint.Name})
t.AppendRow(table.Row{"Pool balancer type", org.GetBalancerType()})
t.AppendRow(table.Row{"Credentials", org.CredentialsName})
t.AppendRow(table.Row{"Created at", org.CreatedAt})
t.AppendRow(table.Row{"Updated at", org.UpdatedAt})
t.AppendRow(table.Row{"Pool manager running", org.PoolManagerStatus.IsRunning})
if !org.PoolManagerStatus.IsRunning {
t.AppendRow(table.Row{"Failure reason", org.PoolManagerStatus.FailureReason})

View file

@ -386,6 +386,7 @@ func init() {
poolListCmd.Flags().StringVarP(&poolOrganization, "org", "o", "", "List all pools within this organization.")
poolListCmd.Flags().StringVarP(&poolEnterprise, "enterprise", "e", "", "List all pools within this enterprise.")
poolListCmd.Flags().BoolVarP(&poolAll, "all", "a", false, "List all pools, regardless of org or repo.")
poolListCmd.Flags().BoolVarP(&long, "long", "l", false, "Include additional info.")
poolListCmd.MarkFlagsMutuallyExclusive("repo", "org", "all", "enterprise")
poolUpdateCmd.Flags().StringVar(&poolImage, "image", "", "The provider-specific image name to use for runners in this pool.")
@ -472,7 +473,13 @@ func formatPools(pools []params.Pool) {
return
}
t := table.NewWriter()
header := table.Row{"ID", "Image", "Flavor", "Tags", "Belongs to", "Level", "Enabled", "Runner Prefix", "Priority"}
t.SetColumnConfigs([]table.ColumnConfig{
{Number: 2, WidthMax: 40},
})
header := table.Row{"ID", "Image", "Flavor", "Tags", "Belongs to", "Enabled"}
if long {
header = append(header, "Level", "Created At", "Updated at", "Runner Prefix", "Priority")
}
t.AppendHeader(header)
for _, pool := range pools {
@ -494,7 +501,11 @@ func formatPools(pools []params.Pool) {
belongsTo = pool.EnterpriseName
level = "enterprise"
}
t.AppendRow(table.Row{pool.ID, pool.Image, pool.Flavor, strings.Join(tags, " "), belongsTo, level, pool.Enabled, pool.GetRunnerPrefix(), pool.Priority})
row := table.Row{pool.ID, pool.Image, pool.Flavor, strings.Join(tags, " "), belongsTo, pool.Enabled}
if long {
row = append(row, level, pool.CreatedAt, pool.UpdatedAt, pool.GetRunnerPrefix(), pool.Priority)
}
t.AppendRow(row)
t.AppendSeparator()
}
fmt.Println(t.Render())
@ -532,6 +543,8 @@ func formatOnePool(pool params.Pool) {
t.AppendHeader(header)
t.AppendRow(table.Row{"ID", pool.ID})
t.AppendRow(table.Row{"Created At", pool.CreatedAt})
t.AppendRow(table.Row{"Updated At", pool.UpdatedAt})
t.AppendRow(table.Row{"Provider Name", pool.ProviderName})
t.AppendRow(table.Row{"Priority", pool.Priority})
t.AppendRow(table.Row{"Image", pool.Image})

View file

@ -316,6 +316,8 @@ func init() {
repoAddCmd.MarkFlagsMutuallyExclusive("webhook-secret", "random-webhook-secret")
repoAddCmd.MarkFlagsOneRequired("webhook-secret", "random-webhook-secret")
repoListCmd.Flags().BoolVarP(&long, "long", "l", false, "Include additional info.")
repoAddCmd.MarkFlagRequired("credentials") //nolint
repoAddCmd.MarkFlagRequired("owner") //nolint
repoAddCmd.MarkFlagRequired("name") //nolint
@ -353,9 +355,16 @@ func formatRepositories(repos []params.Repository) {
}
t := table.NewWriter()
header := table.Row{"ID", "Owner", "Name", "Endpoint", "Credentials name", "Pool Balancer Type", "Pool mgr running"}
if long {
header = append(header, "Created At", "Updated At")
}
t.AppendHeader(header)
for _, val := range repos {
t.AppendRow(table.Row{val.ID, val.Owner, val.Name, val.Endpoint.Name, val.CredentialsName, val.GetBalancerType(), val.PoolManagerStatus.IsRunning})
row := table.Row{val.ID, val.Owner, val.Name, val.Endpoint.Name, val.CredentialsName, val.GetBalancerType(), val.PoolManagerStatus.IsRunning}
if long {
row = append(row, val.CreatedAt, val.UpdatedAt)
}
t.AppendRow(row)
t.AppendSeparator()
}
fmt.Println(t.Render())
@ -371,6 +380,8 @@ func formatOneRepository(repo params.Repository) {
header := table.Row{"Field", "Value"}
t.AppendHeader(header)
t.AppendRow(table.Row{"ID", repo.ID})
t.AppendRow(table.Row{"Created At", repo.CreatedAt})
t.AppendRow(table.Row{"Updated At", repo.UpdatedAt})
t.AppendRow(table.Row{"Owner", repo.Owner})
t.AppendRow(table.Row{"Name", repo.Name})
t.AppendRow(table.Row{"Endpoint", repo.Endpoint.Name})

View file

@ -206,7 +206,7 @@ func init() {
runnerListCmd.Flags().StringVarP(&runnerOrganization, "org", "o", "", "List all runners from all pools within this organization.")
runnerListCmd.Flags().StringVarP(&runnerEnterprise, "enterprise", "e", "", "List all runners from all pools within this enterprise.")
runnerListCmd.Flags().BoolVarP(&runnerAll, "all", "a", false, "List all runners, regardless of org or repo.")
runnerListCmd.Flags().BoolVarP(&long, "long", "l", false, "Include information about tasks.")
runnerListCmd.Flags().BoolVarP(&long, "long", "l", false, "Include additional info.")
runnerListCmd.MarkFlagsMutuallyExclusive("repo", "org", "enterprise", "all")
runnerDeleteCmd.Flags().BoolVarP(&forceRemove, "force-remove-runner", "f", false, "Forcefully remove a runner. If set to true, GARM will ignore provider errors when removing the runner.")
@ -230,15 +230,18 @@ func formatInstances(param []params.Instance, detailed bool) {
t := table.NewWriter()
header := table.Row{"Nr", "Name", "Status", "Runner Status", "Pool ID"}
if detailed {
header = append(header, "Job Name", "Started At", "Run ID", "Repository")
header = append(header, "Created At", "Updated At", "Job Name", "Started At", "Run ID", "Repository")
}
t.AppendHeader(header)
for idx, inst := range param {
row := table.Row{idx + 1, inst.Name, inst.Status, inst.RunnerStatus, inst.PoolID}
if detailed && inst.Job != nil {
repo := fmt.Sprintf("%s/%s", inst.Job.RepositoryOwner, inst.Job.RepositoryName)
row = append(row, inst.Job.Name, inst.Job.StartedAt, inst.Job.RunID, repo)
if detailed {
row = append(row, inst.CreatedAt, inst.UpdatedAt)
if inst.Job != nil {
repo := fmt.Sprintf("%s/%s", inst.Job.RepositoryOwner, inst.Job.RepositoryName)
row = append(row, inst.Job.Name, inst.Job.StartedAt, inst.Job.RunID, repo)
}
}
t.AppendRow(row)
t.AppendSeparator()
@ -257,6 +260,8 @@ func formatSingleInstance(instance params.Instance) {
t.AppendHeader(header)
t.AppendRow(table.Row{"ID", instance.ID}, table.RowConfig{AutoMerge: false})
t.AppendRow(table.Row{"Created At", instance.CreatedAt})
t.AppendRow(table.Row{"Updated At", instance.UpdatedAt})
t.AppendRow(table.Row{"Provider ID", instance.ProviderID}, table.RowConfig{AutoMerge: false})
t.AppendRow(table.Row{"Name", instance.Name}, table.RowConfig{AutoMerge: false})
t.AppendRow(table.Row{"OS Type", instance.OSType}, table.RowConfig{AutoMerge: false})

View file

@ -55,6 +55,8 @@ func (s *sqlDatabase) sqlToCommonGithubCredentials(creds GithubCredentials) (par
UploadBaseURL: creds.Endpoint.UploadBaseURL,
CABundle: creds.Endpoint.CACertBundle,
AuthType: creds.AuthType,
CreatedAt: creds.CreatedAt,
UpdatedAt: creds.UpdatedAt,
Endpoint: ep,
CredentialsPayload: data,
}
@ -94,6 +96,8 @@ func (s *sqlDatabase) sqlToCommonGithubEndpoint(ep GithubEndpoint) (params.Githu
BaseURL: ep.BaseURL,
UploadBaseURL: ep.UploadBaseURL,
CACertBundle: ep.CACertBundle,
CreatedAt: ep.CreatedAt,
UpdatedAt: ep.UpdatedAt,
}, nil
}

View file

@ -65,6 +65,7 @@ func (s *sqlDatabase) sqlToParamsInstance(instance Instance) (params.Instance, e
MetadataURL: instance.MetadataURL,
StatusMessages: []params.StatusMessage{},
CreateAttempt: instance.CreateAttempt,
CreatedAt: instance.CreatedAt,
UpdatedAt: instance.UpdatedAt,
TokenFetched: instance.TokenFetched,
JitConfiguration: jitConfig,
@ -127,6 +128,8 @@ func (s *sqlDatabase) sqlToCommonOrganization(org Organization, detailed bool) (
WebhookSecret: string(secret),
PoolBalancerType: org.PoolBalancerType,
Endpoint: endpoint,
CreatedAt: org.CreatedAt,
UpdatedAt: org.UpdatedAt,
}
if org.CredentialsID != nil {
@ -175,6 +178,8 @@ func (s *sqlDatabase) sqlToCommonEnterprise(enterprise Enterprise, detailed bool
Pools: make([]params.Pool, len(enterprise.Pools)),
WebhookSecret: string(secret),
PoolBalancerType: enterprise.PoolBalancerType,
CreatedAt: enterprise.CreatedAt,
UpdatedAt: enterprise.UpdatedAt,
Endpoint: endpoint,
}
@ -224,6 +229,8 @@ func (s *sqlDatabase) sqlToCommonPool(pool Pool) (params.Pool, error) {
ExtraSpecs: json.RawMessage(pool.ExtraSpecs),
GitHubRunnerGroup: pool.GitHubRunnerGroup,
Priority: pool.Priority,
CreatedAt: pool.CreatedAt,
UpdatedAt: pool.UpdatedAt,
}
if pool.RepoID != nil {
@ -285,6 +292,8 @@ func (s *sqlDatabase) sqlToCommonRepository(repo Repository, detailed bool) (par
Pools: make([]params.Pool, len(repo.Pools)),
WebhookSecret: string(secret),
PoolBalancerType: repo.PoolBalancerType,
CreatedAt: repo.CreatedAt,
UpdatedAt: repo.UpdatedAt,
Endpoint: endpoint,
}

View file

@ -186,6 +186,9 @@ type Instance struct {
// up.
StatusMessages []StatusMessage `json:"status_messages,omitempty"`
// CreatedAt is the timestamp of the creation of this runner.
CreatedAt time.Time `json:"created_at,omitempty"`
// UpdatedAt is the timestamp of the last update to this runner.
UpdatedAt time.Time `json:"updated_at,omitempty"`
@ -305,6 +308,8 @@ type Pool struct {
EnterpriseID string `json:"enterprise_id,omitempty"`
EnterpriseName string `json:"enterprise_name,omitempty"`
RunnerBootstrapTimeout uint `json:"runner_bootstrap_timeout,omitempty"`
CreatedAt time.Time `json:"created_at,omitempty"`
UpdatedAt time.Time `json:"updated_at,omitempty"`
// ExtraSpecs is an opaque raw json that gets sent to the provider
// as part of the bootstrap params for instances. It can contain
// any kind of data needed by providers. The contents of this field means
@ -396,6 +401,8 @@ type Repository struct {
PoolManagerStatus PoolManagerStatus `json:"pool_manager_status,omitempty"`
PoolBalancerType PoolBalancerType `json:"pool_balancing_type,omitempty"`
Endpoint GithubEndpoint `json:"endpoint,omitempty"`
CreatedAt time.Time `json:"created_at,omitempty"`
UpdatedAt time.Time `json:"updated_at,omitempty"`
// Do not serialize sensitive info.
WebhookSecret string `json:"-"`
}
@ -450,6 +457,8 @@ type Organization struct {
PoolManagerStatus PoolManagerStatus `json:"pool_manager_status,omitempty"`
PoolBalancerType PoolBalancerType `json:"pool_balancing_type,omitempty"`
Endpoint GithubEndpoint `json:"endpoint,omitempty"`
CreatedAt time.Time `json:"created_at,omitempty"`
UpdatedAt time.Time `json:"updated_at,omitempty"`
// Do not serialize sensitive info.
WebhookSecret string `json:"-"`
}
@ -499,6 +508,8 @@ type Enterprise struct {
PoolManagerStatus PoolManagerStatus `json:"pool_manager_status,omitempty"`
PoolBalancerType PoolBalancerType `json:"pool_balancing_type,omitempty"`
Endpoint GithubEndpoint `json:"endpoint,omitempty"`
CreatedAt time.Time `json:"created_at,omitempty"`
UpdatedAt time.Time `json:"updated_at,omitempty"`
// Do not serialize sensitive info.
WebhookSecret string `json:"-"`
}
@ -614,6 +625,8 @@ type GithubCredentials struct {
Organizations []Organization `json:"organizations,omitempty"`
Enterprises []Enterprise `json:"enterprises,omitempty"`
Endpoint GithubEndpoint `json:"endpoint,omitempty"`
CreatedAt time.Time `json:"created_at,omitempty"`
UpdatedAt time.Time `json:"updated_at,omitempty"`
// Do not serialize sensitive info.
CredentialsPayload []byte `json:"-"`
@ -856,12 +869,14 @@ func (g GithubEntity) String() string {
type GithubEndpoints []GithubEndpoint
type GithubEndpoint struct {
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
APIBaseURL string `json:"api_base_url,omitempty"`
UploadBaseURL string `json:"upload_base_url,omitempty"`
BaseURL string `json:"base_url,omitempty"`
CACertBundle []byte `json:"ca_cert_bundle,omitempty"`
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
APIBaseURL string `json:"api_base_url,omitempty"`
UploadBaseURL string `json:"upload_base_url,omitempty"`
BaseURL string `json:"base_url,omitempty"`
CACertBundle []byte `json:"ca_cert_bundle,omitempty"`
CreatedAt time.Time `json:"created_at,omitempty"`
UpdatedAt time.Time `json:"updated_at,omitempty"`
Credentials []GithubCredentials `json:"credentials,omitempty"`
}