github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/worker/uniter/runner/jujuc/status-get.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package jujuc 5 6 import ( 7 "github.com/juju/cmd/v3" 8 "github.com/juju/errors" 9 "github.com/juju/gnuflag" 10 11 jujucmd "github.com/juju/juju/cmd" 12 "github.com/juju/juju/core/status" 13 ) 14 15 // StatusGetCommand implements the status-get command. 16 type StatusGetCommand struct { 17 cmd.CommandBase 18 ctx Context 19 includeData bool 20 applicationWide bool 21 out cmd.Output 22 } 23 24 func NewStatusGetCommand(ctx Context) (cmd.Command, error) { 25 return &StatusGetCommand{ctx: ctx}, nil 26 } 27 28 func (c *StatusGetCommand) Info() *cmd.Info { 29 doc := ` 30 By default, only the status value is printed. 31 If the --include-data flag is passed, the associated data are printed also. 32 ` 33 return jujucmd.Info(&cmd.Info{ 34 Name: "status-get", 35 Args: "[--include-data] [--application]", 36 Purpose: "print status information", 37 Doc: doc, 38 }) 39 } 40 41 func (c *StatusGetCommand) SetFlags(f *gnuflag.FlagSet) { 42 c.out.AddFlags(f, "smart", cmd.DefaultFormatters.Formatters()) 43 f.BoolVar(&c.includeData, "include-data", false, "print all status data") 44 f.BoolVar(&c.applicationWide, "application", false, "print status for all units of this application if this unit is the leader") 45 } 46 47 func (c *StatusGetCommand) Init(args []string) error { 48 return cmd.CheckEmpty(args) 49 } 50 51 // StatusInfo is a record of the status information for a application or a unit's workload. 52 type StatusInfo struct { 53 Tag string 54 Status string 55 Info string 56 Data map[string]interface{} 57 } 58 59 // ApplicationStatusInfo holds StatusInfo for an Application and all its Units. 60 type ApplicationStatusInfo struct { 61 Application StatusInfo 62 Units []StatusInfo 63 } 64 65 func toDetails(info StatusInfo, includeData bool) map[string]interface{} { 66 details := make(map[string]interface{}) 67 details["status"] = info.Status 68 if includeData { 69 data := make(map[string]interface{}) 70 for k, v := range info.Data { 71 data[k] = v 72 } 73 details["status-data"] = data 74 details["message"] = info.Info 75 } 76 return details 77 } 78 79 func (c *StatusGetCommand) ApplicationStatus(ctx *cmd.Context) error { 80 applicationStatus, err := c.ctx.ApplicationStatus() 81 if err != nil { 82 if errors.IsNotImplemented(err) { 83 return c.out.Write(ctx, status.Unknown) 84 } 85 return errors.Annotatef(err, "finding application status") 86 } 87 if !c.includeData && c.out.Name() == "smart" { 88 return c.out.Write(ctx, applicationStatus.Application.Status) 89 } 90 statusDetails := make(map[string]interface{}) 91 details := toDetails(applicationStatus.Application, c.includeData) 92 93 units := make(map[string]interface{}, len(applicationStatus.Units)) 94 for _, unit := range applicationStatus.Units { 95 // NOTE: unit.Tag is a unit name, not a unit tag. 96 units[unit.Tag] = toDetails(unit, c.includeData) 97 } 98 details["units"] = units 99 statusDetails["application-status"] = details 100 _ = c.out.Write(ctx, statusDetails) 101 102 return nil 103 104 } 105 106 func (c *StatusGetCommand) unitOrApplicationStatus(ctx *cmd.Context) error { 107 var err error 108 109 if c.applicationWide { 110 return c.ApplicationStatus(ctx) 111 } 112 113 unitStatus, err := c.ctx.UnitStatus() 114 if err != nil { 115 if errors.IsNotImplemented(err) { 116 return c.out.Write(ctx, status.Unknown) 117 } 118 return errors.Annotatef(err, "finding workload status") 119 } 120 if !c.includeData && c.out.Name() == "smart" { 121 return c.out.Write(ctx, unitStatus.Status) 122 } 123 _ = c.out.Write(ctx, toDetails(*unitStatus, c.includeData)) 124 return nil 125 } 126 127 func (c *StatusGetCommand) Run(ctx *cmd.Context) error { 128 return c.unitOrApplicationStatus(ctx) 129 }