github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/state/modeluser_test.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package state_test
     5  
     6  import (
     7  	"fmt"
     8  	"sort"
     9  
    10  	"github.com/juju/errors"
    11  	jc "github.com/juju/testing/checkers"
    12  	"github.com/juju/utils"
    13  	gc "gopkg.in/check.v1"
    14  	"gopkg.in/juju/names.v2"
    15  
    16  	"github.com/juju/juju/permission"
    17  	"github.com/juju/juju/state"
    18  	"github.com/juju/juju/storage"
    19  	"github.com/juju/juju/testing"
    20  	"github.com/juju/juju/testing/factory"
    21  )
    22  
    23  type ModelUserSuite struct {
    24  	ConnSuite
    25  }
    26  
    27  var _ = gc.Suite(&ModelUserSuite{})
    28  
    29  func (s *ModelUserSuite) TestAddModelUser(c *gc.C) {
    30  	now := s.State.NowToTheSecond()
    31  	user := s.Factory.MakeUser(c,
    32  		&factory.UserParams{
    33  			Name:        "validusername",
    34  			NoModelUser: true,
    35  		})
    36  	createdBy := s.Factory.MakeUser(c, &factory.UserParams{Name: "createdby"})
    37  	modelUser, err := s.State.AddModelUser(
    38  		s.State.ModelUUID(),
    39  		state.UserAccessSpec{
    40  			User:      user.UserTag(),
    41  			CreatedBy: createdBy.UserTag(),
    42  			Access:    permission.WriteAccess,
    43  		})
    44  	c.Assert(err, jc.ErrorIsNil)
    45  
    46  	c.Assert(modelUser.UserID, gc.Equals, fmt.Sprintf("%s:validusername@local", s.modelTag.Id()))
    47  	c.Assert(modelUser.Object, gc.Equals, s.modelTag)
    48  	c.Assert(modelUser.UserName, gc.Equals, "validusername@local")
    49  	c.Assert(modelUser.DisplayName, gc.Equals, user.DisplayName())
    50  	c.Assert(modelUser.Access, gc.Equals, permission.WriteAccess)
    51  	c.Assert(modelUser.CreatedBy.Id(), gc.Equals, "createdby@local")
    52  	c.Assert(modelUser.DateCreated.Equal(now) || modelUser.DateCreated.After(now), jc.IsTrue)
    53  	when, err := s.State.LastModelConnection(modelUser.UserTag)
    54  	c.Assert(err, jc.Satisfies, state.IsNeverConnectedError)
    55  	c.Assert(when.IsZero(), jc.IsTrue)
    56  
    57  	modelUser, err = s.State.UserAccess(user.UserTag(), s.State.ModelTag())
    58  	c.Assert(err, jc.ErrorIsNil)
    59  	c.Assert(modelUser.UserID, gc.Equals, fmt.Sprintf("%s:validusername@local", s.modelTag.Id()))
    60  	c.Assert(modelUser.Object, gc.Equals, s.modelTag)
    61  	c.Assert(modelUser.UserName, gc.Equals, "validusername@local")
    62  	c.Assert(modelUser.DisplayName, gc.Equals, user.DisplayName())
    63  	c.Assert(modelUser.Access, gc.Equals, permission.WriteAccess)
    64  	c.Assert(modelUser.CreatedBy.Id(), gc.Equals, "createdby@local")
    65  	c.Assert(modelUser.DateCreated.Equal(now) || modelUser.DateCreated.After(now), jc.IsTrue)
    66  	when, err = s.State.LastModelConnection(modelUser.UserTag)
    67  	c.Assert(err, jc.Satisfies, state.IsNeverConnectedError)
    68  	c.Assert(when.IsZero(), jc.IsTrue)
    69  }
    70  
    71  func (s *ModelUserSuite) TestAddReadOnlyModelUser(c *gc.C) {
    72  	user := s.Factory.MakeUser(c,
    73  		&factory.UserParams{
    74  			Name:        "validusername",
    75  			NoModelUser: true,
    76  		})
    77  	createdBy := s.Factory.MakeUser(c, &factory.UserParams{Name: "createdby"})
    78  	modelUser, err := s.State.AddModelUser(
    79  		s.State.ModelUUID(),
    80  		state.UserAccessSpec{
    81  			User:      user.UserTag(),
    82  			CreatedBy: createdBy.UserTag(),
    83  			Access:    permission.ReadAccess,
    84  		})
    85  	c.Assert(err, jc.ErrorIsNil)
    86  
    87  	c.Assert(modelUser.UserName, gc.Equals, "validusername@local")
    88  	c.Assert(modelUser.DisplayName, gc.Equals, user.DisplayName())
    89  	c.Assert(modelUser.Access, gc.Equals, permission.ReadAccess)
    90  
    91  	// Make sure that it is set when we read the user out.
    92  	modelUser, err = s.State.UserAccess(user.UserTag(), s.State.ModelTag())
    93  	c.Assert(err, jc.ErrorIsNil)
    94  	c.Assert(modelUser.UserName, gc.Equals, "validusername@local")
    95  	c.Assert(modelUser.Access, gc.Equals, permission.ReadAccess)
    96  }
    97  
    98  func (s *ModelUserSuite) TestAddReadWriteModelUser(c *gc.C) {
    99  	user := s.Factory.MakeUser(c,
   100  		&factory.UserParams{
   101  			Name:        "validusername",
   102  			NoModelUser: true,
   103  		})
   104  	createdBy := s.Factory.MakeUser(c, &factory.UserParams{Name: "createdby"})
   105  	modelUser, err := s.State.AddModelUser(
   106  		s.State.ModelUUID(),
   107  		state.UserAccessSpec{
   108  			User:      user.UserTag(),
   109  			CreatedBy: createdBy.UserTag(),
   110  			Access:    permission.WriteAccess,
   111  		})
   112  	c.Assert(err, jc.ErrorIsNil)
   113  
   114  	c.Assert(modelUser.UserName, gc.Equals, "validusername@local")
   115  	c.Assert(modelUser.DisplayName, gc.Equals, user.DisplayName())
   116  	c.Assert(modelUser.Access, gc.Equals, permission.WriteAccess)
   117  
   118  	// Make sure that it is set when we read the user out.
   119  	modelUser, err = s.State.UserAccess(user.UserTag(), s.State.ModelTag())
   120  	c.Assert(err, jc.ErrorIsNil)
   121  	c.Assert(modelUser.UserName, gc.Equals, "validusername@local")
   122  	c.Assert(modelUser.Access, gc.Equals, permission.WriteAccess)
   123  }
   124  
   125  func (s *ModelUserSuite) TestAddAdminModelUser(c *gc.C) {
   126  	user := s.Factory.MakeUser(c,
   127  		&factory.UserParams{
   128  			Name:        "validusername",
   129  			NoModelUser: true,
   130  		})
   131  	createdBy := s.Factory.MakeUser(c, &factory.UserParams{Name: "createdby"})
   132  	modelUser, err := s.State.AddModelUser(
   133  		s.State.ModelUUID(),
   134  		state.UserAccessSpec{
   135  			User:      user.UserTag(),
   136  			CreatedBy: createdBy.UserTag(),
   137  			Access:    permission.AdminAccess,
   138  		})
   139  	c.Assert(err, jc.ErrorIsNil)
   140  
   141  	c.Assert(modelUser.UserName, gc.Equals, "validusername@local")
   142  	c.Assert(modelUser.DisplayName, gc.Equals, user.DisplayName())
   143  	c.Assert(modelUser.Access, gc.Equals, permission.AdminAccess)
   144  
   145  	// Make sure that it is set when we read the user out.
   146  	modelUser, err = s.State.UserAccess(user.UserTag(), s.State.ModelTag())
   147  	c.Assert(err, jc.ErrorIsNil)
   148  	c.Assert(modelUser.UserName, gc.Equals, "validusername@local")
   149  	c.Assert(modelUser.Access, gc.Equals, permission.AdminAccess)
   150  }
   151  
   152  func (s *ModelUserSuite) TestDefaultAccessModelUser(c *gc.C) {
   153  	user := s.Factory.MakeUser(c,
   154  		&factory.UserParams{
   155  			Name:        "validusername",
   156  			NoModelUser: true,
   157  		})
   158  	createdBy := s.Factory.MakeUser(c, &factory.UserParams{Name: "createdby"})
   159  	modelUser, err := s.State.AddModelUser(
   160  		s.State.ModelUUID(),
   161  		state.UserAccessSpec{
   162  			User:      user.UserTag(),
   163  			CreatedBy: createdBy.UserTag(),
   164  			Access:    permission.ReadAccess,
   165  		})
   166  	c.Assert(err, jc.ErrorIsNil)
   167  	c.Assert(modelUser.Access, gc.Equals, permission.ReadAccess)
   168  }
   169  
   170  func (s *ModelUserSuite) TestSetAccessModelUser(c *gc.C) {
   171  	user := s.Factory.MakeUser(c,
   172  		&factory.UserParams{
   173  			Name:        "validusername",
   174  			NoModelUser: true,
   175  		})
   176  	createdBy := s.Factory.MakeUser(c, &factory.UserParams{Name: "createdby"})
   177  	modelUser, err := s.State.AddModelUser(
   178  		s.State.ModelUUID(),
   179  		state.UserAccessSpec{
   180  			User:      user.UserTag(),
   181  			CreatedBy: createdBy.UserTag(),
   182  			Access:    permission.AdminAccess,
   183  		})
   184  	c.Assert(err, jc.ErrorIsNil)
   185  	c.Assert(modelUser.Access, gc.Equals, permission.AdminAccess)
   186  
   187  	s.State.SetUserAccess(modelUser.UserTag, s.State.ModelTag(), permission.ReadAccess)
   188  
   189  	modelUser, err = s.State.UserAccess(user.UserTag(), s.State.ModelTag())
   190  	c.Assert(modelUser.Access, gc.Equals, permission.ReadAccess)
   191  }
   192  
   193  func (s *ModelUserSuite) TestCaseUserNameVsId(c *gc.C) {
   194  	model, err := s.State.Model()
   195  	c.Assert(err, jc.ErrorIsNil)
   196  
   197  	user, err := s.State.AddModelUser(
   198  		s.State.ModelUUID(),
   199  		state.UserAccessSpec{
   200  			User:      names.NewUserTag("Bob@RandomProvider"),
   201  			CreatedBy: model.Owner(),
   202  			Access:    permission.ReadAccess,
   203  		})
   204  	c.Assert(err, gc.IsNil)
   205  	c.Assert(user.UserName, gc.Equals, "Bob@RandomProvider")
   206  	c.Assert(user.UserID, gc.Equals, state.DocID(s.State, "bob@randomprovider"))
   207  }
   208  
   209  func (s *ModelUserSuite) TestCaseSensitiveModelUserErrors(c *gc.C) {
   210  	model, err := s.State.Model()
   211  	c.Assert(err, jc.ErrorIsNil)
   212  	s.Factory.MakeModelUser(c, &factory.ModelUserParams{User: "Bob@ubuntuone"})
   213  
   214  	_, err = s.State.AddModelUser(
   215  		s.State.ModelUUID(),
   216  		state.UserAccessSpec{
   217  			User:      names.NewUserTag("boB@ubuntuone"),
   218  			CreatedBy: model.Owner(),
   219  			Access:    permission.ReadAccess,
   220  		})
   221  	c.Assert(err, gc.ErrorMatches, `user access "boB@ubuntuone" already exists`)
   222  	c.Assert(errors.IsAlreadyExists(err), jc.IsTrue)
   223  }
   224  
   225  func (s *ModelUserSuite) TestCaseInsensitiveLookupInMultiEnvirons(c *gc.C) {
   226  	assertIsolated := func(st1, st2 *state.State, usernames ...string) {
   227  		f := factory.NewFactory(st1)
   228  		expectedUser := f.MakeModelUser(c, &factory.ModelUserParams{User: usernames[0]})
   229  
   230  		// assert case insensitive lookup for each username
   231  		for _, username := range usernames {
   232  			userTag := names.NewUserTag(username)
   233  			obtainedUser, err := st1.UserAccess(userTag, st1.ModelTag())
   234  			c.Assert(err, jc.ErrorIsNil)
   235  			c.Assert(obtainedUser, gc.DeepEquals, expectedUser)
   236  
   237  			_, err = st2.UserAccess(userTag, st2.ModelTag())
   238  			c.Assert(errors.IsNotFound(err), jc.IsTrue)
   239  		}
   240  	}
   241  
   242  	otherSt := s.Factory.MakeModel(c, nil)
   243  	defer otherSt.Close()
   244  	assertIsolated(s.State, otherSt,
   245  		"Bob@UbuntuOne",
   246  		"bob@ubuntuone",
   247  		"BOB@UBUNTUONE",
   248  	)
   249  	assertIsolated(otherSt, s.State,
   250  		"Sam@UbuntuOne",
   251  		"sam@ubuntuone",
   252  		"SAM@UBUNTUONE",
   253  	)
   254  }
   255  
   256  func (s *ModelUserSuite) TestAddModelDisplayName(c *gc.C) {
   257  	modelUserDefault := s.Factory.MakeModelUser(c, nil)
   258  	c.Assert(modelUserDefault.DisplayName, gc.Matches, "display name-[0-9]*")
   259  
   260  	modelUser := s.Factory.MakeModelUser(c, &factory.ModelUserParams{DisplayName: "Override user display name"})
   261  	c.Assert(modelUser.DisplayName, gc.Equals, "Override user display name")
   262  }
   263  
   264  func (s *ModelUserSuite) TestAddModelNoUserFails(c *gc.C) {
   265  	createdBy := s.Factory.MakeUser(c, &factory.UserParams{Name: "createdby"})
   266  	_, err := s.State.AddModelUser(
   267  		s.State.ModelUUID(),
   268  		state.UserAccessSpec{
   269  			User:      names.NewLocalUserTag("validusername"),
   270  			CreatedBy: createdBy.UserTag(),
   271  			Access:    permission.ReadAccess,
   272  		})
   273  	c.Assert(err, gc.ErrorMatches, `user "validusername" does not exist locally: user "validusername" not found`)
   274  }
   275  
   276  func (s *ModelUserSuite) TestAddModelNoCreatedByUserFails(c *gc.C) {
   277  	user := s.Factory.MakeUser(c, &factory.UserParams{Name: "validusername"})
   278  	_, err := s.State.AddModelUser(
   279  		s.State.ModelUUID(),
   280  		state.UserAccessSpec{
   281  			User:      user.UserTag(),
   282  			CreatedBy: names.NewLocalUserTag("createdby"),
   283  			Access:    permission.ReadAccess,
   284  		})
   285  	c.Assert(err, gc.ErrorMatches, `createdBy user "createdby" does not exist locally: user "createdby" not found`)
   286  }
   287  
   288  func (s *ModelUserSuite) TestRemoveModelUser(c *gc.C) {
   289  	user := s.Factory.MakeUser(c, &factory.UserParams{Name: "validUsername"})
   290  	_, err := s.State.UserAccess(user.UserTag(), s.State.ModelTag())
   291  	c.Assert(err, jc.ErrorIsNil)
   292  
   293  	err = s.State.RemoveUserAccess(user.UserTag(), s.State.ModelTag())
   294  	c.Assert(err, jc.ErrorIsNil)
   295  
   296  	_, err = s.State.UserAccess(user.UserTag(), s.State.ModelTag())
   297  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   298  }
   299  
   300  func (s *ModelUserSuite) TestRemoveModelUserFails(c *gc.C) {
   301  	user := s.Factory.MakeUser(c, &factory.UserParams{NoModelUser: true})
   302  	err := s.State.RemoveUserAccess(user.UserTag(), s.State.ModelTag())
   303  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   304  }
   305  
   306  func (s *ModelUserSuite) TestUpdateLastConnection(c *gc.C) {
   307  	now := s.State.NowToTheSecond()
   308  	createdBy := s.Factory.MakeUser(c, &factory.UserParams{Name: "createdby"})
   309  	user := s.Factory.MakeUser(c, &factory.UserParams{Name: "validusername", Creator: createdBy.Tag()})
   310  	modelUser, err := s.State.UserAccess(user.UserTag(), s.State.ModelTag())
   311  	c.Assert(err, jc.ErrorIsNil)
   312  	err = s.State.UpdateLastModelConnection(user.UserTag())
   313  	c.Assert(err, jc.ErrorIsNil)
   314  	when, err := s.State.LastModelConnection(modelUser.UserTag)
   315  	c.Assert(err, jc.ErrorIsNil)
   316  	// It is possible that the update is done over a second boundary, so we need
   317  	// to check for after now as well as equal.
   318  	c.Assert(when.After(now) || when.Equal(now), jc.IsTrue)
   319  }
   320  
   321  func (s *ModelUserSuite) TestUpdateLastConnectionTwoModelUsers(c *gc.C) {
   322  	now := s.State.NowToTheSecond()
   323  
   324  	// Create a user and add them to the inital model.
   325  	createdBy := s.Factory.MakeUser(c, &factory.UserParams{Name: "createdby"})
   326  	user := s.Factory.MakeUser(c, &factory.UserParams{Name: "validusername", Creator: createdBy.Tag()})
   327  	modelUser, err := s.State.UserAccess(user.UserTag(), s.State.ModelTag())
   328  	c.Assert(err, jc.ErrorIsNil)
   329  
   330  	// Create a second model and add the same user to this.
   331  	st2 := s.Factory.MakeModel(c, nil)
   332  	defer st2.Close()
   333  	modelUser2, err := st2.AddModelUser(
   334  		st2.ModelUUID(),
   335  		state.UserAccessSpec{
   336  			User:      user.UserTag(),
   337  			CreatedBy: createdBy.UserTag(),
   338  			Access:    permission.ReadAccess,
   339  		})
   340  	c.Assert(err, jc.ErrorIsNil)
   341  
   342  	// Now we have two model users with the same username. Ensure we get
   343  	// separate last connections.
   344  
   345  	// Connect modelUser and get last connection.
   346  	err = s.State.UpdateLastModelConnection(user.UserTag())
   347  	c.Assert(err, jc.ErrorIsNil)
   348  	when, err := s.State.LastModelConnection(modelUser.UserTag)
   349  	c.Assert(err, jc.ErrorIsNil)
   350  	c.Assert(when.After(now) || when.Equal(now), jc.IsTrue)
   351  
   352  	// Try to get last connection for modelUser2. As they have never connected,
   353  	// we expect to get an error.
   354  	_, err = st2.LastModelConnection(modelUser2.UserTag)
   355  	c.Assert(err, gc.ErrorMatches, `never connected: "validusername@local"`)
   356  
   357  	// Connect modelUser2 and get last connection.
   358  	err = s.State.UpdateLastModelConnection(modelUser2.UserTag)
   359  	c.Assert(err, jc.ErrorIsNil)
   360  	when, err = s.State.LastModelConnection(modelUser2.UserTag)
   361  	c.Assert(err, jc.ErrorIsNil)
   362  	c.Assert(when.After(now) || when.Equal(now), jc.IsTrue)
   363  }
   364  
   365  func (s *ModelUserSuite) TestModelsForUserNone(c *gc.C) {
   366  	tag := names.NewUserTag("non-existent@remote")
   367  	models, err := s.State.ModelsForUser(tag)
   368  	c.Assert(err, jc.ErrorIsNil)
   369  	c.Assert(models, gc.HasLen, 0)
   370  }
   371  
   372  func (s *ModelUserSuite) TestModelsForUserNewLocalUser(c *gc.C) {
   373  	user := s.Factory.MakeUser(c, &factory.UserParams{NoModelUser: true})
   374  	models, err := s.State.ModelsForUser(user.UserTag())
   375  	c.Assert(err, jc.ErrorIsNil)
   376  	c.Assert(models, gc.HasLen, 0)
   377  }
   378  
   379  func (s *ModelUserSuite) TestModelsForUser(c *gc.C) {
   380  	user := s.Factory.MakeUser(c, nil)
   381  	models, err := s.State.ModelsForUser(user.UserTag())
   382  	c.Assert(err, jc.ErrorIsNil)
   383  	c.Assert(models, gc.HasLen, 1)
   384  	c.Assert(models[0].UUID(), gc.Equals, s.State.ModelUUID())
   385  	st, err := s.State.ForModel(models[0].ModelTag())
   386  	c.Assert(err, jc.ErrorIsNil)
   387  	modelUser, err := s.State.UserAccess(user.UserTag(), models[0].ModelTag())
   388  	when, err := st.LastModelConnection(modelUser.UserTag)
   389  	c.Assert(err, jc.Satisfies, state.IsNeverConnectedError)
   390  	c.Assert(when.IsZero(), jc.IsTrue)
   391  	c.Assert(st.Close(), jc.ErrorIsNil)
   392  }
   393  
   394  func (s *ModelUserSuite) newEnvWithOwner(c *gc.C, name string, owner names.UserTag) *state.Model {
   395  	// Don't use the factory to call MakeModel because it may at some
   396  	// time in the future be modified to do additional things.  Instead call
   397  	// the state method directly to create an model to make sure that
   398  	// the owner is able to access the model.
   399  	uuid, err := utils.NewUUID()
   400  	c.Assert(err, jc.ErrorIsNil)
   401  	cfg := testing.CustomModelConfig(c, testing.Attrs{
   402  		"name": name,
   403  		"uuid": uuid.String(),
   404  	})
   405  	model, st, err := s.State.NewModel(state.ModelArgs{
   406  		CloudName: "dummy", CloudRegion: "dummy-region", Config: cfg, Owner: owner,
   407  		StorageProviderRegistry: storage.StaticProviderRegistry{},
   408  	})
   409  	c.Assert(err, jc.ErrorIsNil)
   410  	defer st.Close()
   411  	return model
   412  }
   413  
   414  func (s *ModelUserSuite) TestModelsForUserEnvOwner(c *gc.C) {
   415  	owner := names.NewUserTag("external@remote")
   416  	model := s.newEnvWithOwner(c, "test-model", owner)
   417  
   418  	models, err := s.State.ModelsForUser(owner)
   419  	c.Assert(err, jc.ErrorIsNil)
   420  	c.Assert(models, gc.HasLen, 1)
   421  	s.checkSameModel(c, models[0].Model, model)
   422  }
   423  
   424  func (s *ModelUserSuite) checkSameModel(c *gc.C, env1, env2 *state.Model) {
   425  	c.Check(env1.Name(), gc.Equals, env2.Name())
   426  	c.Check(env1.UUID(), gc.Equals, env2.UUID())
   427  }
   428  
   429  func (s *ModelUserSuite) newEnvWithUser(c *gc.C, name string, user names.UserTag) *state.Model {
   430  	envState := s.Factory.MakeModel(c, &factory.ModelParams{Name: name})
   431  	defer envState.Close()
   432  	newEnv, err := envState.Model()
   433  	c.Assert(err, jc.ErrorIsNil)
   434  
   435  	_, err = envState.AddModelUser(
   436  		envState.ModelUUID(),
   437  		state.UserAccessSpec{
   438  			User: user, CreatedBy: newEnv.Owner(),
   439  			Access: permission.ReadAccess,
   440  		})
   441  	c.Assert(err, jc.ErrorIsNil)
   442  	return newEnv
   443  }
   444  
   445  func (s *ModelUserSuite) TestModelsForUserOfNewEnv(c *gc.C) {
   446  	userTag := names.NewUserTag("external@remote")
   447  	model := s.newEnvWithUser(c, "test-model", userTag)
   448  
   449  	models, err := s.State.ModelsForUser(userTag)
   450  	c.Assert(err, jc.ErrorIsNil)
   451  	c.Assert(models, gc.HasLen, 1)
   452  	s.checkSameModel(c, models[0].Model, model)
   453  }
   454  
   455  func (s *ModelUserSuite) TestModelsForUserMultiple(c *gc.C) {
   456  	userTag := names.NewUserTag("external@remote")
   457  	expected := []*state.Model{
   458  		s.newEnvWithUser(c, "user1", userTag),
   459  		s.newEnvWithUser(c, "user2", userTag),
   460  		s.newEnvWithUser(c, "user3", userTag),
   461  		s.newEnvWithOwner(c, "owner1", userTag),
   462  		s.newEnvWithOwner(c, "owner2", userTag),
   463  	}
   464  	sort.Sort(UUIDOrder(expected))
   465  
   466  	models, err := s.State.ModelsForUser(userTag)
   467  	c.Assert(err, jc.ErrorIsNil)
   468  	c.Assert(models, gc.HasLen, len(expected))
   469  	sort.Sort(userUUIDOrder(models))
   470  	for i := range expected {
   471  		s.checkSameModel(c, models[i].Model, expected[i])
   472  	}
   473  }
   474  
   475  func (s *ModelUserSuite) TestIsControllerAdmin(c *gc.C) {
   476  	isAdmin, err := s.State.IsControllerAdmin(s.Owner)
   477  	c.Assert(err, jc.ErrorIsNil)
   478  	c.Assert(isAdmin, jc.IsTrue)
   479  
   480  	user := s.Factory.MakeUser(c, &factory.UserParams{NoModelUser: true})
   481  	isAdmin, err = s.State.IsControllerAdmin(user.UserTag())
   482  	c.Assert(err, jc.ErrorIsNil)
   483  	c.Assert(isAdmin, jc.IsFalse)
   484  
   485  	s.State.SetUserAccess(user.UserTag(), s.State.ControllerTag(), permission.SuperuserAccess)
   486  	isAdmin, err = s.State.IsControllerAdmin(user.UserTag())
   487  	c.Assert(err, jc.ErrorIsNil)
   488  	c.Assert(isAdmin, jc.IsTrue)
   489  
   490  	readonly := s.Factory.MakeModelUser(c, &factory.ModelUserParams{Access: permission.ReadAccess})
   491  	isAdmin, err = s.State.IsControllerAdmin(readonly.UserTag)
   492  	c.Assert(err, jc.ErrorIsNil)
   493  	c.Assert(isAdmin, jc.IsFalse)
   494  }
   495  
   496  func (s *ModelUserSuite) TestIsControllerAdminFromOtherState(c *gc.C) {
   497  	user := s.Factory.MakeUser(c, &factory.UserParams{NoModelUser: true})
   498  
   499  	otherState := s.Factory.MakeModel(c, &factory.ModelParams{Owner: user.UserTag()})
   500  	defer otherState.Close()
   501  
   502  	isAdmin, err := otherState.IsControllerAdmin(user.UserTag())
   503  	c.Assert(err, jc.ErrorIsNil)
   504  	c.Assert(isAdmin, jc.IsFalse)
   505  
   506  	isAdmin, err = otherState.IsControllerAdmin(s.Owner)
   507  	c.Assert(err, jc.ErrorIsNil)
   508  	c.Assert(isAdmin, jc.IsTrue)
   509  }
   510  
   511  // UUIDOrder is used to sort the models into a stable order
   512  type UUIDOrder []*state.Model
   513  
   514  func (a UUIDOrder) Len() int           { return len(a) }
   515  func (a UUIDOrder) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
   516  func (a UUIDOrder) Less(i, j int) bool { return a[i].UUID() < a[j].UUID() }
   517  
   518  // userUUIDOrder is used to sort the UserModels into a stable order
   519  type userUUIDOrder []*state.UserModel
   520  
   521  func (a userUUIDOrder) Len() int           { return len(a) }
   522  func (a userUUIDOrder) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
   523  func (a userUUIDOrder) Less(i, j int) bool { return a[i].UUID() < a[j].UUID() }