github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/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/instance" 13 "github.com/juju/juju/status" 14 ) 15 16 type formattedStatus struct { 17 Model modelStatus `json:"model"` 18 Machines map[string]machineStatus `json:"machines"` 19 Applications map[string]applicationStatus `json:"applications"` 20 } 21 22 type formattedMachineStatus struct { 23 Model string `json:"model"` 24 Machines map[string]machineStatus `json:"machines"` 25 } 26 27 type errorStatus struct { 28 StatusError string `json:"status-error" yaml:"status-error"` 29 } 30 31 type modelStatus struct { 32 Name string `json:"name" yaml:"name"` 33 Controller string `json:"controller" yaml:"controller"` 34 Cloud string `json:"cloud" yaml:"cloud"` 35 CloudRegion string `json:"region,omitempty" yaml:"region,omitempty"` 36 Version string `json:"version" yaml:"version"` 37 AvailableVersion string `json:"upgrade-available,omitempty" yaml:"upgrade-available,omitempty"` 38 Migration string `json:"migration,omitempty" yaml:"migration,omitempty"` 39 } 40 41 type machineStatus struct { 42 Err error `json:"-" yaml:",omitempty"` 43 JujuStatus statusInfoContents `json:"juju-status,omitempty" yaml:"juju-status,omitempty"` 44 DNSName string `json:"dns-name,omitempty" yaml:"dns-name,omitempty"` 45 IPAddresses []string `json:"ip-addresses,omitempty" yaml:"ip-addresses,omitempty"` 46 InstanceId instance.Id `json:"instance-id,omitempty" yaml:"instance-id,omitempty"` 47 MachineStatus statusInfoContents `json:"machine-status,omitempty" yaml:"machine-status,omitempty"` 48 Series string `json:"series,omitempty" yaml:"series,omitempty"` 49 Id string `json:"-" yaml:"-"` 50 Containers map[string]machineStatus `json:"containers,omitempty" yaml:"containers,omitempty"` 51 Hardware string `json:"hardware,omitempty" yaml:"hardware,omitempty"` 52 HAStatus string `json:"controller-member-status,omitempty" yaml:"controller-member-status,omitempty"` 53 } 54 55 // A goyaml bug means we can't declare these types 56 // locally to the GetYAML methods. 57 type machineStatusNoMarshal machineStatus 58 59 func (s machineStatus) MarshalJSON() ([]byte, error) { 60 if s.Err != nil { 61 return json.Marshal(errorStatus{s.Err.Error()}) 62 } 63 return json.Marshal(machineStatusNoMarshal(s)) 64 } 65 66 func (s machineStatus) MarshalYAML() (interface{}, error) { 67 if s.Err != nil { 68 return errorStatus{s.Err.Error()}, nil 69 } 70 return machineStatusNoMarshal(s), nil 71 } 72 73 type applicationStatus struct { 74 Err error `json:"-" yaml:",omitempty"` 75 Charm string `json:"charm" yaml:"charm"` 76 Series string `json:"series"` 77 OS string `json:"os"` 78 CharmOrigin string `json:"charm-origin" yaml:"charm-origin"` 79 CharmName string `json:"charm-name" yaml:"charm-name"` 80 CharmRev int `json:"charm-rev" yaml:"charm-rev"` 81 CanUpgradeTo string `json:"can-upgrade-to,omitempty" yaml:"can-upgrade-to,omitempty"` 82 Exposed bool `json:"exposed" yaml:"exposed"` 83 Life string `json:"life,omitempty" yaml:"life,omitempty"` 84 StatusInfo statusInfoContents `json:"application-status,omitempty" yaml:"application-status"` 85 Relations map[string][]string `json:"relations,omitempty" yaml:"relations,omitempty"` 86 SubordinateTo []string `json:"subordinate-to,omitempty" yaml:"subordinate-to,omitempty"` 87 Units map[string]unitStatus `json:"units,omitempty" yaml:"units,omitempty"` 88 Version string `json:"version,omitempty" yaml:"version,omitempty"` 89 } 90 91 type applicationStatusNoMarshal applicationStatus 92 93 func (s applicationStatus) MarshalJSON() ([]byte, error) { 94 if s.Err != nil { 95 return json.Marshal(errorStatus{s.Err.Error()}) 96 } 97 return json.Marshal(applicationStatusNoMarshal(s)) 98 } 99 100 func (s applicationStatus) MarshalYAML() (interface{}, error) { 101 if s.Err != nil { 102 return errorStatus{s.Err.Error()}, nil 103 } 104 return applicationStatusNoMarshal(s), nil 105 } 106 107 type meterStatus struct { 108 Color string `json:"color,omitempty" yaml:"color,omitempty"` 109 Message string `json:"message,omitempty" yaml:"message,omitempty"` 110 } 111 112 type unitStatus struct { 113 // New Juju Health Status fields. 114 WorkloadStatusInfo statusInfoContents `json:"workload-status,omitempty" yaml:"workload-status"` 115 JujuStatusInfo statusInfoContents `json:"juju-status,omitempty" yaml:"juju-status"` 116 MeterStatus *meterStatus `json:"meter-status,omitempty" yaml:"meter-status,omitempty"` 117 118 Leader bool `json:"leader,omitempty" yaml:"leader,omitempty"` 119 Charm string `json:"upgrading-from,omitempty" yaml:"upgrading-from,omitempty"` 120 Machine string `json:"machine,omitempty" yaml:"machine,omitempty"` 121 OpenedPorts []string `json:"open-ports,omitempty" yaml:"open-ports,omitempty"` 122 PublicAddress string `json:"public-address,omitempty" yaml:"public-address,omitempty"` 123 Subordinates map[string]unitStatus `json:"subordinates,omitempty" yaml:"subordinates,omitempty"` 124 } 125 126 func (s *formattedStatus) applicationScale(name string) (string, bool) { 127 // The current unit count are units that are either in Idle or Executing status. 128 // In other words, units that are active and available. 129 currentUnitCount := 0 130 desiredUnitCount := 0 131 132 app := s.Applications[name] 133 match := func(u unitStatus) { 134 desiredUnitCount += 1 135 switch u.JujuStatusInfo.Current { 136 case status.Executing, status.Idle: 137 currentUnitCount += 1 138 } 139 } 140 // If the app is subordinate to other units, then this is a subordinate charm. 141 if len(app.SubordinateTo) > 0 { 142 for _, a := range s.Applications { 143 for _, u := range a.Units { 144 for sub, subStatus := range u.Subordinates { 145 if subAppName, _ := names.UnitApplication(sub); subAppName == name { 146 match(subStatus) 147 } 148 } 149 } 150 } 151 } else { 152 for _, u := range app.Units { 153 match(u) 154 } 155 } 156 if currentUnitCount == desiredUnitCount { 157 return fmt.Sprint(currentUnitCount), false 158 } 159 return fmt.Sprintf("%d/%d", currentUnitCount, desiredUnitCount), true 160 } 161 162 type statusInfoContents struct { 163 Err error `json:"-" yaml:",omitempty"` 164 Current status.Status `json:"current,omitempty" yaml:"current,omitempty"` 165 Message string `json:"message,omitempty" yaml:"message,omitempty"` 166 Since string `json:"since,omitempty" yaml:"since,omitempty"` 167 Version string `json:"version,omitempty" yaml:"version,omitempty"` 168 Life string `json:"life,omitempty" yaml:"life,omitempty"` 169 } 170 171 type statusInfoContentsNoMarshal statusInfoContents 172 173 func (s statusInfoContents) MarshalJSON() ([]byte, error) { 174 if s.Err != nil { 175 return json.Marshal(errorStatus{s.Err.Error()}) 176 } 177 return json.Marshal(statusInfoContentsNoMarshal(s)) 178 } 179 180 func (s statusInfoContents) MarshalYAML() (interface{}, error) { 181 if s.Err != nil { 182 return errorStatus{s.Err.Error()}, nil 183 } 184 return statusInfoContentsNoMarshal(s), nil 185 } 186 187 type unitStatusNoMarshal unitStatus 188 189 func (s unitStatus) MarshalJSON() ([]byte, error) { 190 if s.WorkloadStatusInfo.Err != nil { 191 return json.Marshal(errorStatus{s.WorkloadStatusInfo.Err.Error()}) 192 } 193 return json.Marshal(unitStatusNoMarshal(s)) 194 } 195 196 func (s unitStatus) MarshalYAML() (interface{}, error) { 197 if s.WorkloadStatusInfo.Err != nil { 198 return errorStatus{s.WorkloadStatusInfo.Err.Error()}, nil 199 } 200 return unitStatusNoMarshal(s), nil 201 }