github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/apiserver/modelmanager/modelinfo_test.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package modelmanager_test
     5  
     6  import (
     7  	"time"
     8  
     9  	"github.com/juju/errors"
    10  	"github.com/juju/names"
    11  	gitjujutesting "github.com/juju/testing"
    12  	jc "github.com/juju/testing/checkers"
    13  	gc "gopkg.in/check.v1"
    14  
    15  	"github.com/juju/juju/apiserver/common"
    16  	"github.com/juju/juju/apiserver/modelmanager"
    17  	"github.com/juju/juju/apiserver/params"
    18  	apiservertesting "github.com/juju/juju/apiserver/testing"
    19  	"github.com/juju/juju/environs/config"
    20  	"github.com/juju/juju/state"
    21  	"github.com/juju/juju/status"
    22  	coretesting "github.com/juju/juju/testing"
    23  )
    24  
    25  type modelInfoSuite struct {
    26  	coretesting.BaseSuite
    27  	authorizer   apiservertesting.FakeAuthorizer
    28  	st           *mockState
    29  	modelmanager *modelmanager.ModelManagerAPI
    30  }
    31  
    32  var _ = gc.Suite(&modelInfoSuite{})
    33  
    34  func (s *modelInfoSuite) SetUpTest(c *gc.C) {
    35  	s.BaseSuite.SetUpTest(c)
    36  	s.authorizer = apiservertesting.FakeAuthorizer{
    37  		Tag: names.NewUserTag("admin@local"),
    38  	}
    39  	s.st = &mockState{
    40  		uuid: coretesting.ModelTag.Id(),
    41  	}
    42  	s.st.model = &mockModel{
    43  		owner: names.NewUserTag("bob@local"),
    44  		cfg:   coretesting.ModelConfig(c),
    45  		life:  state.Dying,
    46  		status: status.StatusInfo{
    47  			Status: status.StatusDestroying,
    48  			Since:  &time.Time{},
    49  		},
    50  		users: []*mockModelUser{{
    51  			userName: "admin",
    52  			access:   state.ModelAdminAccess,
    53  		}, {
    54  			userName:    "bob@local",
    55  			displayName: "Bob",
    56  			access:      state.ModelReadAccess,
    57  		}, {
    58  			userName:    "charlotte@local",
    59  			displayName: "Charlotte",
    60  			access:      state.ModelReadAccess,
    61  		}},
    62  	}
    63  	var err error
    64  	s.modelmanager, err = modelmanager.NewModelManagerAPI(s.st, &s.authorizer)
    65  	c.Assert(err, jc.ErrorIsNil)
    66  }
    67  
    68  func (s *modelInfoSuite) setAPIUser(c *gc.C, user names.UserTag) {
    69  	s.authorizer.Tag = user
    70  	modelmanager, err := modelmanager.NewModelManagerAPI(s.st, s.authorizer)
    71  	c.Assert(err, jc.ErrorIsNil)
    72  	s.modelmanager = modelmanager
    73  }
    74  
    75  func (s *modelInfoSuite) TestModelInfo(c *gc.C) {
    76  	s.st.model.users[1].SetErrors(
    77  		nil, state.NeverConnectedError("never connected"),
    78  	)
    79  	info := s.getModelInfo(c)
    80  	c.Assert(info, jc.DeepEquals, params.ModelInfo{
    81  		Name:           "testenv",
    82  		UUID:           s.st.model.cfg.UUID(),
    83  		ControllerUUID: coretesting.ModelTag.Id(),
    84  		OwnerTag:       "user-bob@local",
    85  		ProviderType:   "someprovider",
    86  		DefaultSeries:  coretesting.FakeDefaultSeries,
    87  		Life:           params.Dying,
    88  		Status: params.EntityStatus{
    89  			Status: status.StatusDestroying,
    90  			Since:  &time.Time{},
    91  		},
    92  		Users: []params.ModelUserInfo{{
    93  			UserName:       "admin",
    94  			LastConnection: &time.Time{},
    95  			Access:         params.ModelWriteAccess,
    96  		}, {
    97  			UserName:       "bob@local",
    98  			DisplayName:    "Bob",
    99  			LastConnection: nil, // never connected
   100  			Access:         params.ModelReadAccess,
   101  		}, {
   102  			UserName:       "charlotte@local",
   103  			DisplayName:    "Charlotte",
   104  			LastConnection: &time.Time{},
   105  			Access:         params.ModelReadAccess,
   106  		}},
   107  	})
   108  	s.st.CheckCalls(c, []gitjujutesting.StubCall{
   109  		{"IsControllerAdministrator", []interface{}{names.NewUserTag("admin@local")}},
   110  		{"ModelUUID", nil},
   111  		{"ForModel", []interface{}{names.NewModelTag(s.st.model.cfg.UUID())}},
   112  		{"Model", nil},
   113  		{"Close", nil},
   114  	})
   115  	s.st.model.CheckCalls(c, []gitjujutesting.StubCall{
   116  		{"Config", nil},
   117  		{"Users", nil},
   118  		{"Status", nil},
   119  		{"Owner", nil},
   120  		{"Life", nil},
   121  	})
   122  }
   123  
   124  func (s *modelInfoSuite) TestModelInfoOwner(c *gc.C) {
   125  	s.setAPIUser(c, names.NewUserTag("bob@local"))
   126  	info := s.getModelInfo(c)
   127  	c.Assert(info.Users, gc.HasLen, 3)
   128  }
   129  
   130  func (s *modelInfoSuite) TestModelInfoNonOwner(c *gc.C) {
   131  	s.setAPIUser(c, names.NewUserTag("charlotte@local"))
   132  	info := s.getModelInfo(c)
   133  	c.Assert(info.Users, gc.HasLen, 1)
   134  	c.Assert(info.Users[0].UserName, gc.Equals, "charlotte@local")
   135  }
   136  
   137  func (s *modelInfoSuite) getModelInfo(c *gc.C) params.ModelInfo {
   138  	results, err := s.modelmanager.ModelInfo(params.Entities{
   139  		Entities: []params.Entity{{
   140  			names.NewModelTag(s.st.model.cfg.UUID()).String(),
   141  		}},
   142  	})
   143  	c.Assert(err, jc.ErrorIsNil)
   144  	c.Assert(results.Results, gc.HasLen, 1)
   145  	c.Assert(results.Results[0].Result, gc.NotNil)
   146  	c.Assert(results.Results[0].Error, gc.IsNil)
   147  	return *results.Results[0].Result
   148  }
   149  
   150  func (s *modelInfoSuite) TestModelInfoErrorInvalidTag(c *gc.C) {
   151  	s.testModelInfoError(c, "user-bob", `"user-bob" is not a valid model tag`)
   152  }
   153  
   154  func (s *modelInfoSuite) TestModelInfoErrorGetModelNotFound(c *gc.C) {
   155  	s.st.SetErrors(errors.NotFoundf("model"))
   156  	s.testModelInfoError(c, coretesting.ModelTag.String(), `permission denied`)
   157  }
   158  
   159  func (s *modelInfoSuite) TestModelInfoErrorModelConfig(c *gc.C) {
   160  	s.st.model.SetErrors(errors.Errorf("no config for you"))
   161  	s.testModelInfoError(c, coretesting.ModelTag.String(), `no config for you`)
   162  }
   163  
   164  func (s *modelInfoSuite) TestModelInfoErrorModelUsers(c *gc.C) {
   165  	s.st.model.SetErrors(errors.Errorf("no users for you"))
   166  	s.testModelInfoError(c, coretesting.ModelTag.String(), `no users for you`)
   167  }
   168  
   169  func (s *modelInfoSuite) TestModelInfoErrorNoModelUsers(c *gc.C) {
   170  	s.st.model.users = nil
   171  	s.testModelInfoError(c, coretesting.ModelTag.String(), `permission denied`)
   172  }
   173  
   174  func (s *modelInfoSuite) TestModelInfoErrorNoAccess(c *gc.C) {
   175  	s.setAPIUser(c, names.NewUserTag("nemo@local"))
   176  	s.testModelInfoError(c, coretesting.ModelTag.String(), `permission denied`)
   177  }
   178  
   179  func (s *modelInfoSuite) testModelInfoError(c *gc.C, modelTag, expectedErr string) {
   180  	results, err := s.modelmanager.ModelInfo(params.Entities{
   181  		Entities: []params.Entity{{modelTag}},
   182  	})
   183  	c.Assert(err, jc.ErrorIsNil)
   184  	c.Assert(results.Results, gc.HasLen, 1)
   185  	c.Assert(results.Results[0].Result, gc.IsNil)
   186  	c.Assert(results.Results[0].Error, gc.ErrorMatches, expectedErr)
   187  }
   188  
   189  type mockState struct {
   190  	gitjujutesting.Stub
   191  
   192  	common.APIHostPortsGetter
   193  	common.ModelConfigGetter
   194  	common.ToolsStorageGetter
   195  
   196  	uuid  string
   197  	model *mockModel
   198  	owner names.UserTag
   199  	users []*state.ModelUser
   200  }
   201  
   202  func (st *mockState) ModelUUID() string {
   203  	st.MethodCall(st, "ModelUUID")
   204  	return st.uuid
   205  }
   206  
   207  func (st *mockState) ModelsForUser(user names.UserTag) ([]*state.UserModel, error) {
   208  	st.MethodCall(st, "ModelsForUser", user)
   209  	return nil, st.NextErr()
   210  }
   211  
   212  func (st *mockState) IsControllerAdministrator(user names.UserTag) (bool, error) {
   213  	st.MethodCall(st, "IsControllerAdministrator", user)
   214  	return user.Canonical() == "admin@local", st.NextErr()
   215  }
   216  
   217  func (st *mockState) NewModel(args state.ModelArgs) (*state.Model, *state.State, error) {
   218  	st.MethodCall(st, "NewModel", args)
   219  	return nil, nil, st.NextErr()
   220  }
   221  
   222  func (st *mockState) ControllerModel() (*state.Model, error) {
   223  	st.MethodCall(st, "ControllerModel")
   224  	return nil, st.NextErr()
   225  }
   226  
   227  func (st *mockState) ForModel(tag names.ModelTag) (modelmanager.Backend, error) {
   228  	st.MethodCall(st, "ForModel", tag)
   229  	return st, st.NextErr()
   230  }
   231  
   232  func (st *mockState) Model() (modelmanager.Model, error) {
   233  	st.MethodCall(st, "Model")
   234  	return st.model, st.NextErr()
   235  }
   236  
   237  func (st *mockState) Close() error {
   238  	st.MethodCall(st, "Close")
   239  	return st.NextErr()
   240  }
   241  
   242  func (st *mockState) AddModelUser(spec state.ModelUserSpec) (*state.ModelUser, error) {
   243  	st.MethodCall(st, "AddModelUser", spec)
   244  	return nil, st.NextErr()
   245  }
   246  
   247  func (st *mockState) RemoveModelUser(tag names.UserTag) error {
   248  	st.MethodCall(st, "RemoveModelUser", tag)
   249  	return st.NextErr()
   250  }
   251  
   252  func (st *mockState) ModelUser(tag names.UserTag) (*state.ModelUser, error) {
   253  	st.MethodCall(st, "ModelUser", tag)
   254  	return nil, st.NextErr()
   255  }
   256  
   257  type mockModel struct {
   258  	gitjujutesting.Stub
   259  	owner  names.UserTag
   260  	life   state.Life
   261  	status status.StatusInfo
   262  	cfg    *config.Config
   263  	users  []*mockModelUser
   264  }
   265  
   266  func (m *mockModel) Config() (*config.Config, error) {
   267  	m.MethodCall(m, "Config")
   268  	return m.cfg, m.NextErr()
   269  }
   270  
   271  func (m *mockModel) Owner() names.UserTag {
   272  	m.MethodCall(m, "Owner")
   273  	m.PopNoErr()
   274  	return m.owner
   275  }
   276  
   277  func (m *mockModel) Life() state.Life {
   278  	m.MethodCall(m, "Life")
   279  	m.PopNoErr()
   280  	return m.life
   281  }
   282  
   283  func (m *mockModel) Status() (status.StatusInfo, error) {
   284  	m.MethodCall(m, "Status")
   285  	return m.status, m.NextErr()
   286  }
   287  
   288  func (m *mockModel) Users() ([]common.ModelUser, error) {
   289  	m.MethodCall(m, "Users")
   290  	if err := m.NextErr(); err != nil {
   291  		return nil, err
   292  	}
   293  	users := make([]common.ModelUser, len(m.users))
   294  	for i, user := range m.users {
   295  		users[i] = user
   296  	}
   297  	return users, nil
   298  }
   299  
   300  type mockModelUser struct {
   301  	gitjujutesting.Stub
   302  	userName       string
   303  	displayName    string
   304  	access         state.ModelAccess
   305  	lastConnection time.Time
   306  }
   307  
   308  func (u *mockModelUser) Access() state.ModelAccess {
   309  	u.MethodCall(u, "Access")
   310  	u.PopNoErr()
   311  	return u.access
   312  }
   313  
   314  func (u *mockModelUser) DisplayName() string {
   315  	u.MethodCall(u, "DisplayName")
   316  	u.PopNoErr()
   317  	return u.displayName
   318  }
   319  
   320  func (u *mockModelUser) LastConnection() (time.Time, error) {
   321  	u.MethodCall(u, "LastConnection")
   322  	return u.lastConnection, u.NextErr()
   323  }
   324  
   325  func (u *mockModelUser) UserName() string {
   326  	u.MethodCall(u, "UserName")
   327  	u.PopNoErr()
   328  	return u.userName
   329  }
   330  
   331  func (u *mockModelUser) UserTag() names.UserTag {
   332  	u.MethodCall(u, "UserTag")
   333  	u.PopNoErr()
   334  	return names.NewUserTag(u.userName)
   335  }