github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/cmd/juju/system/kill_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package system_test
     5  
     6  import (
     7  	"bytes"
     8  	"time"
     9  
    10  	"github.com/juju/cmd"
    11  	"github.com/juju/errors"
    12  	jc "github.com/juju/testing/checkers"
    13  	gc "gopkg.in/check.v1"
    14  
    15  	"github.com/juju/juju/api"
    16  	"github.com/juju/juju/apiserver/common"
    17  	"github.com/juju/juju/apiserver/params"
    18  	"github.com/juju/juju/cmd/juju/system"
    19  	cmdtesting "github.com/juju/juju/cmd/testing"
    20  	"github.com/juju/juju/juju"
    21  	_ "github.com/juju/juju/provider/dummy"
    22  	"github.com/juju/juju/testing"
    23  )
    24  
    25  type KillSuite struct {
    26  	DestroySuite
    27  }
    28  
    29  var _ = gc.Suite(&KillSuite{})
    30  
    31  func (s *KillSuite) SetUpTest(c *gc.C) {
    32  	s.DestroySuite.SetUpTest(c)
    33  }
    34  
    35  func (s *KillSuite) runKillCommand(c *gc.C, args ...string) (*cmd.Context, error) {
    36  	cmd := system.NewKillCommand(s.api, s.clientapi, s.apierror, juju.NewAPIFromName)
    37  	return testing.RunCommand(c, cmd, args...)
    38  }
    39  
    40  func (s *KillSuite) newKillCommand() *system.KillCommand {
    41  	return system.NewKillCommand(s.api, s.clientapi, s.apierror, juju.NewAPIFromName)
    42  }
    43  
    44  func (s *KillSuite) TestKillNoSystemNameError(c *gc.C) {
    45  	_, err := s.runKillCommand(c)
    46  	c.Assert(err, gc.ErrorMatches, "no system specified")
    47  }
    48  
    49  func (s *KillSuite) TestKillBadFlags(c *gc.C) {
    50  	_, err := s.runKillCommand(c, "-n")
    51  	c.Assert(err, gc.ErrorMatches, "flag provided but not defined: -n")
    52  }
    53  
    54  func (s *KillSuite) TestKillUnknownArgument(c *gc.C) {
    55  	_, err := s.runKillCommand(c, "environment", "whoops")
    56  	c.Assert(err, gc.ErrorMatches, `unrecognized args: \["whoops"\]`)
    57  }
    58  
    59  func (s *KillSuite) TestKillNoDialer(c *gc.C) {
    60  	cmd := system.NewKillCommand(nil, nil, nil, nil)
    61  	_, err := testing.RunCommand(c, cmd, "test1", "-y")
    62  	c.Assert(err, gc.ErrorMatches, "no api dialer specified")
    63  }
    64  
    65  func (s *KillSuite) TestKillUnknownSystem(c *gc.C) {
    66  	_, err := s.runKillCommand(c, "foo")
    67  	c.Assert(err, gc.ErrorMatches, `cannot read system info: environment "foo" not found`)
    68  }
    69  
    70  func (s *KillSuite) TestKillNonSystemEnvFails(c *gc.C) {
    71  	_, err := s.runKillCommand(c, "test2")
    72  	c.Assert(err, gc.ErrorMatches, "\"test2\" is not a system; use juju environment destroy to destroy it")
    73  }
    74  
    75  func (s *KillSuite) TestKillCannotConnectToAPISucceeds(c *gc.C) {
    76  	s.apierror = errors.New("connection refused")
    77  	ctx, err := s.runKillCommand(c, "test1", "-y")
    78  	c.Assert(err, jc.ErrorIsNil)
    79  	c.Check(testing.Stderr(ctx), jc.Contains, "Unable to open API: connection refused")
    80  	checkSystemRemovedFromStore(c, "test1", s.store)
    81  
    82  	// Check that we didn't call the API
    83  	c.Assert(s.api.ignoreBlocks, jc.IsFalse)
    84  }
    85  
    86  func (s *KillSuite) TestKillWithAPIConnection(c *gc.C) {
    87  	_, err := s.runKillCommand(c, "test1", "-y")
    88  	c.Assert(err, jc.ErrorIsNil)
    89  	c.Assert(s.api.ignoreBlocks, jc.IsTrue)
    90  	c.Assert(s.api.destroyAll, jc.IsTrue)
    91  	c.Assert(s.clientapi.destroycalled, jc.IsFalse)
    92  	checkSystemRemovedFromStore(c, "test1", s.store)
    93  }
    94  
    95  func (s *KillSuite) TestKillEnvironmentGetFailsWithoutAPIConnection(c *gc.C) {
    96  	s.apierror = errors.New("connection refused")
    97  	s.api.err = errors.NotFoundf(`system "test3"`)
    98  	_, err := s.runKillCommand(c, "test3", "-y")
    99  	c.Assert(err, gc.ErrorMatches, "cannot obtain bootstrap information: unable to get bootstrap information from API")
   100  	checkSystemExistsInStore(c, "test3", s.store)
   101  }
   102  
   103  func (s *KillSuite) TestKillEnvironmentGetFailsWithAPIConnection(c *gc.C) {
   104  	s.api.err = errors.NotFoundf(`system "test3"`)
   105  	_, err := s.runKillCommand(c, "test3", "-y")
   106  	c.Assert(err, gc.ErrorMatches, "cannot obtain bootstrap information: system \"test3\" not found")
   107  	checkSystemExistsInStore(c, "test3", s.store)
   108  }
   109  
   110  func (s *KillSuite) TestKillFallsBackToClient(c *gc.C) {
   111  	s.api.err = &params.Error{"DestroySystem", params.CodeNotImplemented}
   112  	_, err := s.runKillCommand(c, "test1", "-y")
   113  	c.Assert(err, jc.ErrorIsNil)
   114  	c.Assert(s.clientapi.destroycalled, jc.IsTrue)
   115  	checkSystemRemovedFromStore(c, "test1", s.store)
   116  }
   117  
   118  func (s *KillSuite) TestClientKillDestroysSystemWithAPIError(c *gc.C) {
   119  	s.api.err = &params.Error{"DestroySystem", params.CodeNotImplemented}
   120  	s.clientapi.err = errors.New("some destroy error")
   121  	ctx, err := s.runKillCommand(c, "test1", "-y")
   122  	c.Assert(err, jc.ErrorIsNil)
   123  	c.Check(testing.Stderr(ctx), jc.Contains, "Unable to destroy system through the API: some destroy error.  Destroying through provider.")
   124  	c.Assert(s.clientapi.destroycalled, jc.IsTrue)
   125  	checkSystemRemovedFromStore(c, "test1", s.store)
   126  }
   127  
   128  func (s *KillSuite) TestKillDestroysSystemWithAPIError(c *gc.C) {
   129  	s.api.err = errors.New("some destroy error")
   130  	ctx, err := s.runKillCommand(c, "test1", "-y")
   131  	c.Assert(err, jc.ErrorIsNil)
   132  	c.Check(testing.Stderr(ctx), jc.Contains, "Unable to destroy system through the API: some destroy error.  Destroying through provider.")
   133  	c.Assert(s.api.ignoreBlocks, jc.IsTrue)
   134  	c.Assert(s.api.destroyAll, jc.IsTrue)
   135  	checkSystemRemovedFromStore(c, "test1", s.store)
   136  }
   137  
   138  func (s *KillSuite) TestKillCommandConfirmation(c *gc.C) {
   139  	var stdin, stdout bytes.Buffer
   140  	ctx, err := cmd.DefaultContext()
   141  	c.Assert(err, jc.ErrorIsNil)
   142  	ctx.Stdout = &stdout
   143  	ctx.Stdin = &stdin
   144  
   145  	// Ensure confirmation is requested if "-y" is not specified.
   146  	stdin.WriteString("n")
   147  	_, errc := cmdtesting.RunCommand(ctx, s.newKillCommand(), "test1")
   148  	select {
   149  	case err := <-errc:
   150  		c.Check(err, gc.ErrorMatches, "system destruction aborted")
   151  	case <-time.After(testing.LongWait):
   152  		c.Fatalf("command took too long")
   153  	}
   154  	c.Check(testing.Stdout(ctx), gc.Matches, "WARNING!.*test1(.|\n)*")
   155  	checkSystemExistsInStore(c, "test1", s.store)
   156  }
   157  
   158  func (s *KillSuite) TestKillAPIPermErrFails(c *gc.C) {
   159  	testDialer := func(sysName string) (api.Connection, error) {
   160  		return nil, common.ErrPerm
   161  	}
   162  
   163  	cmd := system.NewKillCommand(nil, nil, nil, testDialer)
   164  	_, err := testing.RunCommand(c, cmd, "test1", "-y")
   165  	c.Assert(err, gc.ErrorMatches, "cannot destroy system: permission denied")
   166  	c.Assert(s.api.ignoreBlocks, jc.IsFalse)
   167  	checkSystemExistsInStore(c, "test1", s.store)
   168  }
   169  
   170  func (s *KillSuite) TestKillEarlyAPIConnectionTimeout(c *gc.C) {
   171  	stop := make(chan struct{})
   172  	defer close(stop)
   173  	testDialer := func(sysName string) (api.Connection, error) {
   174  		<-stop
   175  		return nil, errors.New("kill command waited too long")
   176  	}
   177  
   178  	done := make(chan struct{})
   179  	go func() {
   180  		defer close(done)
   181  		cmd := system.NewKillCommand(nil, nil, nil, testDialer)
   182  		ctx, err := testing.RunCommand(c, cmd, "test1", "-y")
   183  		c.Check(err, jc.ErrorIsNil)
   184  		c.Check(testing.Stderr(ctx), jc.Contains, "Unable to open API: connection to state server timed out")
   185  		c.Check(s.api.ignoreBlocks, jc.IsFalse)
   186  		c.Check(s.api.destroyAll, jc.IsFalse)
   187  		checkSystemRemovedFromStore(c, "test1", s.store)
   188  	}()
   189  	select {
   190  	case <-done:
   191  	case <-time.After(1 * time.Minute):
   192  		c.Fatalf("Kill command waited too long to open the API")
   193  	}
   194  }