From 00f7a43727e33d2b9d64fb9493099e9c601139e7 Mon Sep 17 00:00:00 2001 From: Huy Nguyen Date: Thu, 7 Aug 2025 16:16:33 +1000 Subject: [PATCH 1/6] feat: implement -f output format support json,table,basic for deployment-target view --- .../worker/listening-tentacle/view/view.go | 2 +- pkg/cmd/worker/polling-tentacle/view/view.go | 2 +- pkg/cmd/worker/shared/view.go | 5 +- pkg/cmd/worker/ssh/view/view.go | 2 +- pkg/cmd/worker/view/view.go | 177 +++++++++++++++++- 5 files changed, 174 insertions(+), 14 deletions(-) diff --git a/pkg/cmd/worker/listening-tentacle/view/view.go b/pkg/cmd/worker/listening-tentacle/view/view.go index 2b1c72b2..bee24736 100644 --- a/pkg/cmd/worker/listening-tentacle/view/view.go +++ b/pkg/cmd/worker/listening-tentacle/view/view.go @@ -25,7 +25,7 @@ func NewCmdView(f factory.Factory) *cobra.Command { $ %[1]s worker listening-tentacle view Machines-100 `, constants.ExecutableName), RunE: func(c *cobra.Command, args []string) error { - opts := shared.NewViewOptions(flags, cmd.NewDependencies(f, c), args) + opts := shared.NewViewOptions(flags, cmd.NewDependencies(f, c), args, c) return ViewRun(opts) }, } diff --git a/pkg/cmd/worker/polling-tentacle/view/view.go b/pkg/cmd/worker/polling-tentacle/view/view.go index 224391ba..0474bd06 100644 --- a/pkg/cmd/worker/polling-tentacle/view/view.go +++ b/pkg/cmd/worker/polling-tentacle/view/view.go @@ -25,7 +25,7 @@ func NewCmdView(f factory.Factory) *cobra.Command { $ %[1]s worker polling-tentacle view Machines-100 `, constants.ExecutableName), RunE: func(c *cobra.Command, args []string) error { - opts := shared.NewViewOptions(flags, cmd.NewDependencies(f, c), args) + opts := shared.NewViewOptions(flags, cmd.NewDependencies(f, c), args, c) return ViewRun(opts) }, } diff --git a/pkg/cmd/worker/shared/view.go b/pkg/cmd/worker/shared/view.go index 5364e14e..e754afe1 100644 --- a/pkg/cmd/worker/shared/view.go +++ b/pkg/cmd/worker/shared/view.go @@ -6,6 +6,7 @@ import ( "github.com/OctopusDeploy/cli/pkg/machinescommon" "github.com/OctopusDeploy/cli/pkg/output" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/machines" + "github.com/spf13/cobra" ) type ContributeEndpointCallback func(opts *ViewOptions, endpoint machines.IEndpoint) ([]*output.DataRow, error) @@ -18,6 +19,7 @@ type ViewOptions struct { *cmd.Dependencies IdOrName string *ViewFlags + Command *cobra.Command } func NewViewFlags() *ViewFlags { @@ -26,11 +28,12 @@ func NewViewFlags() *ViewFlags { } } -func NewViewOptions(viewFlags *ViewFlags, dependencies *cmd.Dependencies, args []string) *ViewOptions { +func NewViewOptions(viewFlags *ViewFlags, dependencies *cmd.Dependencies, args []string, command *cobra.Command) *ViewOptions { return &ViewOptions{ ViewFlags: viewFlags, Dependencies: dependencies, IdOrName: args[0], + Command: command, } } diff --git a/pkg/cmd/worker/ssh/view/view.go b/pkg/cmd/worker/ssh/view/view.go index 46418dc6..1dc93021 100644 --- a/pkg/cmd/worker/ssh/view/view.go +++ b/pkg/cmd/worker/ssh/view/view.go @@ -25,7 +25,7 @@ func NewCmdView(f factory.Factory) *cobra.Command { $ %[1]s worker ssh view Machines-100 `, constants.ExecutableName), RunE: func(c *cobra.Command, args []string) error { - opts := shared.NewViewOptions(flags, cmd.NewDependencies(f, c), args) + opts := shared.NewViewOptions(flags, cmd.NewDependencies(f, c), args, c) return ViewRun(opts) }, } diff --git a/pkg/cmd/worker/view/view.go b/pkg/cmd/worker/view/view.go index eaecd317..f9eb55d5 100644 --- a/pkg/cmd/worker/view/view.go +++ b/pkg/cmd/worker/view/view.go @@ -2,17 +2,18 @@ package view import ( "fmt" + "strings" "github.com/MakeNowJust/heredoc/v2" "github.com/OctopusDeploy/cli/pkg/cmd" - listeningTentacle "github.com/OctopusDeploy/cli/pkg/cmd/worker/listening-tentacle/view" - pollingTentacle "github.com/OctopusDeploy/cli/pkg/cmd/worker/polling-tentacle/view" "github.com/OctopusDeploy/cli/pkg/cmd/worker/shared" - ssh "github.com/OctopusDeploy/cli/pkg/cmd/worker/ssh/view" "github.com/OctopusDeploy/cli/pkg/constants" "github.com/OctopusDeploy/cli/pkg/factory" "github.com/OctopusDeploy/cli/pkg/machinescommon" + "github.com/OctopusDeploy/cli/pkg/output" "github.com/OctopusDeploy/cli/pkg/usage" + "github.com/OctopusDeploy/cli/pkg/util" + "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/machines" "github.com/spf13/cobra" ) @@ -20,7 +21,7 @@ func NewCmdView(f factory.Factory) *cobra.Command { flags := shared.NewViewFlags() cmd := &cobra.Command{ Args: usage.ExactArgs(1), - Use: "view { | }", + Use: "view { | }", Short: "View a worker", Long: "View a worker in Octopus Deploy", Example: heredoc.Docf(` @@ -28,7 +29,7 @@ func NewCmdView(f factory.Factory) *cobra.Command { $ %[1]s worker view 'worker' `, constants.ExecutableName), RunE: func(c *cobra.Command, args []string) error { - return ViewRun(shared.NewViewOptions(flags, cmd.NewDependencies(f, c), args)) + return ViewRun(shared.NewViewOptions(flags, cmd.NewDependencies(f, c), args, c)) }, } @@ -43,14 +44,170 @@ func ViewRun(opts *shared.ViewOptions) error { return err } - switch worker.Endpoint.GetCommunicationStyle() { + // Use basic format as default for worker view when no -f flag is specified + if !opts.Command.Flags().Changed(constants.FlagOutputFormat) { + opts.Command.Flags().Set(constants.FlagOutputFormat, constants.OutputFormatBasic) + } + + return output.PrintResource(worker, opts.Command, output.Mappers[*machines.Worker]{ + Json: func(w *machines.Worker) any { + return getWorkerAsJson(opts, w) + }, + Table: output.TableDefinition[*machines.Worker]{ + Header: []string{"NAME", "TYPE", "HEALTH", "STATUS", "WORKER POOLS", "ENDPOINT DETAILS"}, + Row: func(w *machines.Worker) []string { + return getWorkerAsTableRow(opts, w) + }, + }, + Basic: func(w *machines.Worker) string { + return getWorkerAsBasic(opts, w) + }, + }) +} + +type WorkerAsJson struct { + Id string `json:"Id"` + Name string `json:"Name"` + HealthStatus string `json:"HealthStatus"` + StatusSummary string `json:"StatusSummary"` + CommunicationStyle string `json:"CommunicationStyle"` + WorkerPools []string `json:"WorkerPools"` + EndpointDetails map[string]string `json:"EndpointDetails"` + WebUrl string `json:"WebUrl"` +} + +func getWorkerAsJson(opts *shared.ViewOptions, worker *machines.Worker) WorkerAsJson { + workerPoolMap, _ := shared.GetWorkerPoolMap(opts) + workerPoolNames := resolveValues(worker.WorkerPoolIDs, workerPoolMap) + + endpointDetails := getEndpointDetails(worker) + + return WorkerAsJson{ + Id: worker.GetID(), + Name: worker.Name, + HealthStatus: getHealthStatusFormatted(worker.HealthStatus), + StatusSummary: worker.StatusSummary, + CommunicationStyle: worker.Endpoint.GetCommunicationStyle(), + WorkerPools: workerPoolNames, + EndpointDetails: endpointDetails, + WebUrl: util.GenerateWebURL(opts.Host, worker.SpaceID, fmt.Sprintf("infrastructure/workers/%s/settings", worker.GetID())), + } +} + +func getWorkerAsTableRow(opts *shared.ViewOptions, worker *machines.Worker) []string { + workerPoolMap, _ := shared.GetWorkerPoolMap(opts) + workerPoolNames := resolveValues(worker.WorkerPoolIDs, workerPoolMap) + + endpointDetails := getEndpointDetails(worker) + endpointDetailsStr := formatEndpointDetailsForTable(endpointDetails) + + return []string{ + worker.Name, + getWorkerTypeDisplayName(worker.Endpoint.GetCommunicationStyle()), + getHealthStatusFormatted(worker.HealthStatus), + worker.StatusSummary, + strings.Join(workerPoolNames, ", "), + endpointDetailsStr, + } +} + +func getWorkerAsBasic(opts *shared.ViewOptions, worker *machines.Worker) string { + var result strings.Builder + + result.WriteString(fmt.Sprintf("%s %s\n", output.Bold(worker.Name), output.Dimf("(%s)", worker.GetID()))) + result.WriteString(fmt.Sprintf("Health status: %s\n", getHealthStatusFormatted(worker.HealthStatus))) + result.WriteString(fmt.Sprintf("Current status: %s\n", worker.StatusSummary)) + result.WriteString(fmt.Sprintf("Communication style: %s\n", getWorkerTypeDisplayName(worker.Endpoint.GetCommunicationStyle()))) + + workerPoolMap, _ := shared.GetWorkerPoolMap(opts) + workerPoolNames := resolveValues(worker.WorkerPoolIDs, workerPoolMap) + result.WriteString(fmt.Sprintf("Worker Pools: %s\n", output.FormatAsList(workerPoolNames))) + + // Add endpoint-specific details + endpointDetails := getEndpointDetails(worker) + for key, value := range endpointDetails { + result.WriteString(fmt.Sprintf("%s: %s\n", key, value)) + } + + // Web URL + url := util.GenerateWebURL(opts.Host, worker.SpaceID, fmt.Sprintf("infrastructure/workers/%s/settings", worker.GetID())) + result.WriteString(fmt.Sprintf("\nView this worker in Octopus Deploy: %s\n", output.Blue(url))) + + // Handle web flag + if opts.WebFlags != nil && opts.WebFlags.Web.Value { + machinescommon.DoWebForWorkers(worker, opts.Dependencies, opts.WebFlags, getWorkerTypeDisplayName(worker.Endpoint.GetCommunicationStyle())) + } + + return result.String() +} + +func getHealthStatusFormatted(status string) string { + switch status { + case "Healthy": + return output.Green(status) + case "Unhealthy": + return output.Red(status) + case "HasWarnings": + return output.Yellow("Has Warnings") + case "Unavailable": + return output.Dim(status) + default: + return status + } +} + +func getWorkerTypeDisplayName(communicationStyle string) string { + switch communicationStyle { case "TentaclePassive": - return listeningTentacle.ViewRun(opts) + return "Listening Tentacle" case "TentacleActive": - return pollingTentacle.ViewRun(opts) + return "Polling Tentacle" case "Ssh": - return ssh.ViewRun(opts) + return "SSH" + default: + return communicationStyle } +} - return fmt.Errorf("unsupported worker '%s'", worker.Endpoint.GetCommunicationStyle()) +func getEndpointDetails(worker *machines.Worker) map[string]string { + details := make(map[string]string) + + switch endpoint := worker.Endpoint.(type) { + case *machines.ListeningTentacleEndpoint: + details["URI"] = endpoint.URI.String() + if endpoint.TentacleVersionDetails != nil { + details["Tentacle version"] = endpoint.TentacleVersionDetails.Version + } + case *machines.PollingTentacleEndpoint: + if endpoint.TentacleVersionDetails != nil { + details["Tentacle version"] = endpoint.TentacleVersionDetails.Version + } + case *machines.SSHEndpoint: + details["URI"] = endpoint.URI.String() + if endpoint.DotNetCorePlatform != "" { + details["Platform"] = endpoint.DotNetCorePlatform + } + } + + return details +} + +func formatEndpointDetailsForTable(details map[string]string) string { + var parts []string + for key, value := range details { + parts = append(parts, fmt.Sprintf("%s: %s", key, value)) + } + return strings.Join(parts, "; ") +} + +func resolveValues(keys []string, lookup map[string]string) []string { + var result []string + for _, key := range keys { + if value, exists := lookup[key]; exists { + result = append(result, value) + } else { + result = append(result, key) + } + } + return result } From 3531a3c866d2d206b9d66be9618b574c42b9a579 Mon Sep 17 00:00:00 2001 From: Huy Nguyen Date: Thu, 7 Aug 2025 16:57:35 +1000 Subject: [PATCH 2/6] feat: implement output-format (-f) parameter for worker-pool view --- pkg/cmd/workerpool/dynamic/view/view.go | 2 +- pkg/cmd/workerpool/shared/view.go | 5 +- pkg/cmd/workerpool/static/view/view.go | 2 +- pkg/cmd/workerpool/view/view.go | 216 ++++++++++++++++++++++-- 4 files changed, 211 insertions(+), 14 deletions(-) diff --git a/pkg/cmd/workerpool/dynamic/view/view.go b/pkg/cmd/workerpool/dynamic/view/view.go index 01cf123a..3edd20e1 100644 --- a/pkg/cmd/workerpool/dynamic/view/view.go +++ b/pkg/cmd/workerpool/dynamic/view/view.go @@ -25,7 +25,7 @@ func NewCmdView(f factory.Factory) *cobra.Command { $ %[1]s worker-pool dynamic view 'Hosted Workers' `, constants.ExecutableName), RunE: func(c *cobra.Command, args []string) error { - return ViewRun(shared.NewViewOptions(flags, cmd.NewDependencies(f, c), args)) + return ViewRun(shared.NewViewOptions(flags, cmd.NewDependencies(f, c), args, c)) }, } diff --git a/pkg/cmd/workerpool/shared/view.go b/pkg/cmd/workerpool/shared/view.go index 7b1d58c9..d949edfb 100644 --- a/pkg/cmd/workerpool/shared/view.go +++ b/pkg/cmd/workerpool/shared/view.go @@ -6,6 +6,7 @@ import ( "github.com/OctopusDeploy/cli/pkg/machinescommon" "github.com/OctopusDeploy/cli/pkg/output" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/workerpools" + "github.com/spf13/cobra" ) type ContributeDetailsCallback func(opts *ViewOptions, workerPool workerpools.IWorkerPool) ([]*output.DataRow, error) @@ -18,6 +19,7 @@ type ViewOptions struct { *cmd.Dependencies IdOrName string *ViewFlags + Command *cobra.Command } func NewViewFlags() *ViewFlags { @@ -26,11 +28,12 @@ func NewViewFlags() *ViewFlags { } } -func NewViewOptions(viewFlags *ViewFlags, dependencies *cmd.Dependencies, args []string) *ViewOptions { +func NewViewOptions(viewFlags *ViewFlags, dependencies *cmd.Dependencies, args []string, command *cobra.Command) *ViewOptions { return &ViewOptions{ ViewFlags: viewFlags, Dependencies: dependencies, IdOrName: args[0], + Command: command, } } diff --git a/pkg/cmd/workerpool/static/view/view.go b/pkg/cmd/workerpool/static/view/view.go index c84733a2..7552c960 100644 --- a/pkg/cmd/workerpool/static/view/view.go +++ b/pkg/cmd/workerpool/static/view/view.go @@ -28,7 +28,7 @@ func NewCmdView(f factory.Factory) *cobra.Command { $ %[1]s worker-pool static view 'windows workers' `, constants.ExecutableName), RunE: func(c *cobra.Command, args []string) error { - return ViewRun(shared.NewViewOptions(flags, cmd.NewDependencies(f, c), args)) + return ViewRun(shared.NewViewOptions(flags, cmd.NewDependencies(f, c), args, c)) }, } diff --git a/pkg/cmd/workerpool/view/view.go b/pkg/cmd/workerpool/view/view.go index a98d7614..d8ff8794 100644 --- a/pkg/cmd/workerpool/view/view.go +++ b/pkg/cmd/workerpool/view/view.go @@ -2,17 +2,19 @@ package view import ( "fmt" - dynamicPool "github.com/OctopusDeploy/cli/pkg/cmd/workerpool/dynamic/view" - "github.com/OctopusDeploy/cli/pkg/cmd/workerpool/shared" - staticPool "github.com/OctopusDeploy/cli/pkg/cmd/workerpool/static/view" - "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/workerpools" + "strings" "github.com/MakeNowJust/heredoc/v2" "github.com/OctopusDeploy/cli/pkg/cmd" + "github.com/OctopusDeploy/cli/pkg/cmd/workerpool/shared" "github.com/OctopusDeploy/cli/pkg/constants" "github.com/OctopusDeploy/cli/pkg/factory" "github.com/OctopusDeploy/cli/pkg/machinescommon" + "github.com/OctopusDeploy/cli/pkg/output" "github.com/OctopusDeploy/cli/pkg/usage" + "github.com/OctopusDeploy/cli/pkg/util" + "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/machines" + "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/workerpools" "github.com/spf13/cobra" ) @@ -28,7 +30,7 @@ func NewCmdView(f factory.Factory) *cobra.Command { $ %[1]s worker-pool view 'linux workers' `, constants.ExecutableName), RunE: func(c *cobra.Command, args []string) error { - return ViewRun(shared.NewViewOptions(flags, cmd.NewDependencies(f, c), args)) + return ViewRun(shared.NewViewOptions(flags, cmd.NewDependencies(f, c), args, c)) }, } @@ -43,12 +45,204 @@ func ViewRun(opts *shared.ViewOptions) error { return err } - switch workerPool.GetWorkerPoolType() { - case workerpools.WorkerPoolTypeDynamic: - return dynamicPool.ViewRun(opts) - case workerpools.WorkerPoolTypeStatic: - return staticPool.ViewRun(opts) + // Use basic format as default for worker pool view when no -f flag is specified + if !opts.Command.Flags().Changed(constants.FlagOutputFormat) { + opts.Command.Flags().Set(constants.FlagOutputFormat, constants.OutputFormatBasic) + } + + return output.PrintResource(workerPool, opts.Command, output.Mappers[workerpools.IWorkerPool]{ + Json: func(wp workerpools.IWorkerPool) any { + return getWorkerPoolAsJson(opts, wp) + }, + Table: output.TableDefinition[workerpools.IWorkerPool]{ + Header: []string{"NAME", "TYPE", "DEFAULT", "WORKERS", "HEALTHY", "UNHEALTHY"}, + Row: func(wp workerpools.IWorkerPool) []string { + return getWorkerPoolAsTableRow(opts, wp) + }, + }, + Basic: func(wp workerpools.IWorkerPool) string { + return getWorkerPoolAsBasic(opts, wp) + }, + }) +} + +type WorkerPoolAsJson struct { + Id string `json:"Id"` + Name string `json:"Name"` + WorkerPoolType string `json:"WorkerPoolType"` + IsDefault bool `json:"IsDefault"` + Workers WorkerStats `json:"Workers"` + WorkerPoolDetails map[string]string `json:"WorkerPoolDetails"` + WebUrl string `json:"WebUrl"` +} + +type WorkerStats struct { + Total int `json:"Total"` + Healthy int `json:"Healthy"` + HasWarnings int `json:"HasWarnings"` + Unhealthy int `json:"Unhealthy"` + Unavailable int `json:"Unavailable"` + Disabled int `json:"Disabled"` + SSH int `json:"SSH"` + ListeningTentacle int `json:"ListeningTentacle"` + PollingTentacle int `json:"PollingTentacle"` +} + +func getWorkerPoolAsJson(opts *shared.ViewOptions, workerPool workerpools.IWorkerPool) WorkerPoolAsJson { + workers, _ := getWorkers(opts, workerPool) + workerStats := calculateWorkerStats(workers) + + workerPoolDetails := getWorkerPoolDetails(workerPool) + + return WorkerPoolAsJson{ + Id: workerPool.GetID(), + Name: workerPool.GetName(), + WorkerPoolType: getWorkerPoolTypeDescription(workerPool.GetWorkerPoolType()), + IsDefault: workerPool.GetIsDefault(), + Workers: workerStats, + WorkerPoolDetails: workerPoolDetails, + WebUrl: util.GenerateWebURL(opts.Host, workerPool.GetSpaceID(), fmt.Sprintf("infrastructure/workerpools/%s", workerPool.GetID())), + } +} + +func getWorkerPoolAsTableRow(opts *shared.ViewOptions, workerPool workerpools.IWorkerPool) []string { + workers, _ := getWorkers(opts, workerPool) + workerStats := calculateWorkerStats(workers) + + defaultStatus := "" + if workerPool.GetIsDefault() { + defaultStatus = output.Green("Yes") + } else { + defaultStatus = "No" + } + + return []string{ + output.Bold(workerPool.GetName()), + getWorkerPoolTypeDescription(workerPool.GetWorkerPoolType()), + defaultStatus, + fmt.Sprintf("%d", workerStats.Total), + output.Greenf("%d", workerStats.Healthy), + output.Redf("%d", workerStats.Unhealthy+workerStats.Unavailable), } +} - return fmt.Errorf("unsupported worker pool '%s'", workerPool.GetWorkerPoolType()) +func getWorkerPoolAsBasic(opts *shared.ViewOptions, workerPool workerpools.IWorkerPool) string { + var result strings.Builder + + // Header + result.WriteString(fmt.Sprintf("%s %s\n", output.Bold(workerPool.GetName()), output.Dimf("(%s)", workerPool.GetID()))) + result.WriteString(fmt.Sprintf("Worker Pool Type: %s\n", getWorkerPoolTypeDescription(workerPool.GetWorkerPoolType()))) + + if workerPool.GetIsDefault() { + result.WriteString(fmt.Sprintf("Default: %s\n", output.Green("Yes"))) + } + + // Worker statistics + workers, _ := getWorkers(opts, workerPool) + workerStats := calculateWorkerStats(workers) + + result.WriteString(fmt.Sprintf("Total workers: %d\n", workerStats.Total)) + if workerStats.Disabled > 0 { + result.WriteString(fmt.Sprintf("Disabled workers: %s\n", output.Dimf("%d", workerStats.Disabled))) + } + if workerStats.Healthy > 0 { + result.WriteString(fmt.Sprintf("Healthy workers: %s\n", output.Greenf("%d", workerStats.Healthy))) + } + if workerStats.HasWarnings > 0 { + result.WriteString(fmt.Sprintf("Has Warnings workers: %s\n", output.Yellowf("%d", workerStats.HasWarnings))) + } + if workerStats.Unhealthy > 0 { + result.WriteString(fmt.Sprintf("Unhealthy workers: %s\n", output.Redf("%d", workerStats.Unhealthy))) + } + if workerStats.Unavailable > 0 { + result.WriteString(fmt.Sprintf("Unavailable workers: %s\n", output.Redf("%d", workerStats.Unavailable))) + } + + // Worker type breakdown + if workerStats.SSH > 0 { + result.WriteString(fmt.Sprintf("SSH workers: %d\n", workerStats.SSH)) + } + if workerStats.ListeningTentacle > 0 { + result.WriteString(fmt.Sprintf("Listening Tentacle workers: %d\n", workerStats.ListeningTentacle)) + } + if workerStats.PollingTentacle > 0 { + result.WriteString(fmt.Sprintf("Polling Tentacle workers: %d\n", workerStats.PollingTentacle)) + } + + // Worker pool specific details + workerPoolDetails := getWorkerPoolDetails(workerPool) + for key, value := range workerPoolDetails { + result.WriteString(fmt.Sprintf("%s: %s\n", key, value)) + } + + // Web URL + url := util.GenerateWebURL(opts.Host, workerPool.GetSpaceID(), fmt.Sprintf("infrastructure/workerpools/%s", workerPool.GetID())) + result.WriteString(fmt.Sprintf("\nView this worker pool in Octopus Deploy: %s\n", output.Blue(url))) + + // Handle web flag + if opts.WebFlags != nil && opts.WebFlags.Web.Value { + machinescommon.DoWebForWorkerPools(workerPool, opts.Dependencies, opts.WebFlags) + } + + return result.String() +} + +func getWorkers(opts *shared.ViewOptions, workerPool workerpools.IWorkerPool) ([]*machines.Worker, error) { + if workerPool.GetWorkerPoolType() == workerpools.WorkerPoolTypeStatic { + return opts.Client.WorkerPools.GetWorkers(workerPool) + } + // Dynamic worker pools don't have static workers + return []*machines.Worker{}, nil +} + +func calculateWorkerStats(workers []*machines.Worker) WorkerStats { + stats := WorkerStats{} + + for _, worker := range workers { + stats.Total++ + + if worker.IsDisabled { + stats.Disabled++ + } + + switch worker.HealthStatus { + case "Healthy": + stats.Healthy++ + case "HasWarnings": + stats.HasWarnings++ + case "Unhealthy": + stats.Unhealthy++ + case "Unavailable": + stats.Unavailable++ + } + + switch worker.Endpoint.GetCommunicationStyle() { + case "Ssh": + stats.SSH++ + case "TentaclePassive": + stats.ListeningTentacle++ + case "TentacleActive": + stats.PollingTentacle++ + } + } + + return stats +} + +func getWorkerPoolDetails(workerPool workerpools.IWorkerPool) map[string]string { + details := make(map[string]string) + + if workerPool.GetWorkerPoolType() == workerpools.WorkerPoolTypeDynamic { + dynamicPool := workerPool.(*workerpools.DynamicWorkerPool) + details["Worker Type"] = string(dynamicPool.WorkerType) + } + + return details +} + +func getWorkerPoolTypeDescription(poolType workerpools.WorkerPoolType) string { + if poolType == workerpools.WorkerPoolTypeDynamic { + return "Dynamic" + } + return "Static" } From c4b91d83edd715c276bc9ff45e422a3657658fbf Mon Sep 17 00:00:00 2001 From: Huy Nguyen Date: Thu, 7 Aug 2025 17:14:58 +1000 Subject: [PATCH 3/6] switch back to default table view --- pkg/cmd/worker/view/view.go | 47 +++++++++++++++------------------ pkg/cmd/workerpool/view/view.go | 5 ---- 2 files changed, 21 insertions(+), 31 deletions(-) diff --git a/pkg/cmd/worker/view/view.go b/pkg/cmd/worker/view/view.go index f9eb55d5..6898a31a 100644 --- a/pkg/cmd/worker/view/view.go +++ b/pkg/cmd/worker/view/view.go @@ -21,7 +21,7 @@ func NewCmdView(f factory.Factory) *cobra.Command { flags := shared.NewViewFlags() cmd := &cobra.Command{ Args: usage.ExactArgs(1), - Use: "view { | }", + Use: "view { | }", Short: "View a worker", Long: "View a worker in Octopus Deploy", Example: heredoc.Docf(` @@ -44,11 +44,6 @@ func ViewRun(opts *shared.ViewOptions) error { return err } - // Use basic format as default for worker view when no -f flag is specified - if !opts.Command.Flags().Changed(constants.FlagOutputFormat) { - opts.Command.Flags().Set(constants.FlagOutputFormat, constants.OutputFormatBasic) - } - return output.PrintResource(worker, opts.Command, output.Mappers[*machines.Worker]{ Json: func(w *machines.Worker) any { return getWorkerAsJson(opts, w) @@ -66,22 +61,22 @@ func ViewRun(opts *shared.ViewOptions) error { } type WorkerAsJson struct { - Id string `json:"Id"` - Name string `json:"Name"` - HealthStatus string `json:"HealthStatus"` - StatusSummary string `json:"StatusSummary"` - CommunicationStyle string `json:"CommunicationStyle"` - WorkerPools []string `json:"WorkerPools"` - EndpointDetails map[string]string `json:"EndpointDetails"` - WebUrl string `json:"WebUrl"` + Id string `json:"Id"` + Name string `json:"Name"` + HealthStatus string `json:"HealthStatus"` + StatusSummary string `json:"StatusSummary"` + CommunicationStyle string `json:"CommunicationStyle"` + WorkerPools []string `json:"WorkerPools"` + EndpointDetails map[string]string `json:"EndpointDetails"` + WebUrl string `json:"WebUrl"` } func getWorkerAsJson(opts *shared.ViewOptions, worker *machines.Worker) WorkerAsJson { workerPoolMap, _ := shared.GetWorkerPoolMap(opts) workerPoolNames := resolveValues(worker.WorkerPoolIDs, workerPoolMap) - + endpointDetails := getEndpointDetails(worker) - + return WorkerAsJson{ Id: worker.GetID(), Name: worker.Name, @@ -97,10 +92,10 @@ func getWorkerAsJson(opts *shared.ViewOptions, worker *machines.Worker) WorkerAs func getWorkerAsTableRow(opts *shared.ViewOptions, worker *machines.Worker) []string { workerPoolMap, _ := shared.GetWorkerPoolMap(opts) workerPoolNames := resolveValues(worker.WorkerPoolIDs, workerPoolMap) - + endpointDetails := getEndpointDetails(worker) endpointDetailsStr := formatEndpointDetailsForTable(endpointDetails) - + return []string{ worker.Name, getWorkerTypeDisplayName(worker.Endpoint.GetCommunicationStyle()), @@ -113,31 +108,31 @@ func getWorkerAsTableRow(opts *shared.ViewOptions, worker *machines.Worker) []st func getWorkerAsBasic(opts *shared.ViewOptions, worker *machines.Worker) string { var result strings.Builder - + result.WriteString(fmt.Sprintf("%s %s\n", output.Bold(worker.Name), output.Dimf("(%s)", worker.GetID()))) result.WriteString(fmt.Sprintf("Health status: %s\n", getHealthStatusFormatted(worker.HealthStatus))) result.WriteString(fmt.Sprintf("Current status: %s\n", worker.StatusSummary)) result.WriteString(fmt.Sprintf("Communication style: %s\n", getWorkerTypeDisplayName(worker.Endpoint.GetCommunicationStyle()))) - + workerPoolMap, _ := shared.GetWorkerPoolMap(opts) workerPoolNames := resolveValues(worker.WorkerPoolIDs, workerPoolMap) result.WriteString(fmt.Sprintf("Worker Pools: %s\n", output.FormatAsList(workerPoolNames))) - + // Add endpoint-specific details endpointDetails := getEndpointDetails(worker) for key, value := range endpointDetails { result.WriteString(fmt.Sprintf("%s: %s\n", key, value)) } - + // Web URL url := util.GenerateWebURL(opts.Host, worker.SpaceID, fmt.Sprintf("infrastructure/workers/%s/settings", worker.GetID())) result.WriteString(fmt.Sprintf("\nView this worker in Octopus Deploy: %s\n", output.Blue(url))) - + // Handle web flag if opts.WebFlags != nil && opts.WebFlags.Web.Value { machinescommon.DoWebForWorkers(worker, opts.Dependencies, opts.WebFlags, getWorkerTypeDisplayName(worker.Endpoint.GetCommunicationStyle())) } - + return result.String() } @@ -171,7 +166,7 @@ func getWorkerTypeDisplayName(communicationStyle string) string { func getEndpointDetails(worker *machines.Worker) map[string]string { details := make(map[string]string) - + switch endpoint := worker.Endpoint.(type) { case *machines.ListeningTentacleEndpoint: details["URI"] = endpoint.URI.String() @@ -188,7 +183,7 @@ func getEndpointDetails(worker *machines.Worker) map[string]string { details["Platform"] = endpoint.DotNetCorePlatform } } - + return details } diff --git a/pkg/cmd/workerpool/view/view.go b/pkg/cmd/workerpool/view/view.go index d8ff8794..05abfeb8 100644 --- a/pkg/cmd/workerpool/view/view.go +++ b/pkg/cmd/workerpool/view/view.go @@ -45,11 +45,6 @@ func ViewRun(opts *shared.ViewOptions) error { return err } - // Use basic format as default for worker pool view when no -f flag is specified - if !opts.Command.Flags().Changed(constants.FlagOutputFormat) { - opts.Command.Flags().Set(constants.FlagOutputFormat, constants.OutputFormatBasic) - } - return output.PrintResource(workerPool, opts.Command, output.Mappers[workerpools.IWorkerPool]{ Json: func(wp workerpools.IWorkerPool) any { return getWorkerPoolAsJson(opts, wp) From 8e621105639571ca7f21093b90958275fe93c0b5 Mon Sep 17 00:00:00 2001 From: Huy Nguyen Date: Thu, 7 Aug 2025 17:27:44 +1000 Subject: [PATCH 4/6] handle open web flag --- pkg/cmd/worker/view/view.go | 16 +++--- pkg/cmd/workerpool/view/view.go | 96 +++++++++++++++++---------------- pkg/machinescommon/web.go | 2 +- 3 files changed, 61 insertions(+), 53 deletions(-) diff --git a/pkg/cmd/worker/view/view.go b/pkg/cmd/worker/view/view.go index 6898a31a..ea18fd93 100644 --- a/pkg/cmd/worker/view/view.go +++ b/pkg/cmd/worker/view/view.go @@ -44,7 +44,7 @@ func ViewRun(opts *shared.ViewOptions) error { return err } - return output.PrintResource(worker, opts.Command, output.Mappers[*machines.Worker]{ + err = output.PrintResource(worker, opts.Command, output.Mappers[*machines.Worker]{ Json: func(w *machines.Worker) any { return getWorkerAsJson(opts, w) }, @@ -58,6 +58,15 @@ func ViewRun(opts *shared.ViewOptions) error { return getWorkerAsBasic(opts, w) }, }) + if err != nil { + return err + } + + if opts.WebFlags != nil && opts.WebFlags.Web.Value { + machinescommon.DoWebForWorkers(worker, opts.Dependencies, opts.WebFlags, getWorkerTypeDisplayName(worker.Endpoint.GetCommunicationStyle())) + } + + return nil } type WorkerAsJson struct { @@ -128,11 +137,6 @@ func getWorkerAsBasic(opts *shared.ViewOptions, worker *machines.Worker) string url := util.GenerateWebURL(opts.Host, worker.SpaceID, fmt.Sprintf("infrastructure/workers/%s/settings", worker.GetID())) result.WriteString(fmt.Sprintf("\nView this worker in Octopus Deploy: %s\n", output.Blue(url))) - // Handle web flag - if opts.WebFlags != nil && opts.WebFlags.Web.Value { - machinescommon.DoWebForWorkers(worker, opts.Dependencies, opts.WebFlags, getWorkerTypeDisplayName(worker.Endpoint.GetCommunicationStyle())) - } - return result.String() } diff --git a/pkg/cmd/workerpool/view/view.go b/pkg/cmd/workerpool/view/view.go index 05abfeb8..f1fdb92f 100644 --- a/pkg/cmd/workerpool/view/view.go +++ b/pkg/cmd/workerpool/view/view.go @@ -45,7 +45,7 @@ func ViewRun(opts *shared.ViewOptions) error { return err } - return output.PrintResource(workerPool, opts.Command, output.Mappers[workerpools.IWorkerPool]{ + err = output.PrintResource(workerPool, opts.Command, output.Mappers[workerpools.IWorkerPool]{ Json: func(wp workerpools.IWorkerPool) any { return getWorkerPoolAsJson(opts, wp) }, @@ -59,58 +59,67 @@ func ViewRun(opts *shared.ViewOptions) error { return getWorkerPoolAsBasic(opts, wp) }, }) + if err != nil { + return err + } + + if opts.WebFlags != nil && opts.WebFlags.Web.Value { + machinescommon.DoWebForWorkerPools(workerPool, opts.Dependencies, opts.WebFlags) + } + + return nil } type WorkerPoolAsJson struct { - Id string `json:"Id"` - Name string `json:"Name"` - WorkerPoolType string `json:"WorkerPoolType"` - IsDefault bool `json:"IsDefault"` - Workers WorkerStats `json:"Workers"` + Id string `json:"Id"` + Name string `json:"Name"` + WorkerPoolType string `json:"WorkerPoolType"` + IsDefault bool `json:"IsDefault"` + Workers WorkerStats `json:"Workers"` WorkerPoolDetails map[string]string `json:"WorkerPoolDetails"` - WebUrl string `json:"WebUrl"` + WebUrl string `json:"WebUrl"` } type WorkerStats struct { - Total int `json:"Total"` - Healthy int `json:"Healthy"` - HasWarnings int `json:"HasWarnings"` - Unhealthy int `json:"Unhealthy"` - Unavailable int `json:"Unavailable"` - Disabled int `json:"Disabled"` - SSH int `json:"SSH"` - ListeningTentacle int `json:"ListeningTentacle"` - PollingTentacle int `json:"PollingTentacle"` + Total int `json:"Total"` + Healthy int `json:"Healthy"` + HasWarnings int `json:"HasWarnings"` + Unhealthy int `json:"Unhealthy"` + Unavailable int `json:"Unavailable"` + Disabled int `json:"Disabled"` + SSH int `json:"SSH"` + ListeningTentacle int `json:"ListeningTentacle"` + PollingTentacle int `json:"PollingTentacle"` } func getWorkerPoolAsJson(opts *shared.ViewOptions, workerPool workerpools.IWorkerPool) WorkerPoolAsJson { workers, _ := getWorkers(opts, workerPool) workerStats := calculateWorkerStats(workers) - + workerPoolDetails := getWorkerPoolDetails(workerPool) - + return WorkerPoolAsJson{ - Id: workerPool.GetID(), - Name: workerPool.GetName(), - WorkerPoolType: getWorkerPoolTypeDescription(workerPool.GetWorkerPoolType()), - IsDefault: workerPool.GetIsDefault(), - Workers: workerStats, + Id: workerPool.GetID(), + Name: workerPool.GetName(), + WorkerPoolType: getWorkerPoolTypeDescription(workerPool.GetWorkerPoolType()), + IsDefault: workerPool.GetIsDefault(), + Workers: workerStats, WorkerPoolDetails: workerPoolDetails, - WebUrl: util.GenerateWebURL(opts.Host, workerPool.GetSpaceID(), fmt.Sprintf("infrastructure/workerpools/%s", workerPool.GetID())), + WebUrl: util.GenerateWebURL(opts.Host, workerPool.GetSpaceID(), fmt.Sprintf("infrastructure/workerpools/%s", workerPool.GetID())), } } func getWorkerPoolAsTableRow(opts *shared.ViewOptions, workerPool workerpools.IWorkerPool) []string { workers, _ := getWorkers(opts, workerPool) workerStats := calculateWorkerStats(workers) - + defaultStatus := "" if workerPool.GetIsDefault() { defaultStatus = output.Green("Yes") } else { defaultStatus = "No" } - + return []string{ output.Bold(workerPool.GetName()), getWorkerPoolTypeDescription(workerPool.GetWorkerPoolType()), @@ -123,19 +132,19 @@ func getWorkerPoolAsTableRow(opts *shared.ViewOptions, workerPool workerpools.IW func getWorkerPoolAsBasic(opts *shared.ViewOptions, workerPool workerpools.IWorkerPool) string { var result strings.Builder - + // Header result.WriteString(fmt.Sprintf("%s %s\n", output.Bold(workerPool.GetName()), output.Dimf("(%s)", workerPool.GetID()))) result.WriteString(fmt.Sprintf("Worker Pool Type: %s\n", getWorkerPoolTypeDescription(workerPool.GetWorkerPoolType()))) - + if workerPool.GetIsDefault() { result.WriteString(fmt.Sprintf("Default: %s\n", output.Green("Yes"))) } - + // Worker statistics workers, _ := getWorkers(opts, workerPool) workerStats := calculateWorkerStats(workers) - + result.WriteString(fmt.Sprintf("Total workers: %d\n", workerStats.Total)) if workerStats.Disabled > 0 { result.WriteString(fmt.Sprintf("Disabled workers: %s\n", output.Dimf("%d", workerStats.Disabled))) @@ -152,7 +161,7 @@ func getWorkerPoolAsBasic(opts *shared.ViewOptions, workerPool workerpools.IWork if workerStats.Unavailable > 0 { result.WriteString(fmt.Sprintf("Unavailable workers: %s\n", output.Redf("%d", workerStats.Unavailable))) } - + // Worker type breakdown if workerStats.SSH > 0 { result.WriteString(fmt.Sprintf("SSH workers: %d\n", workerStats.SSH)) @@ -163,22 +172,17 @@ func getWorkerPoolAsBasic(opts *shared.ViewOptions, workerPool workerpools.IWork if workerStats.PollingTentacle > 0 { result.WriteString(fmt.Sprintf("Polling Tentacle workers: %d\n", workerStats.PollingTentacle)) } - + // Worker pool specific details workerPoolDetails := getWorkerPoolDetails(workerPool) for key, value := range workerPoolDetails { result.WriteString(fmt.Sprintf("%s: %s\n", key, value)) } - + // Web URL url := util.GenerateWebURL(opts.Host, workerPool.GetSpaceID(), fmt.Sprintf("infrastructure/workerpools/%s", workerPool.GetID())) result.WriteString(fmt.Sprintf("\nView this worker pool in Octopus Deploy: %s\n", output.Blue(url))) - - // Handle web flag - if opts.WebFlags != nil && opts.WebFlags.Web.Value { - machinescommon.DoWebForWorkerPools(workerPool, opts.Dependencies, opts.WebFlags) - } - + return result.String() } @@ -192,14 +196,14 @@ func getWorkers(opts *shared.ViewOptions, workerPool workerpools.IWorkerPool) ([ func calculateWorkerStats(workers []*machines.Worker) WorkerStats { stats := WorkerStats{} - + for _, worker := range workers { stats.Total++ - + if worker.IsDisabled { stats.Disabled++ } - + switch worker.HealthStatus { case "Healthy": stats.Healthy++ @@ -210,7 +214,7 @@ func calculateWorkerStats(workers []*machines.Worker) WorkerStats { case "Unavailable": stats.Unavailable++ } - + switch worker.Endpoint.GetCommunicationStyle() { case "Ssh": stats.SSH++ @@ -220,18 +224,18 @@ func calculateWorkerStats(workers []*machines.Worker) WorkerStats { stats.PollingTentacle++ } } - + return stats } func getWorkerPoolDetails(workerPool workerpools.IWorkerPool) map[string]string { details := make(map[string]string) - + if workerPool.GetWorkerPoolType() == workerpools.WorkerPoolTypeDynamic { dynamicPool := workerPool.(*workerpools.DynamicWorkerPool) details["Worker Type"] = string(dynamicPool.WorkerType) } - + return details } diff --git a/pkg/machinescommon/web.go b/pkg/machinescommon/web.go index 636e6796..a8893490 100644 --- a/pkg/machinescommon/web.go +++ b/pkg/machinescommon/web.go @@ -41,7 +41,7 @@ func DoWebForWorkers(worker *machines.Worker, dependencies *cmd.Dependencies, fl } func DoWebForWorkerPools(workerPool workerpools.IWorkerPool, dependencies *cmd.Dependencies, flags *WebFlags) { - url := fmt.Sprintf("%s/app#/%s/infrastructure/workerpools/%s/settings", dependencies.Host, dependencies.Space.GetID(), workerPool.GetID()) + url := fmt.Sprintf("%s/app#/%s/infrastructure/workerpools/%s", dependencies.Host, dependencies.Space.GetID(), workerPool.GetID()) doWeb(url, "Worker Pool", dependencies.Out, flags) } From e18940fa1c252541fce06da7c4d388839e307d0e Mon Sep 17 00:00:00 2001 From: Huy Nguyen Date: Thu, 7 Aug 2025 17:45:27 +1000 Subject: [PATCH 5/6] refactor --- pkg/cmd/workerpool/view/view.go | 54 +++++++++------------------------ 1 file changed, 14 insertions(+), 40 deletions(-) diff --git a/pkg/cmd/workerpool/view/view.go b/pkg/cmd/workerpool/view/view.go index f1fdb92f..3b61fe01 100644 --- a/pkg/cmd/workerpool/view/view.go +++ b/pkg/cmd/workerpool/view/view.go @@ -71,13 +71,12 @@ func ViewRun(opts *shared.ViewOptions) error { } type WorkerPoolAsJson struct { - Id string `json:"Id"` - Name string `json:"Name"` - WorkerPoolType string `json:"WorkerPoolType"` - IsDefault bool `json:"IsDefault"` - Workers WorkerStats `json:"Workers"` - WorkerPoolDetails map[string]string `json:"WorkerPoolDetails"` - WebUrl string `json:"WebUrl"` + Id string `json:"Id"` + Name string `json:"Name"` + WorkerPoolType string `json:"WorkerPoolType"` + IsDefault bool `json:"IsDefault"` + Workers WorkerStats `json:"Workers"` + WebUrl string `json:"WebUrl"` } type WorkerStats struct { @@ -96,16 +95,13 @@ func getWorkerPoolAsJson(opts *shared.ViewOptions, workerPool workerpools.IWorke workers, _ := getWorkers(opts, workerPool) workerStats := calculateWorkerStats(workers) - workerPoolDetails := getWorkerPoolDetails(workerPool) - return WorkerPoolAsJson{ - Id: workerPool.GetID(), - Name: workerPool.GetName(), - WorkerPoolType: getWorkerPoolTypeDescription(workerPool.GetWorkerPoolType()), - IsDefault: workerPool.GetIsDefault(), - Workers: workerStats, - WorkerPoolDetails: workerPoolDetails, - WebUrl: util.GenerateWebURL(opts.Host, workerPool.GetSpaceID(), fmt.Sprintf("infrastructure/workerpools/%s", workerPool.GetID())), + Id: workerPool.GetID(), + Name: workerPool.GetName(), + WorkerPoolType: string(workerPool.GetWorkerPoolType()), + IsDefault: workerPool.GetIsDefault(), + Workers: workerStats, + WebUrl: util.GenerateWebURL(opts.Host, workerPool.GetSpaceID(), fmt.Sprintf("infrastructure/workerpools/%s", workerPool.GetID())), } } @@ -122,7 +118,7 @@ func getWorkerPoolAsTableRow(opts *shared.ViewOptions, workerPool workerpools.IW return []string{ output.Bold(workerPool.GetName()), - getWorkerPoolTypeDescription(workerPool.GetWorkerPoolType()), + string(workerPool.GetWorkerPoolType()), defaultStatus, fmt.Sprintf("%d", workerStats.Total), output.Greenf("%d", workerStats.Healthy), @@ -135,7 +131,7 @@ func getWorkerPoolAsBasic(opts *shared.ViewOptions, workerPool workerpools.IWork // Header result.WriteString(fmt.Sprintf("%s %s\n", output.Bold(workerPool.GetName()), output.Dimf("(%s)", workerPool.GetID()))) - result.WriteString(fmt.Sprintf("Worker Pool Type: %s\n", getWorkerPoolTypeDescription(workerPool.GetWorkerPoolType()))) + result.WriteString(fmt.Sprintf("Worker Pool Type: %s\n", string(workerPool.GetWorkerPoolType()))) if workerPool.GetIsDefault() { result.WriteString(fmt.Sprintf("Default: %s\n", output.Green("Yes"))) @@ -173,12 +169,6 @@ func getWorkerPoolAsBasic(opts *shared.ViewOptions, workerPool workerpools.IWork result.WriteString(fmt.Sprintf("Polling Tentacle workers: %d\n", workerStats.PollingTentacle)) } - // Worker pool specific details - workerPoolDetails := getWorkerPoolDetails(workerPool) - for key, value := range workerPoolDetails { - result.WriteString(fmt.Sprintf("%s: %s\n", key, value)) - } - // Web URL url := util.GenerateWebURL(opts.Host, workerPool.GetSpaceID(), fmt.Sprintf("infrastructure/workerpools/%s", workerPool.GetID())) result.WriteString(fmt.Sprintf("\nView this worker pool in Octopus Deploy: %s\n", output.Blue(url))) @@ -228,20 +218,4 @@ func calculateWorkerStats(workers []*machines.Worker) WorkerStats { return stats } -func getWorkerPoolDetails(workerPool workerpools.IWorkerPool) map[string]string { - details := make(map[string]string) - - if workerPool.GetWorkerPoolType() == workerpools.WorkerPoolTypeDynamic { - dynamicPool := workerPool.(*workerpools.DynamicWorkerPool) - details["Worker Type"] = string(dynamicPool.WorkerType) - } - return details -} - -func getWorkerPoolTypeDescription(poolType workerpools.WorkerPoolType) string { - if poolType == workerpools.WorkerPoolTypeDynamic { - return "Dynamic" - } - return "Static" -} From d869bba1242f58588cffe7962f1f0853a1fd5c6b Mon Sep 17 00:00:00 2001 From: Huy Nguyen Date: Tue, 12 Aug 2025 10:55:05 +1000 Subject: [PATCH 6/6] Fix endcode issue for healthStatus in json format --- pkg/cmd/worker/view/view.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/cmd/worker/view/view.go b/pkg/cmd/worker/view/view.go index ea18fd93..27a34c08 100644 --- a/pkg/cmd/worker/view/view.go +++ b/pkg/cmd/worker/view/view.go @@ -89,7 +89,7 @@ func getWorkerAsJson(opts *shared.ViewOptions, worker *machines.Worker) WorkerAs return WorkerAsJson{ Id: worker.GetID(), Name: worker.Name, - HealthStatus: getHealthStatusFormatted(worker.HealthStatus), + HealthStatus: worker.HealthStatus, StatusSummary: worker.StatusSummary, CommunicationStyle: worker.Endpoint.GetCommunicationStyle(), WorkerPools: workerPoolNames,