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