github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/cmd/juju/environment/destroy_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package environment_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/apiserver/params" 16 "github.com/juju/juju/cmd/juju/environment" 17 cmdtesting "github.com/juju/juju/cmd/testing" 18 "github.com/juju/juju/environs/configstore" 19 _ "github.com/juju/juju/provider/dummy" 20 "github.com/juju/juju/testing" 21 ) 22 23 type DestroySuite struct { 24 testing.FakeJujuHomeSuite 25 api *fakeDestroyAPI 26 store configstore.Storage 27 } 28 29 var _ = gc.Suite(&DestroySuite{}) 30 31 // fakeDestroyAPI mocks out the cient API 32 type fakeDestroyAPI struct { 33 err error 34 env map[string]interface{} 35 } 36 37 func (f *fakeDestroyAPI) Close() error { return nil } 38 39 func (f *fakeDestroyAPI) DestroyEnvironment() error { 40 return f.err 41 } 42 43 func (s *DestroySuite) SetUpTest(c *gc.C) { 44 s.FakeJujuHomeSuite.SetUpTest(c) 45 s.api = &fakeDestroyAPI{} 46 s.api.err = nil 47 48 var err error 49 s.store, err = configstore.Default() 50 c.Assert(err, jc.ErrorIsNil) 51 52 var envList = []struct { 53 name string 54 serverUUID string 55 envUUID string 56 }{ 57 { 58 name: "test1", 59 serverUUID: "test1-uuid", 60 envUUID: "test1-uuid", 61 }, { 62 name: "test2", 63 serverUUID: "test1-uuid", 64 envUUID: "test2-uuid", 65 }, 66 } 67 for _, env := range envList { 68 info := s.store.CreateInfo(env.name) 69 info.SetAPIEndpoint(configstore.APIEndpoint{ 70 Addresses: []string{"localhost"}, 71 CACert: testing.CACert, 72 EnvironUUID: env.envUUID, 73 ServerUUID: env.serverUUID, 74 }) 75 76 err := info.Write() 77 c.Assert(err, jc.ErrorIsNil) 78 } 79 } 80 81 func (s *DestroySuite) runDestroyCommand(c *gc.C, args ...string) (*cmd.Context, error) { 82 cmd := environment.NewDestroyCommand(s.api) 83 return testing.RunCommand(c, cmd, args...) 84 } 85 86 func (s *DestroySuite) newDestroyCommand() *environment.DestroyCommand { 87 return environment.NewDestroyCommand(s.api) 88 } 89 90 func checkEnvironmentExistsInStore(c *gc.C, name string, store configstore.Storage) { 91 _, err := store.ReadInfo(name) 92 c.Assert(err, jc.ErrorIsNil) 93 } 94 95 func checkEnvironmentRemovedFromStore(c *gc.C, name string, store configstore.Storage) { 96 _, err := store.ReadInfo(name) 97 c.Assert(err, jc.Satisfies, errors.IsNotFound) 98 } 99 100 func (s *DestroySuite) TestDestroyNoEnvironmentNameError(c *gc.C) { 101 _, err := s.runDestroyCommand(c) 102 c.Assert(err, gc.ErrorMatches, "no environment specified") 103 } 104 105 func (s *DestroySuite) TestDestroyBadFlags(c *gc.C) { 106 _, err := s.runDestroyCommand(c, "-n") 107 c.Assert(err, gc.ErrorMatches, "flag provided but not defined: -n") 108 } 109 110 func (s *DestroySuite) TestDestroyUnknownArgument(c *gc.C) { 111 _, err := s.runDestroyCommand(c, "environment", "whoops") 112 c.Assert(err, gc.ErrorMatches, `unrecognized args: \["whoops"\]`) 113 } 114 115 func (s *DestroySuite) TestDestroyUnknownEnvironment(c *gc.C) { 116 _, err := s.runDestroyCommand(c, "foo") 117 c.Assert(err, gc.ErrorMatches, `cannot read environment info: environment "foo" not found`) 118 } 119 120 func (s *DestroySuite) TestDestroyCannotConnectToAPI(c *gc.C) { 121 s.api.err = errors.New("connection refused") 122 _, err := s.runDestroyCommand(c, "test2", "-y") 123 c.Assert(err, gc.ErrorMatches, "cannot destroy environment: connection refused") 124 c.Check(c.GetTestLog(), jc.Contains, "failed to destroy environment \"test2\"") 125 checkEnvironmentExistsInStore(c, "test2", s.store) 126 } 127 128 func (s *DestroySuite) TestSystemDestroyFails(c *gc.C) { 129 _, err := s.runDestroyCommand(c, "test1", "-y") 130 c.Assert(err, gc.ErrorMatches, `"test1" is a system; use 'juju system destroy' to destroy it`) 131 checkEnvironmentExistsInStore(c, "test1", s.store) 132 } 133 134 func (s *DestroySuite) TestDestroy(c *gc.C) { 135 checkEnvironmentExistsInStore(c, "test2", s.store) 136 _, err := s.runDestroyCommand(c, "test2", "-y") 137 c.Assert(err, jc.ErrorIsNil) 138 checkEnvironmentRemovedFromStore(c, "test2", s.store) 139 } 140 141 func (s *DestroySuite) TestFailedDestroyEnvironment(c *gc.C) { 142 s.api.err = errors.New("permission denied") 143 _, err := s.runDestroyCommand(c, "test2", "-y") 144 c.Assert(err, gc.ErrorMatches, "cannot destroy environment: permission denied") 145 checkEnvironmentExistsInStore(c, "test2", s.store) 146 } 147 148 func (s *DestroySuite) resetEnvironment(c *gc.C) { 149 info := s.store.CreateInfo("test2") 150 info.SetAPIEndpoint(configstore.APIEndpoint{ 151 Addresses: []string{"localhost"}, 152 CACert: testing.CACert, 153 EnvironUUID: "test2-uuid", 154 ServerUUID: "test1-uuid", 155 }) 156 err := info.Write() 157 c.Assert(err, jc.ErrorIsNil) 158 } 159 160 func (s *DestroySuite) TestDestroyCommandConfirmation(c *gc.C) { 161 var stdin, stdout bytes.Buffer 162 ctx, err := cmd.DefaultContext() 163 c.Assert(err, jc.ErrorIsNil) 164 ctx.Stdout = &stdout 165 ctx.Stdin = &stdin 166 167 // Ensure confirmation is requested if "-y" is not specified. 168 stdin.WriteString("n") 169 _, errc := cmdtesting.RunCommand(ctx, s.newDestroyCommand(), "test2") 170 select { 171 case err := <-errc: 172 c.Check(err, gc.ErrorMatches, "environment destruction: aborted") 173 case <-time.After(testing.LongWait): 174 c.Fatalf("command took too long") 175 } 176 c.Check(testing.Stdout(ctx), gc.Matches, "WARNING!.*test2(.|\n)*") 177 checkEnvironmentExistsInStore(c, "test1", s.store) 178 179 // EOF on stdin: equivalent to answering no. 180 stdin.Reset() 181 stdout.Reset() 182 _, errc = cmdtesting.RunCommand(ctx, s.newDestroyCommand(), "test2") 183 select { 184 case err := <-errc: 185 c.Check(err, gc.ErrorMatches, "environment destruction: aborted") 186 case <-time.After(testing.LongWait): 187 c.Fatalf("command took too long") 188 } 189 c.Check(testing.Stdout(ctx), gc.Matches, "WARNING!.*test2(.|\n)*") 190 checkEnvironmentExistsInStore(c, "test1", s.store) 191 192 for _, answer := range []string{"y", "Y", "yes", "YES"} { 193 stdin.Reset() 194 stdout.Reset() 195 stdin.WriteString(answer) 196 _, errc = cmdtesting.RunCommand(ctx, s.newDestroyCommand(), "test2") 197 select { 198 case err := <-errc: 199 c.Check(err, jc.ErrorIsNil) 200 case <-time.After(testing.LongWait): 201 c.Fatalf("command took too long") 202 } 203 checkEnvironmentRemovedFromStore(c, "test2", s.store) 204 205 // Add the test2 environment back into the store for the next test 206 s.resetEnvironment(c) 207 } 208 } 209 210 func (s *DestroySuite) TestBlockedDestroy(c *gc.C) { 211 s.api.err = ¶ms.Error{Code: params.CodeOperationBlocked} 212 s.runDestroyCommand(c, "test2", "-y") 213 c.Check(c.GetTestLog(), jc.Contains, "To remove the block") 214 }