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  }