github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/state/unitagent.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package state
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"gopkg.in/juju/names.v2"
     9  
    10  	"github.com/juju/juju/status"
    11  )
    12  
    13  // UnitAgent represents the state of a service's unit agent.
    14  type UnitAgent struct {
    15  	st   *State
    16  	tag  names.Tag
    17  	name string
    18  	status.StatusHistoryGetter
    19  }
    20  
    21  func newUnitAgent(st *State, tag names.Tag, name string) *UnitAgent {
    22  	unitAgent := &UnitAgent{
    23  		st:   st,
    24  		tag:  tag,
    25  		name: name,
    26  	}
    27  
    28  	return unitAgent
    29  }
    30  
    31  // String returns the unit agent as string.
    32  func (u *UnitAgent) String() string {
    33  	return u.name
    34  }
    35  
    36  // Status returns the status of the unit agent.
    37  func (u *UnitAgent) Status() (status.StatusInfo, error) {
    38  	info, err := getStatus(u.st, u.globalKey(), "agent")
    39  	if err != nil {
    40  		return status.StatusInfo{}, errors.Trace(err)
    41  	}
    42  	// The current health spec says when a hook error occurs, the workload should
    43  	// be in error state, but the state model more correctly records the agent
    44  	// itself as being in error. So we'll do that model translation here.
    45  	// TODO(fwereade): this should absolutely not be happpening in the model.
    46  	if info.Status == status.Error {
    47  		return status.StatusInfo{
    48  			Status:  status.Idle,
    49  			Message: "",
    50  			Data:    map[string]interface{}{},
    51  			Since:   info.Since,
    52  		}, nil
    53  	}
    54  	return info, nil
    55  }
    56  
    57  // SetStatus sets the status of the unit agent. The optional values
    58  // allow to pass additional helpful status data.
    59  func (u *UnitAgent) SetStatus(unitAgentStatus status.StatusInfo) (err error) {
    60  	switch unitAgentStatus.Status {
    61  	case status.Idle, status.Executing, status.Rebooting, status.Failed:
    62  	case status.Error:
    63  		if unitAgentStatus.Message == "" {
    64  			return errors.Errorf("cannot set status %q without info", unitAgentStatus.Status)
    65  		}
    66  	case status.Allocating, status.Lost:
    67  		return errors.Errorf("cannot set status %q", unitAgentStatus.Status)
    68  	default:
    69  		return errors.Errorf("cannot set invalid status %q", unitAgentStatus.Status)
    70  	}
    71  	return setStatus(u.st, setStatusParams{
    72  		badge:     "agent",
    73  		globalKey: u.globalKey(),
    74  		status:    unitAgentStatus.Status,
    75  		message:   unitAgentStatus.Message,
    76  		rawData:   unitAgentStatus.Data,
    77  		updated:   unitAgentStatus.Since,
    78  	})
    79  }
    80  
    81  // StatusHistory returns a slice of at most filter.Size StatusInfo items
    82  // or items as old as filter.Date or items newer than now - filter.Delta time
    83  // representing past statuses for this agent.
    84  func (u *UnitAgent) StatusHistory(filter status.StatusHistoryFilter) ([]status.StatusInfo, error) {
    85  	args := &statusHistoryArgs{
    86  		st:        u.st,
    87  		globalKey: u.globalKey(),
    88  		filter:    filter,
    89  	}
    90  	return statusHistory(args)
    91  }
    92  
    93  // unitAgentGlobalKey returns the global database key for the named unit.
    94  func unitAgentGlobalKey(name string) string {
    95  	return "u#" + name
    96  }
    97  
    98  // globalKey returns the global database key for the unit.
    99  func (u *UnitAgent) globalKey() string {
   100  	return unitAgentGlobalKey(u.name)
   101  }
   102  
   103  // Tag returns a names.Tag identifying this agent's unit.
   104  func (u *UnitAgent) Tag() names.Tag {
   105  	return u.tag
   106  }