github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/state/environ_test.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package state_test
     5  
     6  import (
     7  	"fmt"
     8  
     9  	"github.com/juju/errors"
    10  	"github.com/juju/names"
    11  	jc "github.com/juju/testing/checkers"
    12  	"github.com/juju/utils"
    13  	gc "gopkg.in/check.v1"
    14  
    15  	"github.com/juju/juju/environs/config"
    16  	"github.com/juju/juju/state"
    17  	"github.com/juju/juju/testing"
    18  	"github.com/juju/juju/testing/factory"
    19  )
    20  
    21  type EnvironSuite struct {
    22  	ConnSuite
    23  }
    24  
    25  var _ = gc.Suite(&EnvironSuite{})
    26  
    27  func (s *EnvironSuite) TestEnvironment(c *gc.C) {
    28  	env, err := s.State.Environment()
    29  	c.Assert(err, jc.ErrorIsNil)
    30  
    31  	expectedTag := names.NewEnvironTag(env.UUID())
    32  	c.Assert(env.Tag(), gc.Equals, expectedTag)
    33  	c.Assert(env.ServerTag(), gc.Equals, expectedTag)
    34  	c.Assert(env.Name(), gc.Equals, "testenv")
    35  	c.Assert(env.Owner(), gc.Equals, s.Owner)
    36  	c.Assert(env.Life(), gc.Equals, state.Alive)
    37  }
    38  
    39  func (s *EnvironSuite) TestNewEnvironmentNonExistentLocalUser(c *gc.C) {
    40  	cfg, _ := s.createTestEnvConfig(c)
    41  	owner := names.NewUserTag("non-existent@local")
    42  
    43  	_, _, err := s.State.NewEnvironment(cfg, owner)
    44  	c.Assert(err, gc.ErrorMatches, `cannot create environment: user "non-existent" not found`)
    45  }
    46  
    47  func (s *EnvironSuite) TestNewEnvironmentSameUserSameNameFails(c *gc.C) {
    48  	cfg, _ := s.createTestEnvConfig(c)
    49  	owner := s.Factory.MakeUser(c, nil).UserTag()
    50  
    51  	// Create the first environment.
    52  	_, st1, err := s.State.NewEnvironment(cfg, owner)
    53  	c.Assert(err, jc.ErrorIsNil)
    54  	defer st1.Close()
    55  
    56  	// Attempt to create another environment with a different UUID but the
    57  	// same owner and name as the first.
    58  	newUUID, err := utils.NewUUID()
    59  	c.Assert(err, jc.ErrorIsNil)
    60  	cfg2 := testing.CustomEnvironConfig(c, testing.Attrs{
    61  		"name": cfg.Name(),
    62  		"uuid": newUUID.String(),
    63  	})
    64  	_, _, err = s.State.NewEnvironment(cfg2, owner)
    65  	errMsg := fmt.Sprintf("environment %q for %s already exists", cfg2.Name(), owner.Username())
    66  	c.Assert(err, gc.ErrorMatches, errMsg)
    67  	c.Assert(errors.IsAlreadyExists(err), jc.IsTrue)
    68  
    69  	// Remove the first environment.
    70  	env1, err := st1.Environment()
    71  	c.Assert(err, jc.ErrorIsNil)
    72  	err = env1.Destroy()
    73  	c.Assert(err, jc.ErrorIsNil)
    74  	err = st1.RemoveAllEnvironDocs()
    75  	c.Assert(err, jc.ErrorIsNil)
    76  
    77  	// We should now be able to create the other environment.
    78  	env2, st2, err := s.State.NewEnvironment(cfg2, owner)
    79  	c.Assert(err, jc.ErrorIsNil)
    80  	defer st2.Close()
    81  	c.Assert(env2, gc.NotNil)
    82  	c.Assert(st2, gc.NotNil)
    83  }
    84  
    85  func (s *EnvironSuite) TestNewEnvironment(c *gc.C) {
    86  	cfg, uuid := s.createTestEnvConfig(c)
    87  	owner := names.NewUserTag("test@remote")
    88  
    89  	env, st, err := s.State.NewEnvironment(cfg, owner)
    90  	c.Assert(err, jc.ErrorIsNil)
    91  	defer st.Close()
    92  
    93  	envTag := names.NewEnvironTag(uuid)
    94  	assertEnvMatches := func(env *state.Environment) {
    95  		c.Assert(env.UUID(), gc.Equals, envTag.Id())
    96  		c.Assert(env.Tag(), gc.Equals, envTag)
    97  		c.Assert(env.ServerTag(), gc.Equals, s.envTag)
    98  		c.Assert(env.Owner(), gc.Equals, owner)
    99  		c.Assert(env.Name(), gc.Equals, "testing")
   100  		c.Assert(env.Life(), gc.Equals, state.Alive)
   101  	}
   102  	assertEnvMatches(env)
   103  
   104  	// Since the environ tag for the State connection is different,
   105  	// asking for this environment through FindEntity returns a not found error.
   106  	env, err = s.State.GetEnvironment(envTag)
   107  	c.Assert(err, jc.ErrorIsNil)
   108  	assertEnvMatches(env)
   109  
   110  	env, err = st.Environment()
   111  	c.Assert(err, jc.ErrorIsNil)
   112  	assertEnvMatches(env)
   113  
   114  	_, err = s.State.FindEntity(envTag)
   115  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   116  
   117  	entity, err := st.FindEntity(envTag)
   118  	c.Assert(err, jc.ErrorIsNil)
   119  	c.Assert(entity.Tag(), gc.Equals, envTag)
   120  
   121  	// Ensure the environment is functional by adding a machine
   122  	_, err = st.AddMachine("quantal", state.JobHostUnits)
   123  	c.Assert(err, jc.ErrorIsNil)
   124  }
   125  
   126  func (s *EnvironSuite) TestStateServerEnvironment(c *gc.C) {
   127  	env, err := s.State.StateServerEnvironment()
   128  	c.Assert(err, jc.ErrorIsNil)
   129  
   130  	expectedTag := names.NewEnvironTag(env.UUID())
   131  	c.Assert(env.Tag(), gc.Equals, expectedTag)
   132  	c.Assert(env.ServerTag(), gc.Equals, expectedTag)
   133  	c.Assert(env.Name(), gc.Equals, "testenv")
   134  	c.Assert(env.Owner(), gc.Equals, s.Owner)
   135  	c.Assert(env.Life(), gc.Equals, state.Alive)
   136  }
   137  
   138  func (s *EnvironSuite) TestStateServerEnvironmentAccessibleFromOtherEnvironments(c *gc.C) {
   139  	cfg, _ := s.createTestEnvConfig(c)
   140  	_, st, err := s.State.NewEnvironment(cfg, names.NewUserTag("test@remote"))
   141  	defer st.Close()
   142  
   143  	env, err := st.StateServerEnvironment()
   144  	c.Assert(err, jc.ErrorIsNil)
   145  	c.Assert(env.Tag(), gc.Equals, s.envTag)
   146  	c.Assert(env.Name(), gc.Equals, "testenv")
   147  	c.Assert(env.Owner(), gc.Equals, s.Owner)
   148  	c.Assert(env.Life(), gc.Equals, state.Alive)
   149  }
   150  
   151  func (s *EnvironSuite) TestConfigForStateServerEnv(c *gc.C) {
   152  	otherState := s.Factory.MakeEnvironment(c, &factory.EnvParams{Name: "other"})
   153  	defer otherState.Close()
   154  
   155  	env, err := otherState.GetEnvironment(s.envTag)
   156  	c.Assert(err, jc.ErrorIsNil)
   157  
   158  	conf, err := env.Config()
   159  	c.Assert(err, jc.ErrorIsNil)
   160  	c.Assert(conf.Name(), gc.Equals, "testenv")
   161  	uuid, ok := conf.UUID()
   162  	c.Assert(ok, jc.IsTrue)
   163  	c.Assert(uuid, gc.Equals, s.envTag.Id())
   164  }
   165  
   166  func (s *EnvironSuite) TestConfigForOtherEnv(c *gc.C) {
   167  	otherState := s.Factory.MakeEnvironment(c, &factory.EnvParams{Name: "other"})
   168  	defer otherState.Close()
   169  	otherEnv, err := otherState.Environment()
   170  	c.Assert(err, jc.ErrorIsNil)
   171  
   172  	// By getting the environment through a different state connection,
   173  	// the underlying state pointer in the *state.Environment struct has
   174  	// a different environment tag.
   175  	env, err := s.State.GetEnvironment(otherEnv.EnvironTag())
   176  	c.Assert(err, jc.ErrorIsNil)
   177  
   178  	conf, err := env.Config()
   179  	c.Assert(err, jc.ErrorIsNil)
   180  	c.Assert(conf.Name(), gc.Equals, "other")
   181  	uuid, ok := conf.UUID()
   182  	c.Assert(ok, jc.IsTrue)
   183  	c.Assert(uuid, gc.Equals, otherEnv.UUID())
   184  }
   185  
   186  // createTestEnvConfig returns a new environment config and its UUID for testing.
   187  func (s *EnvironSuite) createTestEnvConfig(c *gc.C) (*config.Config, string) {
   188  	uuid, err := utils.NewUUID()
   189  	c.Assert(err, jc.ErrorIsNil)
   190  	return testing.CustomEnvironConfig(c, testing.Attrs{
   191  		"name": "testing",
   192  		"uuid": uuid.String(),
   193  	}), uuid.String()
   194  }
   195  
   196  func (s *EnvironSuite) TestEnvironmentConfigSameEnvAsState(c *gc.C) {
   197  	env, err := s.State.Environment()
   198  	c.Assert(err, jc.ErrorIsNil)
   199  	cfg, err := env.Config()
   200  	c.Assert(err, jc.ErrorIsNil)
   201  	uuid, exists := cfg.UUID()
   202  	c.Assert(exists, jc.IsTrue)
   203  	c.Assert(uuid, gc.Equals, s.State.EnvironUUID())
   204  }
   205  
   206  func (s *EnvironSuite) TestEnvironmentConfigDifferentEnvThanState(c *gc.C) {
   207  	otherState := s.Factory.MakeEnvironment(c, nil)
   208  	defer otherState.Close()
   209  	env, err := otherState.Environment()
   210  	c.Assert(err, jc.ErrorIsNil)
   211  	cfg, err := env.Config()
   212  	c.Assert(err, jc.ErrorIsNil)
   213  	uuid, exists := cfg.UUID()
   214  	c.Assert(exists, jc.IsTrue)
   215  	c.Assert(uuid, gc.Equals, env.UUID())
   216  	c.Assert(uuid, gc.Not(gc.Equals), s.State.EnvironUUID())
   217  }
   218  
   219  func (s *EnvironSuite) TestDestroyStateServerEnvironment(c *gc.C) {
   220  	env, err := s.State.Environment()
   221  	c.Assert(err, jc.ErrorIsNil)
   222  	err = env.Destroy()
   223  	c.Assert(err, jc.ErrorIsNil)
   224  }
   225  
   226  func (s *EnvironSuite) TestDestroyOtherEnvironment(c *gc.C) {
   227  	st2 := s.Factory.MakeEnvironment(c, nil)
   228  	defer st2.Close()
   229  	env, err := st2.Environment()
   230  	c.Assert(err, jc.ErrorIsNil)
   231  	err = env.Destroy()
   232  	c.Assert(err, jc.ErrorIsNil)
   233  }
   234  
   235  func (s *EnvironSuite) TestDestroyStateServerEnvironmentFails(c *gc.C) {
   236  	st2 := s.Factory.MakeEnvironment(c, nil)
   237  	defer st2.Close()
   238  	env, err := s.State.Environment()
   239  	c.Assert(err, jc.ErrorIsNil)
   240  	c.Assert(env.Destroy(), gc.ErrorMatches, "failed to destroy environment: hosting 1 other environments")
   241  }
   242  
   243  func (s *EnvironSuite) TestDestroyStateServerEnvironmentRace(c *gc.C) {
   244  	// Simulate an environment being added just before the remove txn is
   245  	// called.
   246  	defer state.SetBeforeHooks(c, s.State, func() {
   247  		blocker := s.Factory.MakeEnvironment(c, nil)
   248  		err := blocker.Close()
   249  		c.Check(err, jc.ErrorIsNil)
   250  	}).Check()
   251  
   252  	env, err := s.State.Environment()
   253  	c.Assert(err, jc.ErrorIsNil)
   254  	c.Assert(env.Destroy(), gc.ErrorMatches, "failed to destroy environment: hosting 1 other environments")
   255  }
   256  
   257  func (s *EnvironSuite) TestDestroyStateServerAlreadyDyingRaceNoOp(c *gc.C) {
   258  	env, err := s.State.Environment()
   259  	c.Assert(err, jc.ErrorIsNil)
   260  
   261  	// Simulate an environment being destroyed by another client just before
   262  	// the remove txn is called.
   263  	defer state.SetBeforeHooks(c, s.State, func() {
   264  		c.Assert(env.Destroy(), jc.ErrorIsNil)
   265  	}).Check()
   266  
   267  	c.Assert(env.Destroy(), jc.ErrorIsNil)
   268  }
   269  
   270  func (s *EnvironSuite) TestDestroyStateServerAlreadyDyingNoOp(c *gc.C) {
   271  	env, err := s.State.Environment()
   272  	c.Assert(err, jc.ErrorIsNil)
   273  
   274  	c.Assert(env.Destroy(), jc.ErrorIsNil)
   275  	c.Assert(env.Destroy(), jc.ErrorIsNil)
   276  }
   277  
   278  func (s *EnvironSuite) TestListEnvironmentUsers(c *gc.C) {
   279  	env, err := s.State.Environment()
   280  	c.Assert(err, jc.ErrorIsNil)
   281  
   282  	expected := addEnvUsers(c, s.State)
   283  	obtained, err := env.Users()
   284  	c.Assert(err, gc.IsNil)
   285  
   286  	assertObtainedUsersMatchExpectedUsers(c, obtained, expected)
   287  }
   288  
   289  func (s *EnvironSuite) TestMisMatchedEnvs(c *gc.C) {
   290  	// create another environment
   291  	otherEnvState := s.Factory.MakeEnvironment(c, nil)
   292  	defer otherEnvState.Close()
   293  	otherEnv, err := otherEnvState.Environment()
   294  	c.Assert(err, jc.ErrorIsNil)
   295  
   296  	// get that environment from State
   297  	env, err := s.State.GetEnvironment(otherEnv.EnvironTag())
   298  	c.Assert(err, jc.ErrorIsNil)
   299  
   300  	// check that the Users method errors
   301  	users, err := env.Users()
   302  	c.Assert(users, gc.IsNil)
   303  	c.Assert(err, gc.ErrorMatches, "cannot lookup environment users outside the current environment")
   304  }
   305  
   306  func (s *EnvironSuite) TestListUsersTwoEnvironments(c *gc.C) {
   307  	env, err := s.State.Environment()
   308  	c.Assert(err, jc.ErrorIsNil)
   309  
   310  	otherEnvState := s.Factory.MakeEnvironment(c, nil)
   311  	defer otherEnvState.Close()
   312  	otherEnv, err := otherEnvState.Environment()
   313  	c.Assert(err, jc.ErrorIsNil)
   314  
   315  	// Add users to both environments
   316  	expectedUsers := addEnvUsers(c, s.State)
   317  	expectedUsersOtherEnv := addEnvUsers(c, otherEnvState)
   318  
   319  	// test that only the expected users are listed for each environment
   320  	obtainedUsers, err := env.Users()
   321  	c.Assert(err, jc.ErrorIsNil)
   322  	assertObtainedUsersMatchExpectedUsers(c, obtainedUsers, expectedUsers)
   323  
   324  	obtainedUsersOtherEnv, err := otherEnv.Users()
   325  	c.Assert(err, jc.ErrorIsNil)
   326  	assertObtainedUsersMatchExpectedUsers(c, obtainedUsersOtherEnv, expectedUsersOtherEnv)
   327  }
   328  
   329  func addEnvUsers(c *gc.C, st *state.State) (expected []*state.EnvironmentUser) {
   330  	// get the environment owner
   331  	testAdmin := names.NewUserTag("test-admin")
   332  	owner, err := st.EnvironmentUser(testAdmin)
   333  	c.Assert(err, jc.ErrorIsNil)
   334  
   335  	f := factory.NewFactory(st)
   336  	return []*state.EnvironmentUser{
   337  		// we expect the owner to be an existing environment user
   338  		owner,
   339  		// add new users to the environment
   340  		f.MakeEnvUser(c, nil),
   341  		f.MakeEnvUser(c, nil),
   342  		f.MakeEnvUser(c, nil),
   343  	}
   344  }
   345  
   346  func assertObtainedUsersMatchExpectedUsers(c *gc.C, obtainedUsers, expectedUsers []*state.EnvironmentUser) {
   347  	c.Assert(len(obtainedUsers), gc.Equals, len(expectedUsers))
   348  	for i, obtained := range obtainedUsers {
   349  		c.Assert(obtained.EnvironmentTag().Id(), gc.Equals, expectedUsers[i].EnvironmentTag().Id())
   350  		c.Assert(obtained.UserName(), gc.Equals, expectedUsers[i].UserName())
   351  		c.Assert(obtained.DisplayName(), gc.Equals, expectedUsers[i].DisplayName())
   352  		c.Assert(obtained.CreatedBy(), gc.Equals, expectedUsers[i].CreatedBy())
   353  	}
   354  }
   355  
   356  func (s *EnvironSuite) TestAllEnvironments(c *gc.C) {
   357  	s.Factory.MakeEnvironment(c, &factory.EnvParams{
   358  		Name: "test", Owner: names.NewUserTag("bob@remote")}).Close()
   359  	s.Factory.MakeEnvironment(c, &factory.EnvParams{
   360  		Name: "test", Owner: names.NewUserTag("mary@remote")}).Close()
   361  	envs, err := s.State.AllEnvironments()
   362  	c.Assert(err, jc.ErrorIsNil)
   363  	c.Assert(envs, gc.HasLen, 3)
   364  	var obtained []string
   365  	for _, env := range envs {
   366  		obtained = append(obtained, fmt.Sprintf("%s/%s", env.Owner().Username(), env.Name()))
   367  	}
   368  	expected := []string{
   369  		"test-admin@local/testenv",
   370  		"bob@remote/test",
   371  		"mary@remote/test",
   372  	}
   373  	c.Assert(obtained, jc.SameContents, expected)
   374  }
   375  
   376  func (s *EnvironSuite) TestHostedEnvironCount(c *gc.C) {
   377  	c.Assert(state.HostedEnvironCount(c, s.State), gc.Equals, 0)
   378  
   379  	st1 := s.Factory.MakeEnvironment(c, nil)
   380  	defer st1.Close()
   381  	c.Assert(state.HostedEnvironCount(c, s.State), gc.Equals, 1)
   382  
   383  	st2 := s.Factory.MakeEnvironment(c, nil)
   384  	defer st2.Close()
   385  	c.Assert(state.HostedEnvironCount(c, s.State), gc.Equals, 2)
   386  
   387  	env1, err := st1.Environment()
   388  	c.Assert(err, jc.ErrorIsNil)
   389  	c.Assert(env1.Destroy(), jc.ErrorIsNil)
   390  	c.Assert(state.HostedEnvironCount(c, s.State), gc.Equals, 1)
   391  
   392  	env2, err := st2.Environment()
   393  	c.Assert(err, jc.ErrorIsNil)
   394  	c.Assert(env2.Destroy(), jc.ErrorIsNil)
   395  	c.Assert(state.HostedEnvironCount(c, s.State), gc.Equals, 0)
   396  }