github.com/Pankov404/juju@v0.0.0-20150703034450-be266991dceb/apiserver/client/destroy_test.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package client_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  	gc "gopkg.in/check.v1"
    13  
    14  	"github.com/juju/juju/apiserver/client"
    15  	"github.com/juju/juju/apiserver/common"
    16  	apiservertesting "github.com/juju/juju/apiserver/testing"
    17  	"github.com/juju/juju/environs"
    18  	"github.com/juju/juju/instance"
    19  	"github.com/juju/juju/juju/testing"
    20  	"github.com/juju/juju/provider/dummy"
    21  	"github.com/juju/juju/state"
    22  	jujutesting "github.com/juju/juju/testing"
    23  	"github.com/juju/juju/testing/factory"
    24  )
    25  
    26  type destroyEnvironmentSuite struct {
    27  	baseSuite
    28  }
    29  
    30  var _ = gc.Suite(&destroyEnvironmentSuite{})
    31  
    32  // setUpManual adds "manually provisioned" machines to state:
    33  // one manager machine, and one non-manager.
    34  func (s *destroyEnvironmentSuite) setUpManual(c *gc.C) (m0, m1 *state.Machine) {
    35  	m0, err := s.State.AddMachine("precise", state.JobManageEnviron)
    36  	c.Assert(err, jc.ErrorIsNil)
    37  	err = m0.SetProvisioned(instance.Id("manual:0"), "manual:0:fake_nonce", nil)
    38  	c.Assert(err, jc.ErrorIsNil)
    39  	m1, err = s.State.AddMachine("precise", state.JobHostUnits)
    40  	c.Assert(err, jc.ErrorIsNil)
    41  	err = m1.SetProvisioned(instance.Id("manual:1"), "manual:1:fake_nonce", nil)
    42  	c.Assert(err, jc.ErrorIsNil)
    43  	return m0, m1
    44  }
    45  
    46  // setUpInstances adds machines to state backed by instances:
    47  // one manager machine, one non-manager, and a container in the
    48  // non-manager.
    49  func (s *destroyEnvironmentSuite) setUpInstances(c *gc.C) (m0, m1, m2 *state.Machine) {
    50  	m0, err := s.State.AddMachine("precise", state.JobManageEnviron)
    51  	c.Assert(err, jc.ErrorIsNil)
    52  	inst, _ := testing.AssertStartInstance(c, s.Environ, m0.Id())
    53  	err = m0.SetProvisioned(inst.Id(), "fake_nonce", nil)
    54  	c.Assert(err, jc.ErrorIsNil)
    55  
    56  	m1, err = s.State.AddMachine("precise", state.JobHostUnits)
    57  	c.Assert(err, jc.ErrorIsNil)
    58  	inst, _ = testing.AssertStartInstance(c, s.Environ, m1.Id())
    59  	err = m1.SetProvisioned(inst.Id(), "fake_nonce", nil)
    60  	c.Assert(err, jc.ErrorIsNil)
    61  
    62  	m2, err = s.State.AddMachineInsideMachine(state.MachineTemplate{
    63  		Series: "precise",
    64  		Jobs:   []state.MachineJob{state.JobHostUnits},
    65  	}, m1.Id(), instance.LXC)
    66  	c.Assert(err, jc.ErrorIsNil)
    67  	err = m2.SetProvisioned("container0", "fake_nonce", nil)
    68  	c.Assert(err, jc.ErrorIsNil)
    69  
    70  	return m0, m1, m2
    71  }
    72  
    73  func (s *destroyEnvironmentSuite) TestDestroyEnvironmentManual(c *gc.C) {
    74  	_, nonManager := s.setUpManual(c)
    75  
    76  	// If there are any non-manager manual machines in state, DestroyEnvironment will
    77  	// error. It will not set the Dying flag on the environment.
    78  	err := s.APIState.Client().DestroyEnvironment()
    79  	c.Assert(err, gc.ErrorMatches, fmt.Sprintf("failed to destroy environment: manually provisioned machines must first be destroyed with `juju destroy-machine %s`", nonManager.Id()))
    80  	env, err := s.State.Environment()
    81  	c.Assert(err, jc.ErrorIsNil)
    82  	c.Assert(env.Life(), gc.Equals, state.Alive)
    83  
    84  	// If we remove the non-manager machine, it should pass.
    85  	// Manager machines will remain.
    86  	err = nonManager.EnsureDead()
    87  	c.Assert(err, jc.ErrorIsNil)
    88  	err = nonManager.Remove()
    89  	c.Assert(err, jc.ErrorIsNil)
    90  	err = s.APIState.Client().DestroyEnvironment()
    91  	c.Assert(err, jc.ErrorIsNil)
    92  	err = env.Refresh()
    93  	c.Assert(err, jc.ErrorIsNil)
    94  	c.Assert(env.Life(), gc.Equals, state.Dying)
    95  }
    96  
    97  func (s *destroyEnvironmentSuite) TestDestroyEnvironment(c *gc.C) {
    98  	manager, nonManager, _ := s.setUpInstances(c)
    99  	managerId, _ := manager.InstanceId()
   100  	nonManagerId, _ := nonManager.InstanceId()
   101  
   102  	instances, err := s.Environ.Instances([]instance.Id{managerId, nonManagerId})
   103  	c.Assert(err, jc.ErrorIsNil)
   104  	for _, inst := range instances {
   105  		c.Assert(inst, gc.NotNil)
   106  	}
   107  
   108  	services, err := s.State.AllServices()
   109  	c.Assert(err, jc.ErrorIsNil)
   110  
   111  	err = s.APIState.Client().DestroyEnvironment()
   112  	c.Assert(err, jc.ErrorIsNil)
   113  
   114  	// After DestroyEnvironment returns, we should have:
   115  	//   - all non-manager instances stopped
   116  	instances, err = s.Environ.Instances([]instance.Id{managerId, nonManagerId})
   117  	c.Assert(err, gc.Equals, environs.ErrPartialInstances)
   118  	c.Assert(instances[0], gc.NotNil)
   119  	c.Assert(instances[1], jc.ErrorIsNil)
   120  	//   - all services in state are Dying or Dead (or removed altogether),
   121  	//     after running the state Cleanups.
   122  	needsCleanup, err := s.State.NeedsCleanup()
   123  	c.Assert(err, jc.ErrorIsNil)
   124  	c.Assert(needsCleanup, jc.IsTrue)
   125  	err = s.State.Cleanup()
   126  	c.Assert(err, jc.ErrorIsNil)
   127  	for _, s := range services {
   128  		err = s.Refresh()
   129  		if err != nil {
   130  			c.Assert(err, jc.Satisfies, errors.IsNotFound)
   131  		} else {
   132  			c.Assert(s.Life(), gc.Not(gc.Equals), state.Alive)
   133  		}
   134  	}
   135  	//   - environment is Dying
   136  	env, err := s.State.Environment()
   137  	c.Assert(err, jc.ErrorIsNil)
   138  	c.Assert(env.Life(), gc.Equals, state.Dying)
   139  }
   140  
   141  func (s *destroyEnvironmentSuite) TestDestroyEnvironmentWithContainers(c *gc.C) {
   142  	ops := make(chan dummy.Operation, 500)
   143  	dummy.Listen(ops)
   144  
   145  	_, nonManager, _ := s.setUpInstances(c)
   146  	nonManagerId, _ := nonManager.InstanceId()
   147  
   148  	err := s.APIState.Client().DestroyEnvironment()
   149  	c.Assert(err, jc.ErrorIsNil)
   150  	for op := range ops {
   151  		if op, ok := op.(dummy.OpStopInstances); ok {
   152  			c.Assert(op.Ids, jc.SameContents, []instance.Id{nonManagerId})
   153  			break
   154  		}
   155  	}
   156  }
   157  
   158  func (s *destroyEnvironmentSuite) TestBlockDestroyDestroyEnvironment(c *gc.C) {
   159  	// Setup environment
   160  	s.setUpInstances(c)
   161  	s.BlockDestroyEnvironment(c, "TestBlockDestroyDestroyEnvironment")
   162  	err := s.APIState.Client().DestroyEnvironment()
   163  	s.AssertBlocked(c, err, "TestBlockDestroyDestroyEnvironment")
   164  }
   165  
   166  func (s *destroyEnvironmentSuite) TestBlockRemoveDestroyEnvironment(c *gc.C) {
   167  	// Setup environment
   168  	s.setUpInstances(c)
   169  	s.BlockRemoveObject(c, "TestBlockRemoveDestroyEnvironment")
   170  	err := s.APIState.Client().DestroyEnvironment()
   171  	s.AssertBlocked(c, err, "TestBlockRemoveDestroyEnvironment")
   172  }
   173  
   174  func (s *destroyEnvironmentSuite) TestBlockChangesDestroyEnvironment(c *gc.C) {
   175  	// Setup environment
   176  	s.setUpInstances(c)
   177  	// lock environment: can't destroy locked environment
   178  	s.BlockAllChanges(c, "TestBlockChangesDestroyEnvironment")
   179  	err := s.APIState.Client().DestroyEnvironment()
   180  	s.AssertBlocked(c, err, "TestBlockChangesDestroyEnvironment")
   181  }
   182  
   183  type destroyTwoEnvironmentsSuite struct {
   184  	testing.JujuConnSuite
   185  	otherState     *state.State
   186  	otherEnvOwner  names.UserTag
   187  	otherEnvClient *client.Client
   188  }
   189  
   190  var _ = gc.Suite(&destroyTwoEnvironmentsSuite{})
   191  
   192  func (s *destroyTwoEnvironmentsSuite) SetUpTest(c *gc.C) {
   193  	s.JujuConnSuite.SetUpTest(c)
   194  	s.otherEnvOwner = names.NewUserTag("jess@dummy")
   195  	s.otherState = factory.NewFactory(s.State).MakeEnvironment(c, &factory.EnvParams{
   196  		Owner:   s.otherEnvOwner,
   197  		Prepare: true,
   198  		ConfigAttrs: jujutesting.Attrs{
   199  			"state-server": false,
   200  		},
   201  	})
   202  	s.AddCleanup(func(*gc.C) { s.otherState.Close() })
   203  
   204  	// get the client for the other environment
   205  	auth := apiservertesting.FakeAuthorizer{
   206  		Tag:            s.otherEnvOwner,
   207  		EnvironManager: false,
   208  	}
   209  	var err error
   210  	s.otherEnvClient, err = client.NewClient(s.otherState, common.NewResources(), auth)
   211  	c.Assert(err, jc.ErrorIsNil)
   212  }
   213  
   214  func (s *destroyTwoEnvironmentsSuite) TestCleanupEnvironDocs(c *gc.C) {
   215  	otherFactory := factory.NewFactory(s.otherState)
   216  	otherFactory.MakeMachine(c, nil)
   217  	m := otherFactory.MakeMachine(c, nil)
   218  	otherFactory.MakeMachineNested(c, m.Id(), nil)
   219  
   220  	err := s.otherEnvClient.DestroyEnvironment()
   221  	c.Assert(err, jc.ErrorIsNil)
   222  
   223  	_, err = s.otherState.Environment()
   224  	c.Assert(errors.IsNotFound(err), jc.IsTrue)
   225  
   226  	_, err = s.State.Environment()
   227  	c.Assert(err, jc.ErrorIsNil)
   228  	c.Assert(s.otherState.EnsureEnvironmentRemoved(), jc.ErrorIsNil)
   229  }
   230  
   231  func (s *destroyTwoEnvironmentsSuite) TestDestroyStateServerAfterNonStateServerIsDestroyed(c *gc.C) {
   232  	err := s.APIState.Client().DestroyEnvironment()
   233  	c.Assert(err, gc.ErrorMatches, "failed to destroy environment: state server environment cannot be destroyed before all other environments are destroyed")
   234  	err = s.otherEnvClient.DestroyEnvironment()
   235  	c.Assert(err, jc.ErrorIsNil)
   236  	err = s.APIState.Client().DestroyEnvironment()
   237  	c.Assert(err, jc.ErrorIsNil)
   238  }