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

     1  // Copyright 2012-2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package state_test
     5  
     6  import (
     7  	"time"
     8  
     9  	jc "github.com/juju/testing/checkers"
    10  	gc "gopkg.in/check.v1"
    11  
    12  	"github.com/juju/juju/state"
    13  	"github.com/juju/juju/status"
    14  	"github.com/juju/juju/testing"
    15  )
    16  
    17  type StatusUnitAgentSuite struct {
    18  	ConnSuite
    19  	unit  *state.Unit
    20  	agent *state.UnitAgent
    21  }
    22  
    23  var _ = gc.Suite(&StatusUnitAgentSuite{})
    24  
    25  func (s *StatusUnitAgentSuite) SetUpTest(c *gc.C) {
    26  	s.ConnSuite.SetUpTest(c)
    27  	s.unit = s.Factory.MakeUnit(c, nil)
    28  	s.agent = s.unit.Agent()
    29  }
    30  
    31  func (s *StatusUnitAgentSuite) TestInitialStatus(c *gc.C) {
    32  	s.checkInitialStatus(c)
    33  }
    34  
    35  func (s *StatusUnitAgentSuite) checkInitialStatus(c *gc.C) {
    36  	statusInfo, err := s.agent.Status()
    37  	c.Check(err, jc.ErrorIsNil)
    38  	checkInitialUnitAgentStatus(c, statusInfo)
    39  }
    40  
    41  func (s *StatusUnitAgentSuite) TestSetUnknownStatus(c *gc.C) {
    42  	now := testing.ZeroTime()
    43  	sInfo := status.StatusInfo{
    44  		Status:  status.Status("vliegkat"),
    45  		Message: "orville",
    46  		Since:   &now,
    47  	}
    48  	err := s.agent.SetStatus(sInfo)
    49  	c.Check(err, gc.ErrorMatches, `cannot set invalid status "vliegkat"`)
    50  
    51  	s.checkInitialStatus(c)
    52  }
    53  
    54  func (s *StatusUnitAgentSuite) TestSetErrorStatusWithoutInfo(c *gc.C) {
    55  	now := testing.ZeroTime()
    56  	sInfo := status.StatusInfo{
    57  		Status:  status.Error,
    58  		Message: "",
    59  		Since:   &now,
    60  	}
    61  	err := s.agent.SetStatus(sInfo)
    62  	c.Check(err, gc.ErrorMatches, `cannot set status "error" without info`)
    63  
    64  	s.checkInitialStatus(c)
    65  }
    66  
    67  func (s *StatusUnitAgentSuite) TestSetOverwritesData(c *gc.C) {
    68  	now := testing.ZeroTime()
    69  	sInfo := status.StatusInfo{
    70  		Status:  status.Idle,
    71  		Message: "something",
    72  		Data: map[string]interface{}{
    73  			"pew.pew": "zap",
    74  		},
    75  		Since: &now,
    76  	}
    77  	err := s.agent.SetStatus(sInfo)
    78  	c.Check(err, jc.ErrorIsNil)
    79  
    80  	s.checkGetSetStatus(c)
    81  }
    82  
    83  func (s *StatusUnitAgentSuite) TestGetSetStatusAlive(c *gc.C) {
    84  	s.checkGetSetStatus(c)
    85  }
    86  
    87  func (s *StatusUnitAgentSuite) checkGetSetStatus(c *gc.C) {
    88  	now := testing.ZeroTime()
    89  	sInfo := status.StatusInfo{
    90  		Status:  status.Idle,
    91  		Message: "something",
    92  		Data: map[string]interface{}{
    93  			"$foo":    "bar",
    94  			"baz.qux": "ping",
    95  			"pong": map[string]interface{}{
    96  				"$unset": "txn-revno",
    97  			},
    98  		},
    99  		Since: &now,
   100  	}
   101  	err := s.agent.SetStatus(sInfo)
   102  	c.Check(err, jc.ErrorIsNil)
   103  
   104  	unit, err := s.State.Unit(s.unit.Name())
   105  	c.Assert(err, jc.ErrorIsNil)
   106  	agent := unit.Agent()
   107  
   108  	statusInfo, err := agent.Status()
   109  	c.Check(err, jc.ErrorIsNil)
   110  	c.Check(statusInfo.Status, gc.Equals, status.Idle)
   111  	c.Check(statusInfo.Message, gc.Equals, "something")
   112  	c.Check(statusInfo.Data, jc.DeepEquals, map[string]interface{}{
   113  		"$foo":    "bar",
   114  		"baz.qux": "ping",
   115  		"pong": map[string]interface{}{
   116  			"$unset": "txn-revno",
   117  		},
   118  	})
   119  	c.Check(statusInfo.Since, gc.NotNil)
   120  }
   121  
   122  func (s *StatusUnitAgentSuite) TestGetSetStatusDying(c *gc.C) {
   123  	preventUnitDestroyRemove(c, s.unit)
   124  	err := s.unit.Destroy()
   125  	c.Assert(err, jc.ErrorIsNil)
   126  
   127  	s.checkGetSetStatus(c)
   128  }
   129  
   130  func (s *StatusUnitAgentSuite) TestGetSetStatusDead(c *gc.C) {
   131  	preventUnitDestroyRemove(c, s.unit)
   132  	err := s.unit.Destroy()
   133  	c.Assert(err, jc.ErrorIsNil)
   134  	err = s.unit.EnsureDead()
   135  	c.Assert(err, jc.ErrorIsNil)
   136  
   137  	// NOTE: it would be more technically correct to reject status updates
   138  	// while Dead, but it's easier and clearer, not to mention more efficient,
   139  	// to just depend on status doc existence.
   140  	s.checkGetSetStatus(c)
   141  }
   142  
   143  func (s *StatusUnitAgentSuite) TestGetSetStatusGone(c *gc.C) {
   144  	err := s.unit.Destroy()
   145  	c.Assert(err, jc.ErrorIsNil)
   146  
   147  	now := testing.ZeroTime()
   148  	sInfo := status.StatusInfo{
   149  		Status:  status.Idle,
   150  		Message: "not really",
   151  		Since:   &now,
   152  	}
   153  	err = s.agent.SetStatus(sInfo)
   154  	c.Check(err, gc.ErrorMatches, `cannot set status: agent not found`)
   155  
   156  	statusInfo, err := s.agent.Status()
   157  	c.Check(err, gc.ErrorMatches, `cannot get status: agent not found`)
   158  	c.Check(statusInfo, gc.DeepEquals, status.StatusInfo{})
   159  }
   160  
   161  func (s *StatusUnitAgentSuite) TestGetSetErrorStatus(c *gc.C) {
   162  	now := testing.ZeroTime()
   163  	sInfo := status.StatusInfo{
   164  		Status:  status.Error,
   165  		Message: "test-hook failed",
   166  		Data: map[string]interface{}{
   167  			"foo": "bar",
   168  		},
   169  		Since: &now,
   170  	}
   171  	err := s.agent.SetStatus(sInfo)
   172  	c.Assert(err, jc.ErrorIsNil)
   173  
   174  	// Agent error is reported as unit error.
   175  	statusInfo, err := s.unit.Status()
   176  	c.Check(err, jc.ErrorIsNil)
   177  	c.Check(statusInfo.Status, gc.Equals, status.Error)
   178  	c.Check(statusInfo.Message, gc.Equals, "test-hook failed")
   179  	c.Check(statusInfo.Data, gc.DeepEquals, map[string]interface{}{
   180  		"foo": "bar",
   181  	})
   182  
   183  	// For agents, error is reported as idle.
   184  	statusInfo, err = s.agent.Status()
   185  	c.Check(err, jc.ErrorIsNil)
   186  	c.Check(statusInfo.Status, gc.Equals, status.Idle)
   187  	c.Check(statusInfo.Message, gc.Equals, "")
   188  	c.Check(statusInfo.Data, gc.HasLen, 0)
   189  }
   190  
   191  func timeBeforeOrEqual(timeBefore, timeOther time.Time) bool {
   192  	return timeBefore.Before(timeOther) || timeBefore.Equal(timeOther)
   193  }
   194  
   195  func (s *StatusUnitAgentSuite) TestSetAgentStatusSince(c *gc.C) {
   196  	now := testing.ZeroTime()
   197  	sInfo := status.StatusInfo{
   198  		Status:  status.Idle,
   199  		Message: "",
   200  		Since:   &now,
   201  	}
   202  	err := s.agent.SetStatus(sInfo)
   203  	c.Assert(err, jc.ErrorIsNil)
   204  	statusInfo, err := s.agent.Status()
   205  	c.Assert(err, jc.ErrorIsNil)
   206  	firstTime := statusInfo.Since
   207  	c.Assert(firstTime, gc.NotNil)
   208  	c.Assert(timeBeforeOrEqual(now, *firstTime), jc.IsTrue)
   209  
   210  	// Setting the same status a second time also updates the timestamp.
   211  	now = now.Add(1 * time.Second)
   212  	sInfo = status.StatusInfo{
   213  		Status:  status.Idle,
   214  		Message: "",
   215  		Since:   &now,
   216  	}
   217  	err = s.agent.SetStatus(sInfo)
   218  	c.Assert(err, jc.ErrorIsNil)
   219  	statusInfo, err = s.agent.Status()
   220  	c.Assert(err, jc.ErrorIsNil)
   221  	c.Assert(timeBeforeOrEqual(*firstTime, *statusInfo.Since), jc.IsTrue)
   222  }
   223  
   224  func (s *StatusUnitAgentSuite) TestStatusHistoryInitial(c *gc.C) {
   225  	history, err := s.agent.StatusHistory(status.StatusHistoryFilter{Size: 1})
   226  	c.Check(err, jc.ErrorIsNil)
   227  	c.Assert(history, gc.HasLen, 1)
   228  
   229  	checkInitialUnitAgentStatus(c, history[0])
   230  }
   231  
   232  func (s *StatusUnitAgentSuite) TestStatusHistoryShort(c *gc.C) {
   233  	primeUnitAgentStatusHistory(c, s.agent, 5, 0)
   234  
   235  	history, err := s.agent.StatusHistory(status.StatusHistoryFilter{Size: 10})
   236  	c.Check(err, jc.ErrorIsNil)
   237  	c.Assert(history, gc.HasLen, 6)
   238  
   239  	checkInitialUnitAgentStatus(c, history[5])
   240  	history = history[:5]
   241  	for i, statusInfo := range history {
   242  		checkPrimedUnitAgentStatus(c, statusInfo, 4-i, 0)
   243  	}
   244  }
   245  
   246  func (s *StatusUnitAgentSuite) TestStatusHistoryLong(c *gc.C) {
   247  	primeUnitAgentStatusHistory(c, s.agent, 25, 0)
   248  
   249  	history, err := s.agent.StatusHistory(status.StatusHistoryFilter{Size: 15})
   250  	c.Check(err, jc.ErrorIsNil)
   251  	c.Check(history, gc.HasLen, 15)
   252  	for i, statusInfo := range history {
   253  		checkPrimedUnitAgentStatus(c, statusInfo, 24-i, 0)
   254  	}
   255  }