github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/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  	jc "github.com/juju/testing/checkers"
    11  	gc "gopkg.in/check.v1"
    12  
    13  	"github.com/juju/juju/apiserver/params"
    14  	"github.com/juju/juju/environs"
    15  	"github.com/juju/juju/instance"
    16  	"github.com/juju/juju/juju/testing"
    17  	"github.com/juju/juju/provider/dummy"
    18  	"github.com/juju/juju/state"
    19  )
    20  
    21  type destroyEnvironmentSuite struct {
    22  	baseSuite
    23  }
    24  
    25  var _ = gc.Suite(&destroyEnvironmentSuite{})
    26  
    27  // setUpManual adds "manually provisioned" machines to state:
    28  // one manager machine, and one non-manager.
    29  func (s *destroyEnvironmentSuite) setUpManual(c *gc.C) (m0, m1 *state.Machine) {
    30  	m0, err := s.State.AddMachine("precise", state.JobManageEnviron)
    31  	c.Assert(err, jc.ErrorIsNil)
    32  	err = m0.SetProvisioned(instance.Id("manual:0"), "manual:0:fake_nonce", nil)
    33  	c.Assert(err, jc.ErrorIsNil)
    34  	m1, err = s.State.AddMachine("precise", state.JobHostUnits)
    35  	c.Assert(err, jc.ErrorIsNil)
    36  	err = m1.SetProvisioned(instance.Id("manual:1"), "manual:1:fake_nonce", nil)
    37  	c.Assert(err, jc.ErrorIsNil)
    38  	return m0, m1
    39  }
    40  
    41  // setUpInstances adds machines to state backed by instances:
    42  // one manager machine, one non-manager, and a container in the
    43  // non-manager.
    44  func (s *destroyEnvironmentSuite) setUpInstances(c *gc.C) (m0, m1, m2 *state.Machine) {
    45  	m0, err := s.State.AddMachine("precise", state.JobManageEnviron)
    46  	c.Assert(err, jc.ErrorIsNil)
    47  	inst, _ := testing.AssertStartInstance(c, s.Environ, m0.Id())
    48  	err = m0.SetProvisioned(inst.Id(), "fake_nonce", nil)
    49  	c.Assert(err, jc.ErrorIsNil)
    50  
    51  	m1, err = s.State.AddMachine("precise", state.JobHostUnits)
    52  	c.Assert(err, jc.ErrorIsNil)
    53  	inst, _ = testing.AssertStartInstance(c, s.Environ, m1.Id())
    54  	err = m1.SetProvisioned(inst.Id(), "fake_nonce", nil)
    55  	c.Assert(err, jc.ErrorIsNil)
    56  
    57  	m2, err = s.State.AddMachineInsideMachine(state.MachineTemplate{
    58  		Series: "precise",
    59  		Jobs:   []state.MachineJob{state.JobHostUnits},
    60  	}, m1.Id(), instance.LXC)
    61  	c.Assert(err, jc.ErrorIsNil)
    62  	err = m2.SetProvisioned("container0", "fake_nonce", nil)
    63  	c.Assert(err, jc.ErrorIsNil)
    64  
    65  	return m0, m1, m2
    66  }
    67  
    68  func (s *destroyEnvironmentSuite) TestDestroyEnvironmentManual(c *gc.C) {
    69  	_, nonManager := s.setUpManual(c)
    70  
    71  	// If there are any non-manager manual machines in state, DestroyEnvironment will
    72  	// error. It will not set the Dying flag on the environment.
    73  	err := s.APIState.Client().DestroyEnvironment()
    74  	c.Assert(err, gc.ErrorMatches, fmt.Sprintf("manually provisioned machines must first be destroyed with `juju destroy-machine %s`", nonManager.Id()))
    75  	env, err := s.State.Environment()
    76  	c.Assert(err, jc.ErrorIsNil)
    77  	c.Assert(env.Life(), gc.Equals, state.Alive)
    78  
    79  	// If we remove the non-manager machine, it should pass.
    80  	// Manager machines will remain.
    81  	err = nonManager.EnsureDead()
    82  	c.Assert(err, jc.ErrorIsNil)
    83  	err = nonManager.Remove()
    84  	c.Assert(err, jc.ErrorIsNil)
    85  	err = s.APIState.Client().DestroyEnvironment()
    86  	c.Assert(err, jc.ErrorIsNil)
    87  	err = env.Refresh()
    88  	c.Assert(err, jc.ErrorIsNil)
    89  	c.Assert(env.Life(), gc.Equals, state.Dying)
    90  }
    91  
    92  func (s *destroyEnvironmentSuite) TestDestroyEnvironment(c *gc.C) {
    93  	manager, nonManager, _ := s.setUpInstances(c)
    94  	managerId, _ := manager.InstanceId()
    95  	nonManagerId, _ := nonManager.InstanceId()
    96  
    97  	instances, err := s.Environ.Instances([]instance.Id{managerId, nonManagerId})
    98  	c.Assert(err, jc.ErrorIsNil)
    99  	for _, inst := range instances {
   100  		c.Assert(inst, gc.NotNil)
   101  	}
   102  
   103  	services, err := s.State.AllServices()
   104  	c.Assert(err, jc.ErrorIsNil)
   105  
   106  	err = s.APIState.Client().DestroyEnvironment()
   107  	c.Assert(err, jc.ErrorIsNil)
   108  
   109  	// After DestroyEnvironment returns, we should have:
   110  	//   - all non-manager instances stopped
   111  	instances, err = s.Environ.Instances([]instance.Id{managerId, nonManagerId})
   112  	c.Assert(err, gc.Equals, environs.ErrPartialInstances)
   113  	c.Assert(instances[0], gc.NotNil)
   114  	c.Assert(instances[1], jc.ErrorIsNil)
   115  	//   - all services in state are Dying or Dead (or removed altogether),
   116  	//     after running the state Cleanups.
   117  	needsCleanup, err := s.State.NeedsCleanup()
   118  	c.Assert(err, jc.ErrorIsNil)
   119  	c.Assert(needsCleanup, jc.IsTrue)
   120  	err = s.State.Cleanup()
   121  	c.Assert(err, jc.ErrorIsNil)
   122  	for _, s := range services {
   123  		err = s.Refresh()
   124  		if err != nil {
   125  			c.Assert(err, jc.Satisfies, errors.IsNotFound)
   126  		} else {
   127  			c.Assert(s.Life(), gc.Not(gc.Equals), state.Alive)
   128  		}
   129  	}
   130  	//   - environment is Dying
   131  	env, err := s.State.Environment()
   132  	c.Assert(err, jc.ErrorIsNil)
   133  	c.Assert(env.Life(), gc.Equals, state.Dying)
   134  }
   135  
   136  func (s *destroyEnvironmentSuite) TestDestroyEnvironmentWithContainers(c *gc.C) {
   137  	ops := make(chan dummy.Operation, 500)
   138  	dummy.Listen(ops)
   139  
   140  	_, nonManager, _ := s.setUpInstances(c)
   141  	nonManagerId, _ := nonManager.InstanceId()
   142  
   143  	err := s.APIState.Client().DestroyEnvironment()
   144  	c.Assert(err, jc.ErrorIsNil)
   145  	for op := range ops {
   146  		if op, ok := op.(dummy.OpStopInstances); ok {
   147  			c.Assert(op.Ids, jc.SameContents, []instance.Id{nonManagerId})
   148  			break
   149  		}
   150  	}
   151  }
   152  
   153  func (s *destroyEnvironmentSuite) TestBlockDestroyDestroyEnvironment(c *gc.C) {
   154  	// Setup environment
   155  	s.setUpInstances(c)
   156  	// lock environment: can't destroy locked environment
   157  	err := s.State.UpdateEnvironConfig(map[string]interface{}{"block-destroy-environment": true}, nil, nil)
   158  	c.Assert(err, jc.ErrorIsNil)
   159  	err = s.APIState.Client().DestroyEnvironment()
   160  	c.Assert(params.IsCodeOperationBlocked(err), jc.IsTrue)
   161  }
   162  
   163  func (s *destroyEnvironmentSuite) TestBlockRemoveDestroyEnvironment(c *gc.C) {
   164  	// Setup environment
   165  	s.setUpInstances(c)
   166  	// lock environment: can't destroy locked environment
   167  	err := s.State.UpdateEnvironConfig(map[string]interface{}{"block-remove-object": true}, nil, nil)
   168  	c.Assert(err, jc.ErrorIsNil)
   169  	err = s.APIState.Client().DestroyEnvironment()
   170  	c.Assert(params.IsCodeOperationBlocked(err), jc.IsTrue)
   171  }
   172  
   173  func (s *destroyEnvironmentSuite) TestBlockChangesDestroyEnvironment(c *gc.C) {
   174  	// Setup environment
   175  	s.setUpInstances(c)
   176  	// lock environment: can't destroy locked environment
   177  	err := s.State.UpdateEnvironConfig(map[string]interface{}{"block-all-changes": true}, nil, nil)
   178  	c.Assert(err, jc.ErrorIsNil)
   179  	err = s.APIState.Client().DestroyEnvironment()
   180  	c.Assert(params.IsCodeOperationBlocked(err), jc.IsTrue)
   181  }