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 = ¶ms.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 = ¶ms.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 }