github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/state/status_service_test.go (about)

     1  // Copyright 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  )
    15  
    16  type ServiceStatusSuite struct {
    17  	ConnSuite
    18  	service *state.Service
    19  }
    20  
    21  var _ = gc.Suite(&ServiceStatusSuite{})
    22  
    23  func (s *ServiceStatusSuite) SetUpTest(c *gc.C) {
    24  	s.ConnSuite.SetUpTest(c)
    25  	s.service = s.Factory.MakeService(c, nil)
    26  }
    27  
    28  func (s *ServiceStatusSuite) TestInitialStatus(c *gc.C) {
    29  	s.checkInitialStatus(c)
    30  }
    31  
    32  func (s *ServiceStatusSuite) checkInitialStatus(c *gc.C) {
    33  	statusInfo, err := s.service.Status()
    34  	c.Check(err, jc.ErrorIsNil)
    35  	checkInitialWorkloadStatus(c, statusInfo)
    36  }
    37  
    38  func (s *ServiceStatusSuite) TestSetUnknownStatus(c *gc.C) {
    39  	err := s.service.SetStatus(status.Status("vliegkat"), "orville", nil)
    40  	c.Check(err, gc.ErrorMatches, `cannot set invalid status "vliegkat"`)
    41  
    42  	s.checkInitialStatus(c)
    43  }
    44  
    45  func (s *ServiceStatusSuite) TestSetOverwritesData(c *gc.C) {
    46  	err := s.service.SetStatus(status.StatusActive, "healthy", map[string]interface{}{
    47  		"pew.pew": "zap",
    48  	})
    49  	c.Check(err, jc.ErrorIsNil)
    50  
    51  	s.checkGetSetStatus(c)
    52  }
    53  
    54  func (s *ServiceStatusSuite) TestGetSetStatusAlive(c *gc.C) {
    55  	s.checkGetSetStatus(c)
    56  }
    57  
    58  func (s *ServiceStatusSuite) checkGetSetStatus(c *gc.C) {
    59  	err := s.service.SetStatus(status.StatusActive, "healthy", map[string]interface{}{
    60  		"$ping": map[string]interface{}{
    61  			"foo.bar": 123,
    62  		},
    63  	})
    64  	c.Check(err, jc.ErrorIsNil)
    65  
    66  	service, err := s.State.Service(s.service.Name())
    67  	c.Assert(err, jc.ErrorIsNil)
    68  
    69  	statusInfo, err := service.Status()
    70  	c.Check(err, jc.ErrorIsNil)
    71  	c.Check(statusInfo.Status, gc.Equals, status.StatusActive)
    72  	c.Check(statusInfo.Message, gc.Equals, "healthy")
    73  	c.Check(statusInfo.Data, jc.DeepEquals, map[string]interface{}{
    74  		"$ping": map[string]interface{}{
    75  			"foo.bar": 123,
    76  		},
    77  	})
    78  	c.Check(statusInfo.Since, gc.NotNil)
    79  }
    80  
    81  func (s *ServiceStatusSuite) TestGetSetStatusDying(c *gc.C) {
    82  	_, err := s.service.AddUnit()
    83  	c.Assert(err, jc.ErrorIsNil)
    84  	err = s.service.Destroy()
    85  	c.Assert(err, jc.ErrorIsNil)
    86  
    87  	s.checkGetSetStatus(c)
    88  }
    89  
    90  func (s *ServiceStatusSuite) TestGetSetStatusGone(c *gc.C) {
    91  	err := s.service.Destroy()
    92  	c.Assert(err, jc.ErrorIsNil)
    93  
    94  	err = s.service.SetStatus(status.StatusActive, "not really", nil)
    95  	c.Check(err, gc.ErrorMatches, `cannot set status: service not found`)
    96  
    97  	statusInfo, err := s.service.Status()
    98  	c.Check(err, gc.ErrorMatches, `cannot get status: service not found`)
    99  	c.Check(statusInfo, gc.DeepEquals, status.StatusInfo{})
   100  }
   101  
   102  func (s *ServiceStatusSuite) TestSetStatusSince(c *gc.C) {
   103  	now := time.Now()
   104  
   105  	err := s.service.SetStatus(status.StatusMaintenance, "", nil)
   106  	c.Assert(err, jc.ErrorIsNil)
   107  	statusInfo, err := s.service.Status()
   108  	c.Assert(err, jc.ErrorIsNil)
   109  	firstTime := statusInfo.Since
   110  	c.Assert(firstTime, gc.NotNil)
   111  	c.Assert(timeBeforeOrEqual(now, *firstTime), jc.IsTrue)
   112  
   113  	// Setting the same status a second time also updates the timestamp.
   114  	err = s.service.SetStatus(status.StatusMaintenance, "", nil)
   115  	c.Assert(err, jc.ErrorIsNil)
   116  	statusInfo, err = s.service.Status()
   117  	c.Assert(err, jc.ErrorIsNil)
   118  	c.Assert(timeBeforeOrEqual(*firstTime, *statusInfo.Since), jc.IsTrue)
   119  }
   120  
   121  func (s *ServiceStatusSuite) TestDeriveStatus(c *gc.C) {
   122  	// NOTE(fwereade): as detailed in the code, this implementation is not sane.
   123  	// The specified behaviour is arguably sane, but the code is in the wrong
   124  	// place.
   125  
   126  	// Create a unit with each possible status.
   127  	addUnit := func(status status.Status) *state.Unit {
   128  		unit, err := s.service.AddUnit()
   129  		c.Assert(err, gc.IsNil)
   130  		err = unit.SetStatus(status, "blam", nil)
   131  		c.Assert(err, gc.IsNil)
   132  		return unit
   133  	}
   134  	blockedUnit := addUnit(status.StatusBlocked)
   135  	waitingUnit := addUnit(status.StatusWaiting)
   136  	maintenanceUnit := addUnit(status.StatusMaintenance)
   137  	terminatedUnit := addUnit(status.StatusTerminated)
   138  	activeUnit := addUnit(status.StatusActive)
   139  	unknownUnit := addUnit(status.StatusUnknown)
   140  
   141  	// ...and create one with error status by setting it on the agent :-/.
   142  	errorUnit, err := s.service.AddUnit()
   143  	c.Assert(err, gc.IsNil)
   144  	err = errorUnit.Agent().SetStatus(status.StatusError, "blam", nil)
   145  	c.Assert(err, gc.IsNil)
   146  
   147  	// For each status, in order of severity, check the service status is
   148  	// derived from that unit status; then remove that unit and proceed to
   149  	// the next severity.
   150  	checkAndRemove := func(unit *state.Unit, status status.Status) {
   151  		info, err := s.service.Status()
   152  		c.Check(err, jc.ErrorIsNil)
   153  		c.Check(info.Status, gc.Equals, status)
   154  
   155  		err = unit.Destroy()
   156  		c.Assert(err, jc.ErrorIsNil)
   157  		err = unit.EnsureDead()
   158  		c.Assert(err, jc.ErrorIsNil)
   159  		err = unit.Remove()
   160  		c.Assert(err, jc.ErrorIsNil)
   161  	}
   162  	checkAndRemove(errorUnit, status.StatusError)
   163  	checkAndRemove(blockedUnit, status.StatusBlocked)
   164  	checkAndRemove(waitingUnit, status.StatusWaiting)
   165  	checkAndRemove(maintenanceUnit, status.StatusMaintenance)
   166  	checkAndRemove(terminatedUnit, status.StatusTerminated)
   167  	checkAndRemove(activeUnit, status.StatusActive)
   168  	checkAndRemove(unknownUnit, status.StatusUnknown)
   169  }
   170  
   171  func (s *ServiceStatusSuite) TestServiceStatusOverridesDerivedStatus(c *gc.C) {
   172  	unit, err := s.service.AddUnit()
   173  	c.Assert(err, gc.IsNil)
   174  	err = unit.SetStatus(status.StatusBlocked, "pow", nil)
   175  	c.Assert(err, gc.IsNil)
   176  	err = s.service.SetStatus(status.StatusMaintenance, "zot", nil)
   177  	c.Assert(err, gc.IsNil)
   178  
   179  	info, err := s.service.Status()
   180  	c.Check(err, jc.ErrorIsNil)
   181  	c.Check(info.Status, gc.Equals, status.StatusMaintenance)
   182  }