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  }