github.com/Pankov404/juju@v0.0.0-20150703034450-be266991dceb/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  	"fmt"
     8  	"time"
     9  
    10  	"github.com/juju/names"
    11  	jc "github.com/juju/testing/checkers"
    12  	gc "gopkg.in/check.v1"
    13  
    14  	"github.com/juju/juju/apiserver/common"
    15  	"github.com/juju/juju/apiserver/params"
    16  	apiservertesting "github.com/juju/juju/apiserver/testing"
    17  	"github.com/juju/juju/state"
    18  )
    19  
    20  type statusSetterSuite struct{}
    21  
    22  var _ = gc.Suite(&statusSetterSuite{})
    23  
    24  var _ state.StatusSetter = new(fakeStatus)
    25  
    26  type fakeStatus struct {
    27  	state.Entity
    28  	status  state.Status
    29  	info    string
    30  	data    map[string]interface{}
    31  	updated time.Time
    32  	err     error
    33  	fetchError
    34  }
    35  
    36  func (s *fakeStatus) SetStatus(status state.Status, info string, data map[string]interface{}) error {
    37  	s.status = status
    38  	s.info = info
    39  	s.data = data
    40  	s.updated = time.Now()
    41  	return s.err
    42  }
    43  
    44  func (s *fakeStatus) Status() (state.StatusInfo, error) {
    45  	return state.StatusInfo{
    46  		s.status, s.info, s.data, &s.updated,
    47  	}, s.err
    48  }
    49  
    50  func (s *fakeStatus) UpdateStatus(data map[string]interface{}) error {
    51  	for k, v := range data {
    52  		s.data[k] = v
    53  	}
    54  	return s.err
    55  }
    56  
    57  func (*statusSetterSuite) TestSetServiceStatus(c *gc.C) {
    58  	st := &fakeState{
    59  		entities: map[names.Tag]entityWithError{
    60  			u("x/0"): &fakeService{
    61  				tag: serviceTag("x/0"),
    62  				serviceStatus: state.StatusInfo{
    63  					Status:  state.StatusAllocating,
    64  					Message: "blah",
    65  				},
    66  				err: fmt.Errorf("x0 fails"),
    67  			},
    68  			u("x/1"): &fakeService{
    69  				tag: serviceTag("x/1"),
    70  				serviceStatus: state.StatusInfo{
    71  					Status:  state.StatusInstalling,
    72  					Message: "blah",
    73  				},
    74  			},
    75  			u("x/2"): &fakeService{
    76  				tag: serviceTag("x/2"),
    77  				serviceStatus: state.StatusInfo{
    78  					Status:  state.StatusActive,
    79  					Message: "foo",
    80  				},
    81  			},
    82  			u("x/3"): &fakeService{
    83  				tag: serviceTag("x/3"),
    84  				serviceStatus: state.StatusInfo{
    85  					Status:  state.StatusError,
    86  					Message: "some info",
    87  				},
    88  			},
    89  			u("x/4"): &fakeService{
    90  				tag:           serviceTag("x/4"),
    91  				serviceStatus: state.StatusInfo{},
    92  				fetchError:    "x3 error",
    93  			},
    94  			u("x/5"): &fakeService{
    95  				tag: serviceTag("x/5"),
    96  				serviceStatus: state.StatusInfo{
    97  					Status:  state.StatusStopping,
    98  					Message: "blah",
    99  				},
   100  			},
   101  		},
   102  	}
   103  	getCanModify := func() (common.AuthFunc, error) {
   104  		x0 := serviceTag("x/0")
   105  		x1 := serviceTag("x/1")
   106  		x2 := serviceTag("x/2")
   107  		x3 := serviceTag("x/3")
   108  		x4 := serviceTag("x/4")
   109  		x5 := serviceTag("x/5")
   110  		return func(tag names.Tag) bool {
   111  			return tag == x0 || tag == x1 || tag == x2 || tag == x3 || tag == x4 || tag == x5
   112  		}, nil
   113  	}
   114  	s := common.NewServiceStatusSetter(st, getCanModify)
   115  	args := params.SetStatus{
   116  		Entities: []params.EntityStatus{
   117  			{"unit-x-0", params.StatusInstalling, "bar", nil},
   118  			{"unit-x-1", params.StatusActive, "bar", nil},
   119  			{"unit-x-2", params.StatusStopping, "", nil},
   120  			{"unit-x-3", params.StatusAllocating, "not really", nil},
   121  			{"unit-x-4", params.StatusStopping, "", nil},
   122  			{"unit-x-5", params.StatusStopping, "blah", nil},
   123  		},
   124  	}
   125  	leaderCheck := func(_ state.EntityFinder, tag string) (bool, error) {
   126  		if tag == "unit-x-5" {
   127  			return false, nil
   128  		}
   129  		return true, nil
   130  	}
   131  	result, err := common.ServiceSetStatus(s, args, fakeServiceFromUnitTag, leaderCheck)
   132  	c.Assert(err, jc.ErrorIsNil)
   133  	c.Assert(result, gc.DeepEquals, params.ErrorResults{
   134  		Results: []params.ErrorResult{
   135  			{&params.Error{Message: "x0 fails"}},
   136  			{nil},
   137  			{nil},
   138  			{nil},
   139  			{&params.Error{Message: "x3 error"}},
   140  			{&params.Error{"this unit is not the leader", ""}},
   141  		},
   142  	})
   143  	get := func(tag names.Tag) *fakeService {
   144  		return st.entities[tag].(*fakeService)
   145  	}
   146  	c.Assert(get(u("x/1")).serviceStatus.Status, gc.Equals, state.StatusActive)
   147  	c.Assert(get(u("x/1")).serviceStatus.Message, gc.Equals, "bar")
   148  	c.Assert(get(u("x/2")).serviceStatus.Status, gc.Equals, state.StatusStopping)
   149  	c.Assert(get(u("x/2")).serviceStatus.Message, gc.Equals, "")
   150  	c.Assert(get(u("x/3")).serviceStatus.Status, gc.Equals, state.StatusAllocating)
   151  	c.Assert(get(u("x/3")).serviceStatus.Message, gc.Equals, "not really")
   152  	c.Assert(get(u("x/5")).serviceStatus.Status, gc.Equals, state.StatusStopping)
   153  	c.Assert(get(u("x/5")).serviceStatus.Message, gc.Equals, "blah")
   154  
   155  }
   156  
   157  func (*statusSetterSuite) TestSetServiceStatusNotLeader(c *gc.C) {
   158  	st := &fakeState{
   159  		entities: map[names.Tag]entityWithError{
   160  			u("x/0"): &fakeService{
   161  				tag: serviceTag("x/0"),
   162  				serviceStatus: state.StatusInfo{
   163  					Status:  state.StatusAllocating,
   164  					Message: "blah",
   165  				},
   166  				err: fmt.Errorf("x0 fails"),
   167  			},
   168  		},
   169  	}
   170  
   171  	getCanModify := func() (common.AuthFunc, error) {
   172  		return func(_ names.Tag) bool { return true }, nil
   173  	}
   174  	s := common.NewServiceStatusSetter(st, getCanModify)
   175  	args := params.SetStatus{
   176  		Entities: []params.EntityStatus{
   177  			{"unit-x-0", params.StatusInstalling, "bar", nil},
   178  		},
   179  	}
   180  	leaderCheck := func(_ state.EntityFinder, tag string) (bool, error) {
   181  		return false, nil
   182  	}
   183  	result, err := common.ServiceSetStatus(s, args, fakeServiceFromUnitTag, leaderCheck)
   184  	c.Assert(err, jc.ErrorIsNil)
   185  	c.Assert(result, gc.DeepEquals, params.ErrorResults{
   186  		Results: []params.ErrorResult{
   187  			{&params.Error{"this unit is not the leader", ""}},
   188  		},
   189  	})
   190  
   191  }
   192  
   193  func (*statusSetterSuite) TestSetStatus(c *gc.C) {
   194  	st := &fakeState{
   195  		entities: map[names.Tag]entityWithError{
   196  			u("x/0"): &fakeStatus{status: state.StatusAllocating, info: "blah", err: fmt.Errorf("x0 fails")},
   197  			u("x/1"): &fakeStatus{status: state.StatusInstalling, info: "blah"},
   198  			u("x/2"): &fakeStatus{status: state.StatusActive, info: "foo"},
   199  			u("x/3"): &fakeStatus{status: state.StatusError, info: "some info"},
   200  			u("x/4"): &fakeStatus{fetchError: "x3 error"},
   201  			u("x/5"): &fakeStatus{status: state.StatusStopping, info: "blah"},
   202  		},
   203  	}
   204  	getCanModify := func() (common.AuthFunc, error) {
   205  		x0 := u("x/0")
   206  		x1 := u("x/1")
   207  		x2 := u("x/2")
   208  		x3 := u("x/3")
   209  		x4 := u("x/4")
   210  		x5 := u("x/5")
   211  		return func(tag names.Tag) bool {
   212  			return tag == x0 || tag == x1 || tag == x2 || tag == x3 || tag == x4 || tag == x5
   213  		}, nil
   214  	}
   215  	s := common.NewStatusSetter(st, getCanModify)
   216  	args := params.SetStatus{
   217  		Entities: []params.EntityStatus{
   218  			{"unit-x-0", params.StatusInstalling, "bar", nil},
   219  			{"unit-x-1", params.StatusActive, "bar", nil},
   220  			{"unit-x-2", params.StatusStopping, "", nil},
   221  			{"unit-x-3", params.StatusAllocating, "not really", nil},
   222  			{"unit-x-4", params.StatusStopping, "", nil},
   223  			{"unit-x-5", params.StatusError, "blarg", nil},
   224  			{"unit-x-6", params.StatusActive, "42", nil},
   225  			{"unit-x-7", params.StatusActive, "bar", nil},
   226  		},
   227  	}
   228  	result, err := s.SetStatus(args)
   229  	c.Assert(err, jc.ErrorIsNil)
   230  	c.Assert(result, gc.DeepEquals, params.ErrorResults{
   231  		Results: []params.ErrorResult{
   232  			{&params.Error{Message: "x0 fails"}},
   233  			{nil},
   234  			{nil},
   235  			{nil},
   236  			{&params.Error{Message: "x3 error"}},
   237  			{nil},
   238  			{apiservertesting.ErrUnauthorized},
   239  			{apiservertesting.ErrUnauthorized},
   240  		},
   241  	})
   242  	get := func(tag names.Tag) *fakeStatus {
   243  		return st.entities[tag].(*fakeStatus)
   244  	}
   245  	c.Assert(get(u("x/1")).status, gc.Equals, state.StatusActive)
   246  	c.Assert(get(u("x/1")).info, gc.Equals, "bar")
   247  	c.Assert(get(u("x/2")).status, gc.Equals, state.StatusStopping)
   248  	c.Assert(get(u("x/2")).info, gc.Equals, "")
   249  	c.Assert(get(u("x/3")).status, gc.Equals, state.StatusAllocating)
   250  	c.Assert(get(u("x/3")).info, gc.Equals, "not really")
   251  	c.Assert(get(u("x/5")).status, gc.Equals, state.StatusError)
   252  	c.Assert(get(u("x/5")).info, gc.Equals, "blarg")
   253  }
   254  
   255  func (*statusSetterSuite) TestSetStatusError(c *gc.C) {
   256  	getCanModify := func() (common.AuthFunc, error) {
   257  		return nil, fmt.Errorf("pow")
   258  	}
   259  	s := common.NewStatusSetter(&fakeState{}, getCanModify)
   260  	args := params.SetStatus{
   261  		Entities: []params.EntityStatus{{"x0", "", "", nil}},
   262  	}
   263  	_, err := s.SetStatus(args)
   264  	c.Assert(err, gc.ErrorMatches, "pow")
   265  }
   266  
   267  func (*statusSetterSuite) TestSetStatusNoArgsNoError(c *gc.C) {
   268  	getCanModify := func() (common.AuthFunc, error) {
   269  		return nil, fmt.Errorf("pow")
   270  	}
   271  	s := common.NewStatusSetter(&fakeState{}, getCanModify)
   272  	result, err := s.SetStatus(params.SetStatus{})
   273  	c.Assert(err, jc.ErrorIsNil)
   274  	c.Assert(result.Results, gc.HasLen, 0)
   275  }
   276  
   277  func (*statusSetterSuite) TestUpdateStatus(c *gc.C) {
   278  	st := &fakeState{
   279  		entities: map[names.Tag]entityWithError{
   280  			m("0"): &fakeStatus{status: state.StatusAllocating, info: "blah", err: fmt.Errorf("x0 fails")},
   281  			m("1"): &fakeStatus{status: state.StatusError, info: "foo", data: map[string]interface{}{"foo": "blah"}},
   282  			m("2"): &fakeStatus{status: state.StatusError, info: "some info"},
   283  			m("3"): &fakeStatus{fetchError: "x3 error"},
   284  			m("4"): &fakeStatus{status: state.StatusActive},
   285  			m("5"): &fakeStatus{status: state.StatusStopping, info: ""},
   286  		},
   287  	}
   288  	getCanModify := func() (common.AuthFunc, error) {
   289  		x0 := m("0")
   290  		x1 := m("1")
   291  		x2 := m("2")
   292  		x3 := m("3")
   293  		x4 := m("4")
   294  		return func(tag names.Tag) bool {
   295  			return tag == x0 || tag == x1 || tag == x2 || tag == x3 || tag == x4
   296  		}, nil
   297  	}
   298  	s := common.NewStatusSetter(st, getCanModify)
   299  	args := params.SetStatus{
   300  		Entities: []params.EntityStatus{
   301  			{Tag: "machine-0", Data: nil},
   302  			{Tag: "machine-1", Data: nil},
   303  			{Tag: "machine-2", Data: map[string]interface{}{"foo": "bar"}},
   304  			{Tag: "machine-3", Data: map[string]interface{}{"foo": "bar"}},
   305  			{Tag: "machine-4", Data: map[string]interface{}{"foo": "bar"}},
   306  			{Tag: "machine-5", Data: map[string]interface{}{"foo": "bar"}},
   307  			{Tag: "machine-6", Data: nil},
   308  		},
   309  	}
   310  	result, err := s.UpdateStatus(args)
   311  	c.Assert(err, jc.ErrorIsNil)
   312  	c.Assert(result, gc.DeepEquals, params.ErrorResults{
   313  		Results: []params.ErrorResult{
   314  			{&params.Error{Message: "x0 fails"}},
   315  			{nil},
   316  			{nil},
   317  			{&params.Error{Message: "x3 error"}},
   318  			{&params.Error{Message: "machine 4 is not in an error state"}},
   319  			{apiservertesting.ErrUnauthorized},
   320  			{apiservertesting.ErrUnauthorized},
   321  		},
   322  	})
   323  	get := func(tag names.Tag) *fakeStatus {
   324  		return st.entities[tag].(*fakeStatus)
   325  	}
   326  	c.Assert(get(m("1")).status, gc.Equals, state.StatusError)
   327  	c.Assert(get(m("1")).info, gc.Equals, "foo")
   328  	c.Assert(get(m("1")).data, gc.DeepEquals, map[string]interface{}{"foo": "blah"})
   329  	c.Assert(get(m("2")).status, gc.Equals, state.StatusError)
   330  	c.Assert(get(m("2")).info, gc.Equals, "some info")
   331  	c.Assert(get(m("2")).data, gc.DeepEquals, map[string]interface{}{"foo": "bar"})
   332  }