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