github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/provider/common/destroy_test.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package common_test 5 6 import ( 7 "errors" 8 "fmt" 9 "strings" 10 11 gitjujutesting "github.com/juju/testing" 12 jc "github.com/juju/testing/checkers" 13 gc "gopkg.in/check.v1" 14 15 "github.com/juju/juju/environs" 16 "github.com/juju/juju/environs/config" 17 "github.com/juju/juju/instance" 18 "github.com/juju/juju/provider/common" 19 "github.com/juju/juju/storage" 20 "github.com/juju/juju/storage/provider/dummy" 21 "github.com/juju/juju/storage/provider/registry" 22 "github.com/juju/juju/testing" 23 jujuversion "github.com/juju/juju/version" 24 ) 25 26 type DestroySuite struct { 27 testing.BaseSuite 28 } 29 30 var _ = gc.Suite(&DestroySuite{}) 31 32 func (s *DestroySuite) TestCannotGetInstances(c *gc.C) { 33 env := &mockEnviron{ 34 allInstances: func() ([]instance.Instance, error) { 35 return nil, fmt.Errorf("nope") 36 }, 37 config: configGetter(c), 38 } 39 err := common.Destroy(env) 40 c.Assert(err, gc.ErrorMatches, "destroying instances: nope") 41 } 42 43 func (s *DestroySuite) TestCannotStopInstances(c *gc.C) { 44 env := &mockEnviron{ 45 allInstances: func() ([]instance.Instance, error) { 46 return []instance.Instance{ 47 &mockInstance{id: "one"}, 48 &mockInstance{id: "another"}, 49 }, nil 50 }, 51 stopInstances: func(ids []instance.Id) error { 52 c.Assert(ids, gc.HasLen, 2) 53 c.Assert(ids[0], gc.Equals, instance.Id("one")) 54 c.Assert(ids[1], gc.Equals, instance.Id("another")) 55 return fmt.Errorf("nah") 56 }, 57 config: configGetter(c), 58 } 59 err := common.Destroy(env) 60 c.Assert(err, gc.ErrorMatches, "destroying instances: nah") 61 } 62 63 func (s *DestroySuite) TestSuccessWhenStorageErrors(c *gc.C) { 64 // common.Destroy doesn't touch provider/object storage anymore, 65 // so failing storage should not affect success. 66 env := &mockEnviron{ 67 storage: &mockStorage{removeAllErr: fmt.Errorf("noes!")}, 68 allInstances: func() ([]instance.Instance, error) { 69 return []instance.Instance{ 70 &mockInstance{id: "one"}, 71 &mockInstance{id: "another"}, 72 }, nil 73 }, 74 stopInstances: func(ids []instance.Id) error { 75 c.Assert(ids, gc.HasLen, 2) 76 c.Assert(ids[0], gc.Equals, instance.Id("one")) 77 c.Assert(ids[1], gc.Equals, instance.Id("another")) 78 return nil 79 }, 80 config: configGetter(c), 81 } 82 err := common.Destroy(env) 83 c.Assert(err, jc.ErrorIsNil) 84 } 85 86 func (s *DestroySuite) TestSuccess(c *gc.C) { 87 s.PatchValue(&jujuversion.Current, testing.FakeVersionNumber) 88 stor := newStorage(s, c) 89 err := stor.Put("somewhere", strings.NewReader("stuff"), 5) 90 c.Assert(err, jc.ErrorIsNil) 91 92 env := &mockEnviron{ 93 storage: stor, 94 allInstances: func() ([]instance.Instance, error) { 95 return []instance.Instance{ 96 &mockInstance{id: "one"}, 97 }, nil 98 }, 99 stopInstances: func(ids []instance.Id) error { 100 c.Assert(ids, gc.HasLen, 1) 101 c.Assert(ids[0], gc.Equals, instance.Id("one")) 102 return nil 103 }, 104 config: configGetter(c), 105 } 106 err = common.Destroy(env) 107 c.Assert(err, jc.ErrorIsNil) 108 109 // common.Destroy doesn't touch provider/object storage anymore. 110 r, err := stor.Get("somewhere") 111 c.Assert(err, jc.ErrorIsNil) 112 r.Close() 113 } 114 115 func (s *DestroySuite) TestSuccessWhenNoInstances(c *gc.C) { 116 s.PatchValue(&jujuversion.Current, testing.FakeVersionNumber) 117 stor := newStorage(s, c) 118 err := stor.Put("elsewhere", strings.NewReader("stuff"), 5) 119 c.Assert(err, jc.ErrorIsNil) 120 121 env := &mockEnviron{ 122 storage: stor, 123 allInstances: func() ([]instance.Instance, error) { 124 return nil, environs.ErrNoInstances 125 }, 126 config: configGetter(c), 127 } 128 err = common.Destroy(env) 129 c.Assert(err, jc.ErrorIsNil) 130 } 131 132 func (s *DestroySuite) TestDestroyEnvScopedVolumes(c *gc.C) { 133 volumeSource := &dummy.VolumeSource{ 134 ListVolumesFunc: func() ([]string, error) { 135 return []string{"vol-0", "vol-1", "vol-2"}, nil 136 }, 137 DestroyVolumesFunc: func(ids []string) ([]error, error) { 138 return make([]error, len(ids)), nil 139 }, 140 } 141 staticProvider := &dummy.StorageProvider{ 142 IsDynamic: true, 143 StorageScope: storage.ScopeEnviron, 144 VolumeSourceFunc: func(*config.Config, *storage.Config) (storage.VolumeSource, error) { 145 return volumeSource, nil 146 }, 147 } 148 registry.RegisterProvider("environ", staticProvider) 149 defer registry.RegisterProvider("environ", nil) 150 registry.RegisterEnvironStorageProviders("anything, really", "environ") 151 defer registry.ResetEnvironStorageProviders("anything, really") 152 153 env := &mockEnviron{ 154 config: configGetter(c), 155 allInstances: func() ([]instance.Instance, error) { 156 return nil, environs.ErrNoInstances 157 }, 158 } 159 err := common.Destroy(env) 160 c.Assert(err, jc.ErrorIsNil) 161 162 // common.Destroy will ignore machine-scoped storage providers. 163 staticProvider.CheckCallNames(c, "Dynamic", "Scope", "Supports", "VolumeSource") 164 volumeSource.CheckCalls(c, []gitjujutesting.StubCall{ 165 {"ListVolumes", nil}, 166 {"DestroyVolumes", []interface{}{[]string{"vol-0", "vol-1", "vol-2"}}}, 167 }) 168 } 169 170 func (s *DestroySuite) TestDestroyVolumeErrors(c *gc.C) { 171 volumeSource := &dummy.VolumeSource{ 172 ListVolumesFunc: func() ([]string, error) { 173 return []string{"vol-0", "vol-1", "vol-2"}, nil 174 }, 175 DestroyVolumesFunc: func(ids []string) ([]error, error) { 176 return []error{ 177 nil, 178 errors.New("cannot destroy vol-1"), 179 errors.New("cannot destroy vol-2"), 180 }, nil 181 }, 182 } 183 184 staticProvider := &dummy.StorageProvider{ 185 IsDynamic: true, 186 StorageScope: storage.ScopeEnviron, 187 VolumeSourceFunc: func(*config.Config, *storage.Config) (storage.VolumeSource, error) { 188 return volumeSource, nil 189 }, 190 } 191 registry.RegisterProvider("environ", staticProvider) 192 defer registry.RegisterProvider("environ", nil) 193 registry.RegisterEnvironStorageProviders("anything, really", "environ") 194 defer registry.ResetEnvironStorageProviders("anything, really") 195 196 env := &mockEnviron{ 197 config: configGetter(c), 198 allInstances: func() ([]instance.Instance, error) { 199 return nil, environs.ErrNoInstances 200 }, 201 } 202 err := common.Destroy(env) 203 c.Assert(err, gc.ErrorMatches, "destroying storage: destroying volumes: cannot destroy vol-1, cannot destroy vol-2") 204 } 205 206 func (s *DestroySuite) TestIgnoreStaticVolumes(c *gc.C) { 207 staticProvider := &dummy.StorageProvider{ 208 IsDynamic: false, 209 StorageScope: storage.ScopeEnviron, 210 } 211 registry.RegisterProvider("static", staticProvider) 212 defer registry.RegisterProvider("static", nil) 213 registry.RegisterEnvironStorageProviders("anything, really", "static") 214 defer registry.ResetEnvironStorageProviders("anything, really") 215 216 env := &mockEnviron{ 217 config: configGetter(c), 218 allInstances: func() ([]instance.Instance, error) { 219 return nil, environs.ErrNoInstances 220 }, 221 } 222 err := common.Destroy(env) 223 c.Assert(err, jc.ErrorIsNil) 224 225 // common.Destroy will ignore static storage providers. 226 staticProvider.CheckCallNames(c, "Dynamic") 227 } 228 229 func (s *DestroySuite) TestIgnoreMachineScopedVolumes(c *gc.C) { 230 staticProvider := &dummy.StorageProvider{ 231 IsDynamic: true, 232 StorageScope: storage.ScopeMachine, 233 } 234 registry.RegisterProvider("machine", staticProvider) 235 defer registry.RegisterProvider("machine", nil) 236 registry.RegisterEnvironStorageProviders("anything, really", "machine") 237 defer registry.ResetEnvironStorageProviders("anything, really") 238 239 env := &mockEnviron{ 240 config: configGetter(c), 241 allInstances: func() ([]instance.Instance, error) { 242 return nil, environs.ErrNoInstances 243 }, 244 } 245 err := common.Destroy(env) 246 c.Assert(err, jc.ErrorIsNil) 247 248 // common.Destroy will ignore machine-scoped storage providers. 249 staticProvider.CheckCallNames(c, "Dynamic", "Scope") 250 } 251 252 func (s *DestroySuite) TestIgnoreNoVolumeSupport(c *gc.C) { 253 staticProvider := &dummy.StorageProvider{ 254 IsDynamic: true, 255 StorageScope: storage.ScopeEnviron, 256 SupportsFunc: func(storage.StorageKind) bool { 257 return false 258 }, 259 } 260 registry.RegisterProvider("filesystem", staticProvider) 261 defer registry.RegisterProvider("filesystem", nil) 262 registry.RegisterEnvironStorageProviders("anything, really", "filesystem") 263 defer registry.ResetEnvironStorageProviders("anything, really") 264 265 env := &mockEnviron{ 266 config: configGetter(c), 267 allInstances: func() ([]instance.Instance, error) { 268 return nil, environs.ErrNoInstances 269 }, 270 } 271 err := common.Destroy(env) 272 c.Assert(err, jc.ErrorIsNil) 273 274 // common.Destroy will ignore storage providers that don't support 275 // volumes (until we have persistent filesystems, that is). 276 staticProvider.CheckCallNames(c, "Dynamic", "Scope", "Supports") 277 }