github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/apiserver/common/setstatus_test.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package common_test
     5  
     6  import (
     7  	"time"
     8  
     9  	"github.com/juju/names"
    10  	jc "github.com/juju/testing/checkers"
    11  	gc "gopkg.in/check.v1"
    12  
    13  	"github.com/juju/juju/apiserver/common"
    14  	"github.com/juju/juju/apiserver/params"
    15  	"github.com/juju/juju/state"
    16  	"github.com/juju/juju/testing/factory"
    17  )
    18  
    19  type statusSetterSuite struct {
    20  	statusBaseSuite
    21  	setter *common.StatusSetter
    22  }
    23  
    24  var _ = gc.Suite(&statusSetterSuite{})
    25  
    26  func (s *statusSetterSuite) SetUpTest(c *gc.C) {
    27  	s.statusBaseSuite.SetUpTest(c)
    28  
    29  	s.setter = common.NewStatusSetter(s.State, func() (common.AuthFunc, error) {
    30  		return s.authFunc, nil
    31  	})
    32  }
    33  
    34  func (s *statusSetterSuite) TestUnauthorized(c *gc.C) {
    35  	tag := names.NewMachineTag("42")
    36  	s.badTag = tag
    37  	result, err := s.setter.SetStatus(params.SetStatus{[]params.EntityStatusArgs{{
    38  		Tag:    tag.String(),
    39  		Status: params.StatusExecuting,
    40  	}}})
    41  	c.Assert(err, jc.ErrorIsNil)
    42  	c.Assert(result.Results, gc.HasLen, 1)
    43  	c.Assert(result.Results[0].Error, jc.Satisfies, params.IsCodeUnauthorized)
    44  }
    45  
    46  func (s *statusSetterSuite) TestNotATag(c *gc.C) {
    47  	result, err := s.setter.SetStatus(params.SetStatus{[]params.EntityStatusArgs{{
    48  		Tag:    "not a tag",
    49  		Status: params.StatusExecuting,
    50  	}}})
    51  	c.Assert(err, jc.ErrorIsNil)
    52  	c.Assert(result.Results, gc.HasLen, 1)
    53  	c.Assert(result.Results[0].Error, gc.ErrorMatches, `"not a tag" is not a valid tag`)
    54  }
    55  
    56  func (s *statusSetterSuite) TestNotFound(c *gc.C) {
    57  	result, err := s.setter.SetStatus(params.SetStatus{[]params.EntityStatusArgs{{
    58  		Tag:    names.NewMachineTag("42").String(),
    59  		Status: params.StatusDown,
    60  	}}})
    61  	c.Assert(err, jc.ErrorIsNil)
    62  	c.Assert(result.Results, gc.HasLen, 1)
    63  	c.Assert(result.Results[0].Error, jc.Satisfies, params.IsCodeNotFound)
    64  }
    65  
    66  func (s *statusSetterSuite) TestSetMachineStatus(c *gc.C) {
    67  	machine := s.Factory.MakeMachine(c, nil)
    68  	result, err := s.setter.SetStatus(params.SetStatus{[]params.EntityStatusArgs{{
    69  		Tag:    machine.Tag().String(),
    70  		Status: params.StatusStarted,
    71  	}}})
    72  	c.Assert(err, jc.ErrorIsNil)
    73  	c.Assert(result.Results, gc.HasLen, 1)
    74  	c.Assert(result.Results[0].Error, gc.IsNil)
    75  
    76  	err = machine.Refresh()
    77  	c.Assert(err, jc.ErrorIsNil)
    78  	status, err := machine.Status()
    79  	c.Assert(err, jc.ErrorIsNil)
    80  	c.Assert(status.Status, gc.Equals, state.StatusStarted)
    81  }
    82  
    83  func (s *statusSetterSuite) TestSetUnitStatus(c *gc.C) {
    84  	// The status has to be a valid workload status, because get status
    85  	// on the unit returns the workload status not the agent status as it
    86  	// does on a machine.
    87  	unit := s.Factory.MakeUnit(c, &factory.UnitParams{Status: &state.StatusInfo{
    88  		Status: state.StatusMaintenance,
    89  	}})
    90  	result, err := s.setter.SetStatus(params.SetStatus{[]params.EntityStatusArgs{{
    91  		Tag:    unit.Tag().String(),
    92  		Status: params.StatusActive,
    93  	}}})
    94  	c.Assert(err, jc.ErrorIsNil)
    95  	c.Assert(result.Results, gc.HasLen, 1)
    96  	c.Assert(result.Results[0].Error, gc.IsNil)
    97  
    98  	err = unit.Refresh()
    99  	c.Assert(err, jc.ErrorIsNil)
   100  	status, err := unit.Status()
   101  	c.Assert(err, jc.ErrorIsNil)
   102  	c.Assert(status.Status, gc.Equals, state.StatusActive)
   103  }
   104  
   105  func (s *statusSetterSuite) TestSetServiceStatus(c *gc.C) {
   106  	// Calls to set the status of a service should be going through the
   107  	// ServiceStatusSetter that checks for leadership, so permission denied
   108  	// here.
   109  	service := s.Factory.MakeService(c, &factory.ServiceParams{Status: &state.StatusInfo{
   110  		Status: state.StatusMaintenance,
   111  	}})
   112  	result, err := s.setter.SetStatus(params.SetStatus{[]params.EntityStatusArgs{{
   113  		Tag:    service.Tag().String(),
   114  		Status: params.StatusActive,
   115  	}}})
   116  	c.Assert(err, jc.ErrorIsNil)
   117  	c.Assert(result.Results, gc.HasLen, 1)
   118  	c.Assert(result.Results[0].Error, jc.Satisfies, params.IsCodeUnauthorized)
   119  
   120  	err = service.Refresh()
   121  	c.Assert(err, jc.ErrorIsNil)
   122  	status, err := service.Status()
   123  	c.Assert(err, jc.ErrorIsNil)
   124  	c.Assert(status.Status, gc.Equals, state.StatusMaintenance)
   125  }
   126  
   127  func (s *statusSetterSuite) TestBulk(c *gc.C) {
   128  	s.badTag = names.NewMachineTag("42")
   129  	result, err := s.setter.SetStatus(params.SetStatus{[]params.EntityStatusArgs{{
   130  		Tag:    s.badTag.String(),
   131  		Status: params.StatusActive,
   132  	}, {
   133  		Tag:    "bad-tag",
   134  		Status: params.StatusActive,
   135  	}}})
   136  	c.Assert(err, jc.ErrorIsNil)
   137  	c.Assert(result.Results, gc.HasLen, 2)
   138  	c.Assert(result.Results[0].Error, jc.Satisfies, params.IsCodeUnauthorized)
   139  	c.Assert(result.Results[1].Error, gc.ErrorMatches, `"bad-tag" is not a valid tag`)
   140  }
   141  
   142  type serviceStatusSetterSuite struct {
   143  	statusBaseSuite
   144  	setter *common.ServiceStatusSetter
   145  }
   146  
   147  var _ = gc.Suite(&serviceStatusSetterSuite{})
   148  
   149  func (s *serviceStatusSetterSuite) SetUpTest(c *gc.C) {
   150  	s.statusBaseSuite.SetUpTest(c)
   151  
   152  	s.setter = common.NewServiceStatusSetter(s.State, func() (common.AuthFunc, error) {
   153  		return s.authFunc, nil
   154  	})
   155  }
   156  
   157  func (s *serviceStatusSetterSuite) TestUnauthorized(c *gc.C) {
   158  	// Machines are unauthorized since they are not units
   159  	tag := names.NewUnitTag("foo/0")
   160  	s.badTag = tag
   161  	result, err := s.setter.SetStatus(params.SetStatus{[]params.EntityStatusArgs{{
   162  		Tag:    tag.String(),
   163  		Status: params.StatusActive,
   164  	}}})
   165  	c.Assert(err, jc.ErrorIsNil)
   166  	c.Assert(result.Results, gc.HasLen, 1)
   167  	c.Assert(result.Results[0].Error, jc.Satisfies, params.IsCodeUnauthorized)
   168  }
   169  
   170  func (s *serviceStatusSetterSuite) TestNotATag(c *gc.C) {
   171  	result, err := s.setter.SetStatus(params.SetStatus{[]params.EntityStatusArgs{{
   172  		Tag:    "not a tag",
   173  		Status: params.StatusActive,
   174  	}}})
   175  	c.Assert(err, jc.ErrorIsNil)
   176  	c.Assert(result.Results, gc.HasLen, 1)
   177  	c.Assert(result.Results[0].Error, gc.ErrorMatches, `"not a tag" is not a valid tag`)
   178  }
   179  
   180  func (s *serviceStatusSetterSuite) TestNotFound(c *gc.C) {
   181  	result, err := s.setter.SetStatus(params.SetStatus{[]params.EntityStatusArgs{{
   182  		Tag:    names.NewUnitTag("foo/0").String(),
   183  		Status: params.StatusActive,
   184  	}}})
   185  	c.Assert(err, jc.ErrorIsNil)
   186  	c.Assert(result.Results, gc.HasLen, 1)
   187  	c.Assert(result.Results[0].Error, jc.Satisfies, params.IsCodeNotFound)
   188  }
   189  
   190  func (s *serviceStatusSetterSuite) TestSetMachineStatus(c *gc.C) {
   191  	machine := s.Factory.MakeMachine(c, nil)
   192  	result, err := s.setter.SetStatus(params.SetStatus{[]params.EntityStatusArgs{{
   193  		Tag:    machine.Tag().String(),
   194  		Status: params.StatusActive,
   195  	}}})
   196  	c.Assert(err, jc.ErrorIsNil)
   197  	c.Assert(result.Results, gc.HasLen, 1)
   198  	// Can't call set service status on a machine.
   199  	c.Assert(result.Results[0].Error, jc.Satisfies, params.IsCodeUnauthorized)
   200  }
   201  
   202  func (s *serviceStatusSetterSuite) TestSetServiceStatus(c *gc.C) {
   203  	// TODO: the correct way to fix this is to have the authorizer on the
   204  	// simple status setter to check to see if the unit (authTag) is a leader
   205  	// and able to set the service status. However, that is for another day.
   206  	service := s.Factory.MakeService(c, &factory.ServiceParams{Status: &state.StatusInfo{
   207  		Status: state.StatusMaintenance,
   208  	}})
   209  	result, err := s.setter.SetStatus(params.SetStatus{[]params.EntityStatusArgs{{
   210  		Tag:    service.Tag().String(),
   211  		Status: params.StatusActive,
   212  	}}})
   213  	c.Assert(err, jc.ErrorIsNil)
   214  	c.Assert(result.Results, gc.HasLen, 1)
   215  	// Can't call set service status on a service. Weird I know, but the only
   216  	// way is to go through the unit leader.
   217  	c.Assert(result.Results[0].Error, jc.Satisfies, params.IsCodeUnauthorized)
   218  }
   219  
   220  func (s *serviceStatusSetterSuite) TestSetUnitStatusNotLeader(c *gc.C) {
   221  	// If the unit isn't the leader, it can't set it.
   222  	unit := s.Factory.MakeUnit(c, &factory.UnitParams{Status: &state.StatusInfo{
   223  		Status: state.StatusMaintenance,
   224  	}})
   225  	result, err := s.setter.SetStatus(params.SetStatus{[]params.EntityStatusArgs{{
   226  		Tag:    unit.Tag().String(),
   227  		Status: params.StatusActive,
   228  	}}})
   229  	c.Assert(err, jc.ErrorIsNil)
   230  	c.Assert(result.Results, gc.HasLen, 1)
   231  	status := result.Results[0]
   232  	c.Assert(status.Error, gc.ErrorMatches, ".* is not leader of .*")
   233  }
   234  
   235  func (s *serviceStatusSetterSuite) TestSetUnitStatusIsLeader(c *gc.C) {
   236  	service := s.Factory.MakeService(c, &factory.ServiceParams{Status: &state.StatusInfo{
   237  		Status: state.StatusMaintenance,
   238  	}})
   239  	unit := s.Factory.MakeUnit(c, &factory.UnitParams{
   240  		Service: service,
   241  		Status: &state.StatusInfo{
   242  			Status: state.StatusMaintenance,
   243  		}})
   244  	s.State.LeadershipClaimer().ClaimLeadership(
   245  		service.Name(),
   246  		unit.Name(),
   247  		time.Minute)
   248  	result, err := s.setter.SetStatus(params.SetStatus{[]params.EntityStatusArgs{{
   249  		Tag:    unit.Tag().String(),
   250  		Status: params.StatusActive,
   251  	}}})
   252  
   253  	c.Assert(err, jc.ErrorIsNil)
   254  	c.Assert(result.Results, gc.HasLen, 1)
   255  	c.Assert(result.Results[0].Error, gc.IsNil)
   256  
   257  	err = service.Refresh()
   258  	c.Assert(err, jc.ErrorIsNil)
   259  	status, err := service.Status()
   260  	c.Assert(err, jc.ErrorIsNil)
   261  	c.Assert(status.Status, gc.Equals, state.StatusActive)
   262  }
   263  
   264  func (s *serviceStatusSetterSuite) TestBulk(c *gc.C) {
   265  	s.badTag = names.NewMachineTag("42")
   266  	machine := s.Factory.MakeMachine(c, nil)
   267  	result, err := s.setter.SetStatus(params.SetStatus{[]params.EntityStatusArgs{{
   268  		Tag:    s.badTag.String(),
   269  		Status: params.StatusActive,
   270  	}, {
   271  		Tag:    machine.Tag().String(),
   272  		Status: params.StatusActive,
   273  	}, {
   274  		Tag:    "bad-tag",
   275  		Status: params.StatusActive,
   276  	}}})
   277  	c.Assert(err, jc.ErrorIsNil)
   278  	c.Assert(result.Results, gc.HasLen, 3)
   279  	c.Assert(result.Results[0].Error, jc.Satisfies, params.IsCodeUnauthorized)
   280  	c.Assert(result.Results[1].Error, jc.Satisfies, params.IsCodeUnauthorized)
   281  	c.Assert(result.Results[2].Error, gc.ErrorMatches, `"bad-tag" is not a valid tag`)
   282  }