github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/cmd/juju/destroyenvironment_test.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package main
     5  
     6  import (
     7  	"bytes"
     8  
     9  	"github.com/juju/cmd"
    10  	"github.com/juju/errors"
    11  	jc "github.com/juju/testing/checkers"
    12  	gc "gopkg.in/check.v1"
    13  
    14  	"github.com/juju/juju/cmd/envcmd"
    15  	cmdtesting "github.com/juju/juju/cmd/testing"
    16  	"github.com/juju/juju/environs"
    17  	"github.com/juju/juju/environs/configstore"
    18  	"github.com/juju/juju/instance"
    19  	"github.com/juju/juju/juju/testing"
    20  	"github.com/juju/juju/provider/dummy"
    21  	coretesting "github.com/juju/juju/testing"
    22  )
    23  
    24  type destroyEnvSuite struct {
    25  	testing.JujuConnSuite
    26  }
    27  
    28  var _ = gc.Suite(&destroyEnvSuite{})
    29  
    30  func (s *destroyEnvSuite) TestDestroyEnvironmentCommand(c *gc.C) {
    31  	// Prepare the environment so we can destroy it.
    32  	_, err := environs.PrepareFromName("dummyenv", envcmd.BootstrapContext(cmdtesting.NullContext(c)), s.ConfigStore)
    33  	c.Assert(err, jc.ErrorIsNil)
    34  
    35  	// check environment is mandatory
    36  	opc, errc := cmdtesting.RunCommand(cmdtesting.NullContext(c), new(DestroyEnvironmentCommand))
    37  	c.Check(<-errc, gc.Equals, NoEnvironmentError)
    38  
    39  	// normal destroy
    40  	opc, errc = cmdtesting.RunCommand(cmdtesting.NullContext(c), new(DestroyEnvironmentCommand), "dummyenv", "--yes")
    41  	c.Check(<-errc, gc.IsNil)
    42  	c.Check((<-opc).(dummy.OpDestroy).Env, gc.Equals, "dummyenv")
    43  
    44  	// Verify that the environment information has been removed.
    45  	_, err = s.ConfigStore.ReadInfo("dummyenv")
    46  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
    47  }
    48  
    49  // startEnvironment prepare the environment so we can destroy it.
    50  func (s *destroyEnvSuite) startEnvironment(c *gc.C, desiredEnvName string) {
    51  	_, err := environs.PrepareFromName(desiredEnvName, envcmd.BootstrapContext(cmdtesting.NullContext(c)), s.ConfigStore)
    52  	c.Assert(err, jc.ErrorIsNil)
    53  }
    54  
    55  func (s *destroyEnvSuite) checkDestroyEnvironment(c *gc.C, blocked, force bool) {
    56  	//Setup environment
    57  	envName := "dummyenv"
    58  	s.startEnvironment(c, envName)
    59  	s.AssertConfigParameterUpdated(c, "block-destroy-environment", blocked)
    60  	opc := make(chan dummy.Operation)
    61  	errc := make(chan error)
    62  	if force {
    63  		opc, errc = cmdtesting.RunCommand(cmdtesting.NullContext(c), new(DestroyEnvironmentCommand), envName, "--yes", "--force")
    64  	} else {
    65  		opc, errc = cmdtesting.RunCommand(cmdtesting.NullContext(c), new(DestroyEnvironmentCommand), envName, "--yes")
    66  	}
    67  	if force || !blocked {
    68  		c.Check(<-errc, gc.IsNil)
    69  		c.Check((<-opc).(dummy.OpDestroy).Env, gc.Equals, envName)
    70  		// Verify that the environment information has been removed.
    71  		_, err := s.ConfigStore.ReadInfo(envName)
    72  		c.Assert(err, jc.Satisfies, errors.IsNotFound)
    73  	} else {
    74  		c.Check(<-errc, gc.Not(gc.IsNil))
    75  		c.Check((<-opc), gc.IsNil)
    76  		// Verify that the environment information has not been removed.
    77  		_, err := s.ConfigStore.ReadInfo(envName)
    78  		c.Assert(err, jc.ErrorIsNil)
    79  	}
    80  }
    81  
    82  func (s *destroyEnvSuite) TestDestroyLockedEnvironment(c *gc.C) {
    83  	// lock environment: can't destroy locked environment
    84  	s.checkDestroyEnvironment(c, true, false)
    85  }
    86  
    87  func (s *destroyEnvSuite) TestDestroyUnlockedEnvironment(c *gc.C) {
    88  	s.checkDestroyEnvironment(c, false, false)
    89  }
    90  
    91  func (s *destroyEnvSuite) TestForceDestroyLockedEnvironment(c *gc.C) {
    92  	s.checkDestroyEnvironment(c, true, true)
    93  }
    94  
    95  func (s *destroyEnvSuite) TestForceDestroyUnlockedEnvironment(c *gc.C) {
    96  	s.checkDestroyEnvironment(c, false, true)
    97  }
    98  
    99  func (s *destroyEnvSuite) TestDestroyEnvironmentCommandEFlag(c *gc.C) {
   100  	// Prepare the environment so we can destroy it.
   101  	_, err := environs.PrepareFromName("dummyenv", envcmd.BootstrapContext(cmdtesting.NullContext(c)), s.ConfigStore)
   102  	c.Assert(err, jc.ErrorIsNil)
   103  
   104  	// check that either environment or the flag is mandatory
   105  	opc, errc := cmdtesting.RunCommand(cmdtesting.NullContext(c), new(DestroyEnvironmentCommand))
   106  	c.Check(<-errc, gc.Equals, NoEnvironmentError)
   107  
   108  	// We don't allow them to supply both entries at the same time
   109  	opc, errc = cmdtesting.RunCommand(cmdtesting.NullContext(c), new(DestroyEnvironmentCommand), "-e", "dummyenv", "dummyenv", "--yes")
   110  	c.Check(<-errc, gc.Equals, DoubleEnvironmentError)
   111  	// We treat --environment the same way
   112  	opc, errc = cmdtesting.RunCommand(cmdtesting.NullContext(c), new(DestroyEnvironmentCommand), "--environment", "dummyenv", "dummyenv", "--yes")
   113  	c.Check(<-errc, gc.Equals, DoubleEnvironmentError)
   114  
   115  	// destroy using the -e flag
   116  	opc, errc = cmdtesting.RunCommand(cmdtesting.NullContext(c), new(DestroyEnvironmentCommand), "-e", "dummyenv", "--yes")
   117  	c.Check(<-errc, gc.IsNil)
   118  	c.Check((<-opc).(dummy.OpDestroy).Env, gc.Equals, "dummyenv")
   119  
   120  	// Verify that the environment information has been removed.
   121  	_, err = s.ConfigStore.ReadInfo("dummyenv")
   122  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   123  }
   124  
   125  func (s *destroyEnvSuite) TestDestroyEnvironmentCommandEmptyJenv(c *gc.C) {
   126  	info := s.ConfigStore.CreateInfo("emptyenv")
   127  	err := info.Write()
   128  	c.Assert(err, jc.ErrorIsNil)
   129  
   130  	context, err := coretesting.RunCommand(c, new(DestroyEnvironmentCommand), "-e", "emptyenv")
   131  	c.Assert(err, jc.ErrorIsNil)
   132  
   133  	c.Assert(coretesting.Stderr(context), gc.Equals, "removing empty environment file\n")
   134  }
   135  
   136  func (s *destroyEnvSuite) TestDestroyEnvironmentCommandBroken(c *gc.C) {
   137  	oldinfo, err := s.ConfigStore.ReadInfo("dummyenv")
   138  	c.Assert(err, jc.ErrorIsNil)
   139  	bootstrapConfig := oldinfo.BootstrapConfig()
   140  	apiEndpoint := oldinfo.APIEndpoint()
   141  	apiCredentials := oldinfo.APICredentials()
   142  	err = oldinfo.Destroy()
   143  	c.Assert(err, jc.ErrorIsNil)
   144  	newinfo := s.ConfigStore.CreateInfo("dummyenv")
   145  
   146  	bootstrapConfig["broken"] = "Destroy"
   147  	newinfo.SetBootstrapConfig(bootstrapConfig)
   148  	newinfo.SetAPIEndpoint(apiEndpoint)
   149  	newinfo.SetAPICredentials(apiCredentials)
   150  	err = newinfo.Write()
   151  	c.Assert(err, jc.ErrorIsNil)
   152  
   153  	// Prepare the environment so we can destroy it.
   154  	_, err = environs.PrepareFromName("dummyenv", envcmd.BootstrapContext(cmdtesting.NullContext(c)), s.ConfigStore)
   155  	c.Assert(err, jc.ErrorIsNil)
   156  
   157  	// destroy with broken environment
   158  	opc, errc := cmdtesting.RunCommand(cmdtesting.NullContext(c), new(DestroyEnvironmentCommand), "dummyenv", "--yes")
   159  	op, ok := (<-opc).(dummy.OpDestroy)
   160  	c.Assert(ok, jc.IsTrue)
   161  	c.Assert(op.Error, gc.ErrorMatches, "dummy.Destroy is broken")
   162  	c.Check(<-errc, gc.Equals, op.Error)
   163  	c.Check(<-opc, gc.IsNil)
   164  }
   165  
   166  func (*destroyEnvSuite) TestDestroyEnvironmentCommandConfirmationFlag(c *gc.C) {
   167  	com := new(DestroyEnvironmentCommand)
   168  	c.Check(coretesting.InitCommand(com, []string{"dummyenv"}), gc.IsNil)
   169  	c.Check(com.assumeYes, jc.IsFalse)
   170  
   171  	com = new(DestroyEnvironmentCommand)
   172  	c.Check(coretesting.InitCommand(com, []string{"dummyenv", "-y"}), gc.IsNil)
   173  	c.Check(com.assumeYes, jc.IsTrue)
   174  
   175  	com = new(DestroyEnvironmentCommand)
   176  	c.Check(coretesting.InitCommand(com, []string{"dummyenv", "--yes"}), gc.IsNil)
   177  	c.Check(com.assumeYes, jc.IsTrue)
   178  }
   179  
   180  func (s *destroyEnvSuite) TestDestroyEnvironmentCommandConfirmation(c *gc.C) {
   181  	var stdin, stdout bytes.Buffer
   182  	ctx, err := cmd.DefaultContext()
   183  	c.Assert(err, jc.ErrorIsNil)
   184  	ctx.Stdout = &stdout
   185  	ctx.Stdin = &stdin
   186  
   187  	// Prepare the environment so we can destroy it.
   188  	env, err := environs.PrepareFromName("dummyenv", envcmd.BootstrapContext(cmdtesting.NullContext(c)), s.ConfigStore)
   189  	c.Assert(err, jc.ErrorIsNil)
   190  
   191  	assertEnvironNotDestroyed(c, env, s.ConfigStore)
   192  
   193  	// Ensure confirmation is requested if "-y" is not specified.
   194  	stdin.WriteString("n")
   195  	opc, errc := cmdtesting.RunCommand(ctx, new(DestroyEnvironmentCommand), "dummyenv")
   196  	c.Check(<-errc, gc.ErrorMatches, "environment destruction aborted")
   197  	c.Check(<-opc, gc.IsNil)
   198  	c.Check(stdout.String(), gc.Matches, "WARNING!.*dummyenv.*\\(type: dummy\\)(.|\n)*")
   199  	assertEnvironNotDestroyed(c, env, s.ConfigStore)
   200  
   201  	// EOF on stdin: equivalent to answering no.
   202  	stdin.Reset()
   203  	stdout.Reset()
   204  	opc, errc = cmdtesting.RunCommand(ctx, new(DestroyEnvironmentCommand), "dummyenv")
   205  	c.Check(<-opc, gc.IsNil)
   206  	c.Check(<-errc, gc.ErrorMatches, "environment destruction aborted")
   207  	assertEnvironNotDestroyed(c, env, s.ConfigStore)
   208  
   209  	// "--yes" passed: no confirmation request.
   210  	stdin.Reset()
   211  	stdout.Reset()
   212  	opc, errc = cmdtesting.RunCommand(ctx, new(DestroyEnvironmentCommand), "dummyenv", "--yes")
   213  	c.Check(<-errc, gc.IsNil)
   214  	c.Check((<-opc).(dummy.OpDestroy).Env, gc.Equals, "dummyenv")
   215  	c.Check(stdout.String(), gc.Equals, "")
   216  	assertEnvironDestroyed(c, env, s.ConfigStore)
   217  
   218  	// Any of casing of "y" and "yes" will confirm.
   219  	for _, answer := range []string{"y", "Y", "yes", "YES"} {
   220  		// Prepare the environment so we can destroy it.
   221  		s.Reset(c)
   222  		env, err := environs.PrepareFromName("dummyenv", envcmd.BootstrapContext(cmdtesting.NullContext(c)), s.ConfigStore)
   223  		c.Assert(err, jc.ErrorIsNil)
   224  
   225  		stdin.Reset()
   226  		stdout.Reset()
   227  		stdin.WriteString(answer)
   228  		opc, errc = cmdtesting.RunCommand(ctx, new(DestroyEnvironmentCommand), "dummyenv")
   229  		c.Check(<-errc, gc.IsNil)
   230  		c.Check((<-opc).(dummy.OpDestroy).Env, gc.Equals, "dummyenv")
   231  		c.Check(stdout.String(), gc.Matches, "WARNING!.*dummyenv.*\\(type: dummy\\)(.|\n)*")
   232  		assertEnvironDestroyed(c, env, s.ConfigStore)
   233  	}
   234  }
   235  
   236  func assertEnvironDestroyed(c *gc.C, env environs.Environ, store configstore.Storage) {
   237  	_, err := store.ReadInfo(env.Config().Name())
   238  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   239  
   240  	_, err = env.Instances([]instance.Id{"invalid"})
   241  	c.Assert(err, gc.ErrorMatches, "environment has been destroyed")
   242  }
   243  
   244  func assertEnvironNotDestroyed(c *gc.C, env environs.Environ, store configstore.Storage) {
   245  	info, err := store.ReadInfo(env.Config().Name())
   246  	c.Assert(err, jc.ErrorIsNil)
   247  	c.Assert(info.Initialized(), jc.IsTrue)
   248  
   249  	_, err = environs.NewFromName(env.Config().Name(), store)
   250  	c.Assert(err, jc.ErrorIsNil)
   251  }