github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/apiserver/common/unitstate_test.go (about)

     1  // Copyright 2020 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package common_test
     5  
     6  import (
     7  	"github.com/juju/loggo"
     8  	"github.com/juju/names/v5"
     9  	jc "github.com/juju/testing/checkers"
    10  	"go.uber.org/mock/gomock"
    11  	gc "gopkg.in/check.v1"
    12  
    13  	"github.com/juju/juju/apiserver/common"
    14  	"github.com/juju/juju/apiserver/common/mocks"
    15  	apiservertesting "github.com/juju/juju/apiserver/testing"
    16  	"github.com/juju/juju/controller"
    17  	"github.com/juju/juju/rpc/params"
    18  	"github.com/juju/juju/state"
    19  	"github.com/juju/juju/testing"
    20  )
    21  
    22  type unitStateSuite struct {
    23  	testing.BaseSuite
    24  
    25  	unitTag1 names.UnitTag
    26  
    27  	api         *common.UnitStateAPI
    28  	mockBackend *mocks.MockUnitStateBackend
    29  	mockUnit    *mocks.MockUnitStateUnit
    30  	mockOp      *mocks.MockModelOperation
    31  }
    32  
    33  var _ = gc.Suite(&unitStateSuite{})
    34  
    35  func (s *unitStateSuite) SetUpTest(c *gc.C) {
    36  	s.unitTag1 = names.NewUnitTag("wordpress/0")
    37  }
    38  
    39  func (s *unitStateSuite) assertBackendApi(c *gc.C) *gomock.Controller {
    40  	resources := common.NewResources()
    41  	authorizer := apiservertesting.FakeAuthorizer{
    42  		Tag: s.unitTag1,
    43  	}
    44  
    45  	ctrl := gomock.NewController(c)
    46  	s.mockBackend = mocks.NewMockUnitStateBackend(ctrl)
    47  	s.mockUnit = mocks.NewMockUnitStateUnit(ctrl)
    48  	s.mockOp = mocks.NewMockModelOperation(ctrl)
    49  
    50  	unitAuthFunc := func() (common.AuthFunc, error) {
    51  		return func(tag names.Tag) bool {
    52  			if tag.Id() == s.unitTag1.Id() {
    53  				return true
    54  			}
    55  			return false
    56  		}, nil
    57  	}
    58  
    59  	s.api = common.NewUnitStateAPI(
    60  		s.mockBackend, resources, authorizer, unitAuthFunc, loggo.GetLogger("juju.apiserver.common"))
    61  	return ctrl
    62  }
    63  
    64  func (s *unitStateSuite) expectState() (map[string]string, string, map[int]string, string, string) {
    65  	expCharmState := map[string]string{
    66  		"foo.bar":  "baz",
    67  		"payload$": "enc0d3d",
    68  	}
    69  	expUniterState := "testing"
    70  	expRelationState := map[int]string{
    71  		1: "one",
    72  		2: "two",
    73  	}
    74  	expStorageState := "storage testing"
    75  	expSecretState := "secret testing"
    76  
    77  	unitState := state.NewUnitState()
    78  	unitState.SetCharmState(expCharmState)
    79  	unitState.SetUniterState(expUniterState)
    80  	unitState.SetRelationState(expRelationState)
    81  	unitState.SetStorageState(expStorageState)
    82  	unitState.SetSecretState(expSecretState)
    83  
    84  	exp := s.mockUnit.EXPECT()
    85  	exp.State().Return(unitState, nil)
    86  
    87  	return expCharmState, expUniterState, expRelationState, expStorageState, expSecretState
    88  }
    89  
    90  func (s *unitStateSuite) expectUnit() {
    91  	exp := s.mockBackend.EXPECT()
    92  	exp.Unit(s.unitTag1.Id()).Return(s.mockUnit, nil)
    93  }
    94  
    95  func (s *unitStateSuite) expectSetStateOperation() string {
    96  	unitState := state.NewUnitState()
    97  	expUniterState := "testing"
    98  	unitState.SetUniterState(expUniterState)
    99  
   100  	// Mock controller config which provides the limits passed to SetStateOperation.
   101  	s.mockBackend.EXPECT().ControllerConfig().Return(
   102  		controller.Config{
   103  			"max-charm-state-size": 123,
   104  			"max-agent-state-size": 456,
   105  		}, nil)
   106  
   107  	exp := s.mockUnit.EXPECT()
   108  	exp.SetStateOperation(
   109  		unitState,
   110  		state.UnitStateSizeLimits{
   111  			MaxCharmStateSize: 123,
   112  			MaxAgentStateSize: 456,
   113  		},
   114  	).Return(s.mockOp)
   115  	return expUniterState
   116  }
   117  
   118  func (s *unitStateSuite) expectApplyOperation() {
   119  	exp := s.mockBackend.EXPECT()
   120  	exp.ApplyOperation(s.mockOp).Return(nil)
   121  }
   122  
   123  func (s *unitStateSuite) TestState(c *gc.C) {
   124  	defer s.assertBackendApi(c).Finish()
   125  	s.expectUnit()
   126  	expCharmState, expUniterState, expRelationState, expStorageState, expSecretState := s.expectState()
   127  
   128  	args := params.Entities{
   129  		Entities: []params.Entity{
   130  			{Tag: "not-a-unit-tag"},
   131  			{Tag: "unit-wordpress-0"},
   132  			{Tag: "unit-mysql-0"}, // not accessible by current user
   133  			{Tag: "unit-notfound-0"},
   134  		},
   135  	}
   136  	result, err := s.api.State(args)
   137  	c.Assert(err, jc.ErrorIsNil)
   138  	c.Assert(result, gc.DeepEquals, params.UnitStateResults{
   139  		Results: []params.UnitStateResult{
   140  			{Error: &params.Error{Message: `"not-a-unit-tag" is not a valid tag`}},
   141  			{
   142  				Error:         nil,
   143  				CharmState:    expCharmState,
   144  				UniterState:   expUniterState,
   145  				RelationState: expRelationState,
   146  				StorageState:  expStorageState,
   147  				SecretState:   expSecretState,
   148  			},
   149  			{Error: apiservertesting.ErrUnauthorized},
   150  			{Error: apiservertesting.ErrUnauthorized},
   151  		},
   152  	})
   153  }
   154  
   155  func (s *unitStateSuite) TestSetStateUniterState(c *gc.C) {
   156  	defer s.assertBackendApi(c).Finish()
   157  	s.expectUnit()
   158  	expUniterState := s.expectSetStateOperation()
   159  	s.expectApplyOperation()
   160  
   161  	args := params.SetUnitStateArgs{
   162  		Args: []params.SetUnitStateArg{
   163  			{Tag: "not-a-unit-tag", UniterState: &expUniterState},
   164  			{Tag: "unit-wordpress-0", UniterState: &expUniterState},
   165  			{Tag: "unit-mysql-0", UniterState: &expUniterState}, // not accessible by current user
   166  			{Tag: "unit-notfound-0", UniterState: &expUniterState},
   167  		},
   168  	}
   169  
   170  	result, err := s.api.SetState(args)
   171  	c.Assert(err, jc.ErrorIsNil)
   172  	c.Assert(result, gc.DeepEquals, params.ErrorResults{
   173  		Results: []params.ErrorResult{
   174  			{Error: &params.Error{Message: `"not-a-unit-tag" is not a valid tag`}},
   175  			{Error: nil},
   176  			{Error: apiservertesting.ErrUnauthorized},
   177  			{Error: apiservertesting.ErrUnauthorized},
   178  		},
   179  	})
   180  }