@@ -2,17 +2,18 @@ package view
22
33import (
44 "fmt"
5+ "strings"
56
67 "github.com/MakeNowJust/heredoc/v2"
78 "github.com/OctopusDeploy/cli/pkg/cmd"
8- listeningTentacle "github.com/OctopusDeploy/cli/pkg/cmd/worker/listening-tentacle/view"
9- pollingTentacle "github.com/OctopusDeploy/cli/pkg/cmd/worker/polling-tentacle/view"
109 "github.com/OctopusDeploy/cli/pkg/cmd/worker/shared"
11- ssh "github.com/OctopusDeploy/cli/pkg/cmd/worker/ssh/view"
1210 "github.com/OctopusDeploy/cli/pkg/constants"
1311 "github.com/OctopusDeploy/cli/pkg/factory"
1412 "github.com/OctopusDeploy/cli/pkg/machinescommon"
13+ "github.com/OctopusDeploy/cli/pkg/output"
1514 "github.com/OctopusDeploy/cli/pkg/usage"
15+ "github.com/OctopusDeploy/cli/pkg/util"
16+ "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/machines"
1617 "github.com/spf13/cobra"
1718)
1819
@@ -28,7 +29,7 @@ func NewCmdView(f factory.Factory) *cobra.Command {
2829 $ %[1]s worker view 'worker'
2930 ` , constants .ExecutableName ),
3031 RunE : func (c * cobra.Command , args []string ) error {
31- return ViewRun (shared .NewViewOptions (flags , cmd .NewDependencies (f , c ), args ))
32+ return ViewRun (shared .NewViewOptions (flags , cmd .NewDependencies (f , c ), args , c ))
3233 },
3334 }
3435
@@ -43,14 +44,169 @@ func ViewRun(opts *shared.ViewOptions) error {
4344 return err
4445 }
4546
46- switch worker .Endpoint .GetCommunicationStyle () {
47+ err = output .PrintResource (worker , opts .Command , output.Mappers [* machines.Worker ]{
48+ Json : func (w * machines.Worker ) any {
49+ return getWorkerAsJson (opts , w )
50+ },
51+ Table : output.TableDefinition [* machines.Worker ]{
52+ Header : []string {"NAME" , "TYPE" , "HEALTH" , "STATUS" , "WORKER POOLS" , "ENDPOINT DETAILS" },
53+ Row : func (w * machines.Worker ) []string {
54+ return getWorkerAsTableRow (opts , w )
55+ },
56+ },
57+ Basic : func (w * machines.Worker ) string {
58+ return getWorkerAsBasic (opts , w )
59+ },
60+ })
61+ if err != nil {
62+ return err
63+ }
64+
65+ if opts .WebFlags != nil && opts .WebFlags .Web .Value {
66+ machinescommon .DoWebForWorkers (worker , opts .Dependencies , opts .WebFlags , getWorkerTypeDisplayName (worker .Endpoint .GetCommunicationStyle ()))
67+ }
68+
69+ return nil
70+ }
71+
72+ type WorkerAsJson struct {
73+ Id string `json:"Id"`
74+ Name string `json:"Name"`
75+ HealthStatus string `json:"HealthStatus"`
76+ StatusSummary string `json:"StatusSummary"`
77+ CommunicationStyle string `json:"CommunicationStyle"`
78+ WorkerPools []string `json:"WorkerPools"`
79+ EndpointDetails map [string ]string `json:"EndpointDetails"`
80+ WebUrl string `json:"WebUrl"`
81+ }
82+
83+ func getWorkerAsJson (opts * shared.ViewOptions , worker * machines.Worker ) WorkerAsJson {
84+ workerPoolMap , _ := shared .GetWorkerPoolMap (opts )
85+ workerPoolNames := resolveValues (worker .WorkerPoolIDs , workerPoolMap )
86+
87+ endpointDetails := getEndpointDetails (worker )
88+
89+ return WorkerAsJson {
90+ Id : worker .GetID (),
91+ Name : worker .Name ,
92+ HealthStatus : worker .HealthStatus ,
93+ StatusSummary : worker .StatusSummary ,
94+ CommunicationStyle : worker .Endpoint .GetCommunicationStyle (),
95+ WorkerPools : workerPoolNames ,
96+ EndpointDetails : endpointDetails ,
97+ WebUrl : util .GenerateWebURL (opts .Host , worker .SpaceID , fmt .Sprintf ("infrastructure/workers/%s/settings" , worker .GetID ())),
98+ }
99+ }
100+
101+ func getWorkerAsTableRow (opts * shared.ViewOptions , worker * machines.Worker ) []string {
102+ workerPoolMap , _ := shared .GetWorkerPoolMap (opts )
103+ workerPoolNames := resolveValues (worker .WorkerPoolIDs , workerPoolMap )
104+
105+ endpointDetails := getEndpointDetails (worker )
106+ endpointDetailsStr := formatEndpointDetailsForTable (endpointDetails )
107+
108+ return []string {
109+ worker .Name ,
110+ getWorkerTypeDisplayName (worker .Endpoint .GetCommunicationStyle ()),
111+ getHealthStatusFormatted (worker .HealthStatus ),
112+ worker .StatusSummary ,
113+ strings .Join (workerPoolNames , ", " ),
114+ endpointDetailsStr ,
115+ }
116+ }
117+
118+ func getWorkerAsBasic (opts * shared.ViewOptions , worker * machines.Worker ) string {
119+ var result strings.Builder
120+
121+ result .WriteString (fmt .Sprintf ("%s %s\n " , output .Bold (worker .Name ), output .Dimf ("(%s)" , worker .GetID ())))
122+ result .WriteString (fmt .Sprintf ("Health status: %s\n " , getHealthStatusFormatted (worker .HealthStatus )))
123+ result .WriteString (fmt .Sprintf ("Current status: %s\n " , worker .StatusSummary ))
124+ result .WriteString (fmt .Sprintf ("Communication style: %s\n " , getWorkerTypeDisplayName (worker .Endpoint .GetCommunicationStyle ())))
125+
126+ workerPoolMap , _ := shared .GetWorkerPoolMap (opts )
127+ workerPoolNames := resolveValues (worker .WorkerPoolIDs , workerPoolMap )
128+ result .WriteString (fmt .Sprintf ("Worker Pools: %s\n " , output .FormatAsList (workerPoolNames )))
129+
130+ // Add endpoint-specific details
131+ endpointDetails := getEndpointDetails (worker )
132+ for key , value := range endpointDetails {
133+ result .WriteString (fmt .Sprintf ("%s: %s\n " , key , value ))
134+ }
135+
136+ // Web URL
137+ url := util .GenerateWebURL (opts .Host , worker .SpaceID , fmt .Sprintf ("infrastructure/workers/%s/settings" , worker .GetID ()))
138+ result .WriteString (fmt .Sprintf ("\n View this worker in Octopus Deploy: %s\n " , output .Blue (url )))
139+
140+ return result .String ()
141+ }
142+
143+ func getHealthStatusFormatted (status string ) string {
144+ switch status {
145+ case "Healthy" :
146+ return output .Green (status )
147+ case "Unhealthy" :
148+ return output .Red (status )
149+ case "HasWarnings" :
150+ return output .Yellow ("Has Warnings" )
151+ case "Unavailable" :
152+ return output .Dim (status )
153+ default :
154+ return status
155+ }
156+ }
157+
158+ func getWorkerTypeDisplayName (communicationStyle string ) string {
159+ switch communicationStyle {
47160 case "TentaclePassive" :
48- return listeningTentacle . ViewRun ( opts )
161+ return "Listening Tentacle"
49162 case "TentacleActive" :
50- return pollingTentacle . ViewRun ( opts )
163+ return "Polling Tentacle"
51164 case "Ssh" :
52- return ssh .ViewRun (opts )
165+ return "SSH"
166+ default :
167+ return communicationStyle
168+ }
169+ }
170+
171+ func getEndpointDetails (worker * machines.Worker ) map [string ]string {
172+ details := make (map [string ]string )
173+
174+ switch endpoint := worker .Endpoint .(type ) {
175+ case * machines.ListeningTentacleEndpoint :
176+ details ["URI" ] = endpoint .URI .String ()
177+ if endpoint .TentacleVersionDetails != nil {
178+ details ["Tentacle version" ] = endpoint .TentacleVersionDetails .Version
179+ }
180+ case * machines.PollingTentacleEndpoint :
181+ if endpoint .TentacleVersionDetails != nil {
182+ details ["Tentacle version" ] = endpoint .TentacleVersionDetails .Version
183+ }
184+ case * machines.SSHEndpoint :
185+ details ["URI" ] = endpoint .URI .String ()
186+ if endpoint .DotNetCorePlatform != "" {
187+ details ["Platform" ] = endpoint .DotNetCorePlatform
188+ }
53189 }
54190
55- return fmt .Errorf ("unsupported worker '%s'" , worker .Endpoint .GetCommunicationStyle ())
191+ return details
192+ }
193+
194+ func formatEndpointDetailsForTable (details map [string ]string ) string {
195+ var parts []string
196+ for key , value := range details {
197+ parts = append (parts , fmt .Sprintf ("%s: %s" , key , value ))
198+ }
199+ return strings .Join (parts , "; " )
200+ }
201+
202+ func resolveValues (keys []string , lookup map [string ]string ) []string {
203+ var result []string
204+ for _ , key := range keys {
205+ if value , exists := lookup [key ]; exists {
206+ result = append (result , value )
207+ } else {
208+ result = append (result , key )
209+ }
210+ }
211+ return result
56212}
0 commit comments