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