github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/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  	"github.com/juju/juju/testing"
    15  )
    16  
    17  type ServiceStatusSuite struct {
    18  	ConnSuite
    19  	service *state.Application
    20  }
    21  
    22  var _ = gc.Suite(&ServiceStatusSuite{})
    23  
    24  func (s *ServiceStatusSuite) SetUpTest(c *gc.C) {
    25  	s.ConnSuite.SetUpTest(c)
    26  	s.service = s.Factory.MakeApplication(c, nil)
    27  }
    28  
    29  func (s *ServiceStatusSuite) TestInitialStatus(c *gc.C) {
    30  	s.checkInitialStatus(c)
    31  }
    32  
    33  func (s *ServiceStatusSuite) checkInitialStatus(c *gc.C) {
    34  	statusInfo, err := s.service.Status()
    35  	c.Check(err, jc.ErrorIsNil)
    36  	checkInitialWorkloadStatus(c, statusInfo)
    37  }
    38  
    39  func (s *ServiceStatusSuite) TestSetUnknownStatus(c *gc.C) {
    40  	now := testing.ZeroTime()
    41  	sInfo := status.StatusInfo{
    42  		Status:  status.Status("vliegkat"),
    43  		Message: "orville",
    44  		Since:   &now,
    45  	}
    46  	err := s.service.SetStatus(sInfo)
    47  	c.Check(err, gc.ErrorMatches, `cannot set invalid status "vliegkat"`)
    48  
    49  	s.checkInitialStatus(c)
    50  }
    51  
    52  func (s *ServiceStatusSuite) TestSetOverwritesData(c *gc.C) {
    53  	now := testing.ZeroTime()
    54  	sInfo := status.StatusInfo{
    55  		Status:  status.Active,
    56  		Message: "healthy",
    57  		Data: map[string]interface{}{
    58  			"pew.pew": "zap",
    59  		},
    60  		Since: &now,
    61  	}
    62  	err := s.service.SetStatus(sInfo)
    63  	c.Check(err, jc.ErrorIsNil)
    64  
    65  	s.checkGetSetStatus(c)
    66  }
    67  
    68  func (s *ServiceStatusSuite) TestGetSetStatusAlive(c *gc.C) {
    69  	s.checkGetSetStatus(c)
    70  }
    71  
    72  func (s *ServiceStatusSuite) checkGetSetStatus(c *gc.C) {
    73  	now := testing.ZeroTime()
    74  	sInfo := status.StatusInfo{
    75  		Status:  status.Active,
    76  		Message: "healthy",
    77  		Data: map[string]interface{}{
    78  			"$ping": map[string]interface{}{
    79  				"foo.bar": 123,
    80  			},
    81  		},
    82  		Since: &now,
    83  	}
    84  	err := s.service.SetStatus(sInfo)
    85  	c.Check(err, jc.ErrorIsNil)
    86  
    87  	service, err := s.State.Application(s.service.Name())
    88  	c.Assert(err, jc.ErrorIsNil)
    89  
    90  	statusInfo, err := service.Status()
    91  	c.Check(err, jc.ErrorIsNil)
    92  	c.Check(statusInfo.Status, gc.Equals, status.Active)
    93  	c.Check(statusInfo.Message, gc.Equals, "healthy")
    94  	c.Check(statusInfo.Data, jc.DeepEquals, map[string]interface{}{
    95  		"$ping": map[string]interface{}{
    96  			"foo.bar": 123,
    97  		},
    98  	})
    99  	c.Check(statusInfo.Since, gc.NotNil)
   100  }
   101  
   102  func (s *ServiceStatusSuite) TestGetSetStatusDying(c *gc.C) {
   103  	_, err := s.service.AddUnit()
   104  	c.Assert(err, jc.ErrorIsNil)
   105  	err = s.service.Destroy()
   106  	c.Assert(err, jc.ErrorIsNil)
   107  
   108  	s.checkGetSetStatus(c)
   109  }
   110  
   111  func (s *ServiceStatusSuite) TestGetSetStatusGone(c *gc.C) {
   112  	err := s.service.Destroy()
   113  	c.Assert(err, jc.ErrorIsNil)
   114  
   115  	now := testing.ZeroTime()
   116  	sInfo := status.StatusInfo{
   117  		Status:  status.Active,
   118  		Message: "not really",
   119  		Since:   &now,
   120  	}
   121  	err = s.service.SetStatus(sInfo)
   122  	c.Check(err, gc.ErrorMatches, `cannot set status: application not found`)
   123  
   124  	statusInfo, err := s.service.Status()
   125  	c.Check(err, gc.ErrorMatches, `cannot get status: application not found`)
   126  	c.Check(statusInfo, gc.DeepEquals, status.StatusInfo{})
   127  }
   128  
   129  func (s *ServiceStatusSuite) TestSetStatusSince(c *gc.C) {
   130  	now := testing.ZeroTime()
   131  	sInfo := status.StatusInfo{
   132  		Status:  status.Maintenance,
   133  		Message: "",
   134  		Since:   &now,
   135  	}
   136  	err := s.service.SetStatus(sInfo)
   137  	c.Assert(err, jc.ErrorIsNil)
   138  	statusInfo, err := s.service.Status()
   139  	c.Assert(err, jc.ErrorIsNil)
   140  	firstTime := statusInfo.Since
   141  	c.Assert(firstTime, gc.NotNil)
   142  	c.Assert(timeBeforeOrEqual(now, *firstTime), jc.IsTrue)
   143  
   144  	// Setting the same status a second time also updates the timestamp.
   145  	now = now.Add(1 * time.Second)
   146  	sInfo = status.StatusInfo{
   147  		Status:  status.Maintenance,
   148  		Message: "",
   149  		Since:   &now,
   150  	}
   151  	err = s.service.SetStatus(sInfo)
   152  	c.Assert(err, jc.ErrorIsNil)
   153  	statusInfo, err = s.service.Status()
   154  	c.Assert(err, jc.ErrorIsNil)
   155  	c.Assert(timeBeforeOrEqual(*firstTime, *statusInfo.Since), jc.IsTrue)
   156  }
   157  
   158  func (s *ServiceStatusSuite) TestDeriveStatus(c *gc.C) {
   159  	// NOTE(fwereade): as detailed in the code, this implementation is not sane.
   160  	// The specified behaviour is arguably sane, but the code is in the wrong
   161  	// place.
   162  
   163  	// Create a unit with each possible status.
   164  	addUnit := func(unitStatus status.Status) *state.Unit {
   165  		unit, err := s.service.AddUnit()
   166  		c.Assert(err, gc.IsNil)
   167  		now := testing.ZeroTime()
   168  		sInfo := status.StatusInfo{
   169  			Status:  unitStatus,
   170  			Message: "blam",
   171  			Since:   &now,
   172  		}
   173  		err = unit.SetStatus(sInfo)
   174  		c.Assert(err, gc.IsNil)
   175  		return unit
   176  	}
   177  	blockedUnit := addUnit(status.Blocked)
   178  	waitingUnit := addUnit(status.Waiting)
   179  	maintenanceUnit := addUnit(status.Maintenance)
   180  	terminatedUnit := addUnit(status.Terminated)
   181  	activeUnit := addUnit(status.Active)
   182  	unknownUnit := addUnit(status.Unknown)
   183  
   184  	// ...and create one with error status by setting it on the agent :-/.
   185  	errorUnit, err := s.service.AddUnit()
   186  	c.Assert(err, gc.IsNil)
   187  	now := testing.ZeroTime()
   188  	sInfo := status.StatusInfo{
   189  		Status:  status.Error,
   190  		Message: "blam",
   191  		Since:   &now,
   192  	}
   193  	err = errorUnit.Agent().SetStatus(sInfo)
   194  	c.Assert(err, gc.IsNil)
   195  
   196  	// For each status, in order of severity, check the service status is
   197  	// derived from that unit status; then remove that unit and proceed to
   198  	// the next severity.
   199  	checkAndRemove := func(unit *state.Unit, status status.Status) {
   200  		info, err := s.service.Status()
   201  		c.Check(err, jc.ErrorIsNil)
   202  		c.Check(info.Status, gc.Equals, status)
   203  
   204  		err = unit.Destroy()
   205  		c.Assert(err, jc.ErrorIsNil)
   206  		err = unit.EnsureDead()
   207  		c.Assert(err, jc.ErrorIsNil)
   208  		err = unit.Remove()
   209  		c.Assert(err, jc.ErrorIsNil)
   210  	}
   211  	checkAndRemove(errorUnit, status.Error)
   212  	checkAndRemove(blockedUnit, status.Blocked)
   213  	checkAndRemove(waitingUnit, status.Waiting)
   214  	checkAndRemove(maintenanceUnit, status.Maintenance)
   215  	checkAndRemove(terminatedUnit, status.Terminated)
   216  	checkAndRemove(activeUnit, status.Active)
   217  	checkAndRemove(unknownUnit, status.Unknown)
   218  }
   219  
   220  func (s *ServiceStatusSuite) TestServiceStatusOverridesDerivedStatus(c *gc.C) {
   221  	unit, err := s.service.AddUnit()
   222  	c.Assert(err, gc.IsNil)
   223  	now := testing.ZeroTime()
   224  	sInfo := status.StatusInfo{
   225  		Status:  status.Blocked,
   226  		Message: "pow",
   227  		Since:   &now,
   228  	}
   229  	err = unit.SetStatus(sInfo)
   230  	c.Assert(err, gc.IsNil)
   231  	sInfo = status.StatusInfo{
   232  		Status:  status.Maintenance,
   233  		Message: "zot",
   234  		Since:   &now,
   235  	}
   236  	err = s.service.SetStatus(sInfo)
   237  	c.Assert(err, gc.IsNil)
   238  
   239  	info, err := s.service.Status()
   240  	c.Check(err, jc.ErrorIsNil)
   241  	c.Check(info.Status, gc.Equals, status.Maintenance)
   242  }