github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/cmd/juju/status/formatted.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package status 5 6 import ( 7 "encoding/json" 8 "fmt" 9 10 "gopkg.in/juju/names.v2" 11 12 "github.com/juju/juju/cmd/juju/storage" 13 "github.com/juju/juju/core/instance" 14 "github.com/juju/juju/core/status" 15 ) 16 17 type formattedStatus struct { 18 Model modelStatus `json:"model"` 19 Machines map[string]machineStatus `json:"machines"` 20 Applications map[string]applicationStatus `json:"applications"` 21 RemoteApplications map[string]remoteApplicationStatus `json:"application-endpoints,omitempty" yaml:"application-endpoints,omitempty"` 22 Offers map[string]offerStatus `json:"offers,omitempty" yaml:"offers,omitempty"` 23 Relations []relationStatus `json:"-" yaml:"-"` 24 Storage *storage.CombinedStorage `json:"storage,omitempty" yaml:"storage,omitempty"` 25 Controller *controllerStatus `json:"controller,omitempty" yaml:"controller,omitempty"` 26 } 27 28 type formattedMachineStatus struct { 29 Model string `json:"model"` 30 Machines map[string]machineStatus `json:"machines"` 31 } 32 33 type errorStatus struct { 34 StatusError string `json:"status-error" yaml:"status-error"` 35 } 36 37 type modelStatus struct { 38 Name string `json:"name" yaml:"name"` 39 Type string `json:"type" yaml:"type"` 40 Controller string `json:"controller" yaml:"controller"` 41 Cloud string `json:"cloud" yaml:"cloud"` 42 CloudRegion string `json:"region,omitempty" yaml:"region,omitempty"` 43 Version string `json:"version" yaml:"version"` 44 AvailableVersion string `json:"upgrade-available,omitempty" yaml:"upgrade-available,omitempty"` 45 Status statusInfoContents `json:"model-status,omitempty" yaml:"model-status,omitempty"` 46 MeterStatus *meterStatus `json:"meter-status,omitempty" yaml:"meter-status,omitempty"` 47 SLA string `json:"sla,omitempty" yaml:"sla,omitempty"` 48 } 49 50 type controllerStatus struct { 51 Timestamp string `json:"timestamp,omitempty" yaml:"timestamp,omitempty"` 52 } 53 54 type networkInterface struct { 55 IPAddresses []string `json:"ip-addresses" yaml:"ip-addresses"` 56 MACAddress string `json:"mac-address" yaml:"mac-address"` 57 Gateway string `json:"gateway,omitempty" yaml:"gateway,omitempty"` 58 DNSNameservers []string `json:"dns-nameservers,omitempty" yaml:"dns-nameservers,omitempty"` 59 Space string `json:"space,omitempty" yaml:"space,omitempty"` 60 IsUp bool `json:"is-up" yaml:"is-up"` 61 } 62 63 type machineStatus struct { 64 Err error `json:"-" yaml:",omitempty"` 65 JujuStatus statusInfoContents `json:"juju-status,omitempty" yaml:"juju-status,omitempty"` 66 DNSName string `json:"dns-name,omitempty" yaml:"dns-name,omitempty"` 67 IPAddresses []string `json:"ip-addresses,omitempty" yaml:"ip-addresses,omitempty"` 68 InstanceId instance.Id `json:"instance-id,omitempty" yaml:"instance-id,omitempty"` 69 DisplayName string `json:"display-name,omitempty" yaml:"display-name,omitempty"` 70 MachineStatus statusInfoContents `json:"machine-status,omitempty" yaml:"machine-status,omitempty"` 71 Series string `json:"series,omitempty" yaml:"series,omitempty"` 72 Id string `json:"-" yaml:"-"` 73 NetworkInterfaces map[string]networkInterface `json:"network-interfaces,omitempty" yaml:"network-interfaces,omitempty"` 74 Containers map[string]machineStatus `json:"containers,omitempty" yaml:"containers,omitempty"` 75 Constraints string `json:"constraints,omitempty" yaml:"constraints,omitempty"` 76 Hardware string `json:"hardware,omitempty" yaml:"hardware,omitempty"` 77 HAStatus string `json:"controller-member-status,omitempty" yaml:"controller-member-status,omitempty"` 78 LXDProfiles map[string]lxdProfileContents `json:"lxd-profiles,omitempty" yaml:"lxd-profiles,omitempty"` 79 } 80 81 // A goyaml bug means we can't declare these types 82 // locally to the GetYAML methods. 83 type machineStatusNoMarshal machineStatus 84 85 func (s machineStatus) MarshalJSON() ([]byte, error) { 86 if s.Err != nil { 87 return json.Marshal(errorStatus{s.Err.Error()}) 88 } 89 return json.Marshal(machineStatusNoMarshal(s)) 90 } 91 92 func (s machineStatus) MarshalYAML() (interface{}, error) { 93 if s.Err != nil { 94 return errorStatus{s.Err.Error()}, nil 95 } 96 return machineStatusNoMarshal(s), nil 97 } 98 99 // machineName returns the InstanceId, unless DisplayName is set. 100 func (s machineStatus) machineName() string { 101 if s.DisplayName == "" { 102 return string(s.InstanceId) 103 } 104 return s.DisplayName 105 } 106 107 // LXDProfile holds status info about a LXDProfile 108 type lxdProfileContents struct { 109 Config map[string]string `json:"config" yaml:"config"` 110 Description string `json:"description" yaml:"description"` 111 Devices map[string]map[string]string `json:"devices" yaml:"devices"` 112 } 113 114 type applicationStatus struct { 115 Err error `json:"-" yaml:",omitempty"` 116 Charm string `json:"charm" yaml:"charm"` 117 Series string `json:"series"` 118 OS string `json:"os"` 119 CharmOrigin string `json:"charm-origin" yaml:"charm-origin"` 120 CharmName string `json:"charm-name" yaml:"charm-name"` 121 CharmRev int `json:"charm-rev" yaml:"charm-rev"` 122 CharmVersion string `json:"charm-version,omitempty" yaml:"charm-version,omitempty"` 123 CanUpgradeTo string `json:"can-upgrade-to,omitempty" yaml:"can-upgrade-to,omitempty"` 124 Scale int `json:"scale,omitempty" yaml:"scale,omitempty"` 125 Placement string `json:"placement,omitempty" yaml:"placement,omitempty"` 126 ProviderId string `json:"provider-id,omitempty" yaml:"provider-id,omitempty"` 127 Address string `json:"address,omitempty" yaml:"address,omitempty"` 128 Exposed bool `json:"exposed" yaml:"exposed"` 129 Life string `json:"life,omitempty" yaml:"life,omitempty"` 130 StatusInfo statusInfoContents `json:"application-status,omitempty" yaml:"application-status"` 131 Relations map[string][]string `json:"relations,omitempty" yaml:"relations,omitempty"` 132 SubordinateTo []string `json:"subordinate-to,omitempty" yaml:"subordinate-to,omitempty"` 133 Units map[string]unitStatus `json:"units,omitempty" yaml:"units,omitempty"` 134 Version string `json:"version,omitempty" yaml:"version,omitempty"` 135 EndpointBindings map[string]string `json:"endpoint-bindings,omitempty" yaml:"endpoint-bindings,omitempty"` 136 } 137 138 type applicationStatusNoMarshal applicationStatus 139 140 func (s applicationStatus) MarshalJSON() ([]byte, error) { 141 if s.Err != nil { 142 return json.Marshal(errorStatus{s.Err.Error()}) 143 } 144 return json.Marshal(applicationStatusNoMarshal(s)) 145 } 146 147 func (s applicationStatus) MarshalYAML() (interface{}, error) { 148 if s.Err != nil { 149 return errorStatus{s.Err.Error()}, nil 150 } 151 return applicationStatusNoMarshal(s), nil 152 } 153 154 type remoteEndpoint struct { 155 Name string `json:"-" yaml:"-"` 156 Interface string `json:"interface" yaml:"interface"` 157 Role string `json:"role" yaml:"role"` 158 } 159 160 type remoteApplicationStatus struct { 161 Err error `json:"-" yaml:",omitempty"` 162 OfferURL string `json:"url" yaml:"url"` 163 Endpoints map[string]remoteEndpoint `json:"endpoints,omitempty" yaml:"endpoints,omitempty"` 164 Life string `json:"life,omitempty" yaml:"life,omitempty"` 165 StatusInfo statusInfoContents `json:"application-status,omitempty" yaml:"application-status"` 166 Relations map[string][]string `json:"relations,omitempty" yaml:"relations,omitempty"` 167 } 168 169 type remoteApplicationStatusNoMarshal remoteApplicationStatus 170 171 func (s remoteApplicationStatus) MarshalJSON() ([]byte, error) { 172 if s.Err != nil { 173 return json.Marshal(errorStatus{s.Err.Error()}) 174 } 175 return json.Marshal(remoteApplicationStatusNoMarshal(s)) 176 } 177 178 func (s remoteApplicationStatus) MarshalYAML() (interface{}, error) { 179 if s.Err != nil { 180 return errorStatus{s.Err.Error()}, nil 181 } 182 return remoteApplicationStatusNoMarshal(s), nil 183 } 184 185 type offerStatusNoMarshal offerStatus 186 187 type offerStatus struct { 188 Err error `json:"-" yaml:",omitempty"` 189 OfferName string `json:"-" yaml:",omitempty"` 190 ApplicationName string `json:"application" yaml:"application"` 191 CharmURL string `json:"charm,omitempty" yaml:"charm,omitempty"` 192 TotalConnectedCount int `json:"total-connected-count,omitempty" yaml:"total-connected-count,omitempty"` 193 ActiveConnectedCount int `json:"active-connected-count,omitempty" yaml:"active-connected-count,omitempty"` 194 Endpoints map[string]remoteEndpoint `json:"endpoints" yaml:"endpoints"` 195 } 196 197 func (s offerStatus) MarshalJSON() ([]byte, error) { 198 if s.Err != nil { 199 return json.Marshal(errorStatus{s.Err.Error()}) 200 } 201 return json.Marshal(offerStatusNoMarshal(s)) 202 } 203 204 func (s offerStatus) MarshalYAML() (interface{}, error) { 205 if s.Err != nil { 206 return errorStatus{s.Err.Error()}, nil 207 } 208 return offerStatusNoMarshal(s), nil 209 } 210 211 type meterStatus struct { 212 Color string `json:"color,omitempty" yaml:"color,omitempty"` 213 Message string `json:"message,omitempty" yaml:"message,omitempty"` 214 } 215 216 type unitStatus struct { 217 // New Juju Health Status fields. 218 WorkloadStatusInfo statusInfoContents `json:"workload-status,omitempty" yaml:"workload-status,omitempty"` 219 JujuStatusInfo statusInfoContents `json:"juju-status,omitempty" yaml:"juju-status,omitempty"` 220 MeterStatus *meterStatus `json:"meter-status,omitempty" yaml:"meter-status,omitempty"` 221 222 Leader bool `json:"leader,omitempty" yaml:"leader,omitempty"` 223 Charm string `json:"upgrading-from,omitempty" yaml:"upgrading-from,omitempty"` 224 Machine string `json:"machine,omitempty" yaml:"machine,omitempty"` 225 OpenedPorts []string `json:"open-ports,omitempty" yaml:"open-ports,omitempty"` 226 PublicAddress string `json:"public-address,omitempty" yaml:"public-address,omitempty"` 227 Address string `json:"address,omitempty" yaml:"address,omitempty"` 228 ProviderId string `json:"provider-id,omitempty" yaml:"provider-id,omitempty"` 229 Subordinates map[string]unitStatus `json:"subordinates,omitempty" yaml:"subordinates,omitempty"` 230 } 231 232 func (s *formattedStatus) applicationScale(name string) (string, bool) { 233 // The current unit count are units that are either in Idle or Executing status. 234 // In other words, units that are active and available. 235 currentUnitCount := 0 236 desiredUnitCount := 0 237 238 app := s.Applications[name] 239 match := func(u unitStatus) { 240 desiredUnitCount++ 241 switch u.JujuStatusInfo.Current { 242 case status.Executing, status.Idle, status.Running: 243 currentUnitCount++ 244 } 245 } 246 // If the app is subordinate to other units, then this is a subordinate charm. 247 if len(app.SubordinateTo) > 0 { 248 for _, a := range s.Applications { 249 for _, u := range a.Units { 250 for sub, subStatus := range u.Subordinates { 251 if subAppName, _ := names.UnitApplication(sub); subAppName == name { 252 match(subStatus) 253 } 254 } 255 } 256 } 257 } else { 258 for _, u := range app.Units { 259 match(u) 260 } 261 } 262 if s.Model.Type == "caas" { 263 desiredUnitCount = app.Scale 264 } 265 if currentUnitCount == desiredUnitCount { 266 return fmt.Sprint(currentUnitCount), false 267 } 268 return fmt.Sprintf("%d/%d", currentUnitCount, desiredUnitCount), true 269 } 270 271 type statusInfoContents struct { 272 Err error `json:"-" yaml:",omitempty"` 273 Current status.Status `json:"current,omitempty" yaml:"current,omitempty"` 274 Message string `json:"message,omitempty" yaml:"message,omitempty"` 275 Since string `json:"since,omitempty" yaml:"since,omitempty"` 276 Version string `json:"version,omitempty" yaml:"version,omitempty"` 277 Life string `json:"life,omitempty" yaml:"life,omitempty"` 278 } 279 280 type statusInfoContentsNoMarshal statusInfoContents 281 282 func (s statusInfoContents) MarshalJSON() ([]byte, error) { 283 if s.Err != nil { 284 return json.Marshal(errorStatus{s.Err.Error()}) 285 } 286 return json.Marshal(statusInfoContentsNoMarshal(s)) 287 } 288 289 func (s statusInfoContents) MarshalYAML() (interface{}, error) { 290 if s.Err != nil { 291 return errorStatus{s.Err.Error()}, nil 292 } 293 return statusInfoContentsNoMarshal(s), nil 294 } 295 296 type unitStatusNoMarshal unitStatus 297 298 func (s unitStatus) MarshalJSON() ([]byte, error) { 299 if s.WorkloadStatusInfo.Err != nil { 300 return json.Marshal(errorStatus{s.WorkloadStatusInfo.Err.Error()}) 301 } 302 return json.Marshal(unitStatusNoMarshal(s)) 303 } 304 305 func (s unitStatus) MarshalYAML() (interface{}, error) { 306 if s.WorkloadStatusInfo.Err != nil { 307 return errorStatus{s.WorkloadStatusInfo.Err.Error()}, nil 308 } 309 return unitStatusNoMarshal(s), nil 310 } 311 312 type relationStatus struct { 313 Provider string 314 Requirer string 315 Interface string 316 Type string 317 Status string 318 Message string 319 }