github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/facades/client/controller/destroy_test.go (about) 1 // Copyright 2012-2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package controller_test 5 6 import ( 7 "github.com/juju/errors" 8 jc "github.com/juju/testing/checkers" 9 gc "gopkg.in/check.v1" 10 "gopkg.in/juju/names.v2" 11 12 "github.com/juju/juju/apiserver/common" 13 commontesting "github.com/juju/juju/apiserver/common/testing" 14 "github.com/juju/juju/apiserver/facade/facadetest" 15 "github.com/juju/juju/apiserver/facades/client/controller" 16 "github.com/juju/juju/apiserver/params" 17 apiservertesting "github.com/juju/juju/apiserver/testing" 18 jujutesting "github.com/juju/juju/juju/testing" 19 "github.com/juju/juju/state" 20 "github.com/juju/juju/testing" 21 "github.com/juju/juju/testing/factory" 22 ) 23 24 // NOTE: the testing of the general model destruction code 25 // is found in apiserver/common/modeldestroy_test.go. 26 // 27 // The tests here are around the validation and behaviour of 28 // the flags passed in to the destroy controller call. 29 30 type destroyControllerSuite struct { 31 jujutesting.JujuConnSuite 32 commontesting.BlockHelper 33 34 authorizer apiservertesting.FakeAuthorizer 35 resources *common.Resources 36 controller *controller.ControllerAPI 37 38 otherState *state.State 39 otherModel *state.Model 40 otherModelOwner names.UserTag 41 otherModelUUID string 42 } 43 44 var _ = gc.Suite(&destroyControllerSuite{}) 45 46 func (s *destroyControllerSuite) SetUpTest(c *gc.C) { 47 s.JujuConnSuite.SetUpTest(c) 48 49 s.BlockHelper = commontesting.NewBlockHelper(s.APIState) 50 s.AddCleanup(func(*gc.C) { s.BlockHelper.Close() }) 51 52 s.resources = common.NewResources() 53 s.AddCleanup(func(_ *gc.C) { s.resources.StopAll() }) 54 55 s.authorizer = apiservertesting.FakeAuthorizer{ 56 Tag: s.AdminUserTag(c), 57 } 58 controller, err := controller.NewControllerAPIv7( 59 facadetest.Context{ 60 State_: s.State, 61 StatePool_: s.StatePool, 62 Resources_: s.resources, 63 Auth_: s.authorizer, 64 }) 65 c.Assert(err, jc.ErrorIsNil) 66 s.controller = controller 67 68 s.otherModelOwner = names.NewUserTag("jess@dummy") 69 s.otherState = s.Factory.MakeModel(c, &factory.ModelParams{ 70 Name: "dummytoo", 71 Owner: s.otherModelOwner, 72 ConfigAttrs: testing.Attrs{ 73 "controller": false, 74 }, 75 }) 76 s.AddCleanup(func(c *gc.C) { s.otherState.Close() }) 77 s.otherModelUUID = s.otherState.ModelUUID() 78 79 s.otherModel, err = s.otherState.Model() 80 c.Assert(err, jc.ErrorIsNil) 81 } 82 83 func (s *destroyControllerSuite) TestDestroyControllerKillErrsOnHostedModelsWithBlocks(c *gc.C) { 84 s.BlockDestroyModel(c, "TestBlockDestroyModel") 85 s.BlockRemoveObject(c, "TestBlockRemoveObject") 86 s.otherState.SwitchBlockOn(state.DestroyBlock, "TestBlockDestroyModel") 87 s.otherState.SwitchBlockOn(state.ChangeBlock, "TestChangeBlock") 88 89 err := s.controller.DestroyController(params.DestroyControllerArgs{ 90 DestroyModels: true, 91 }) 92 c.Assert(err, gc.ErrorMatches, "found blocks in controller models") 93 94 model, err := s.State.Model() 95 c.Assert(err, jc.ErrorIsNil) 96 c.Assert(model.Life(), gc.Equals, state.Alive) 97 } 98 99 func (s *destroyControllerSuite) TestDestroyControllerReturnsBlockedModelErr(c *gc.C) { 100 s.BlockDestroyModel(c, "TestBlockDestroyModel") 101 s.BlockRemoveObject(c, "TestBlockRemoveObject") 102 s.otherState.SwitchBlockOn(state.DestroyBlock, "TestBlockDestroyModel") 103 s.otherState.SwitchBlockOn(state.ChangeBlock, "TestChangeBlock") 104 105 err := s.controller.DestroyController(params.DestroyControllerArgs{ 106 DestroyModels: true, 107 }) 108 c.Assert(params.IsCodeOperationBlocked(err), jc.IsTrue) 109 110 numBlocks, err := s.State.AllBlocksForController() 111 c.Assert(err, jc.ErrorIsNil) 112 c.Assert(len(numBlocks), gc.Equals, 4) 113 114 _, err = s.otherState.Model() 115 c.Assert(err, jc.ErrorIsNil) 116 } 117 118 func (s *destroyControllerSuite) TestDestroyControllerKillsHostedModels(c *gc.C) { 119 err := s.controller.DestroyController(params.DestroyControllerArgs{ 120 DestroyModels: true, 121 }) 122 c.Assert(err, jc.ErrorIsNil) 123 124 model, err := s.State.Model() 125 c.Assert(err, jc.ErrorIsNil) 126 c.Assert(model.Life(), gc.Equals, state.Dying) 127 } 128 129 func (s *destroyControllerSuite) TestDestroyControllerLeavesBlocksIfNotKillAll(c *gc.C) { 130 s.BlockDestroyModel(c, "TestBlockDestroyModel") 131 s.BlockRemoveObject(c, "TestBlockRemoveObject") 132 s.otherState.SwitchBlockOn(state.DestroyBlock, "TestBlockDestroyModel") 133 s.otherState.SwitchBlockOn(state.ChangeBlock, "TestChangeBlock") 134 135 err := s.controller.DestroyController(params.DestroyControllerArgs{}) 136 c.Assert(err, gc.ErrorMatches, "found blocks in controller models") 137 138 numBlocks, err := s.State.AllBlocksForController() 139 c.Assert(err, jc.ErrorIsNil) 140 c.Assert(len(numBlocks), gc.Equals, 4) 141 } 142 143 func (s *destroyControllerSuite) TestDestroyControllerNoHostedModels(c *gc.C) { 144 err := common.DestroyModel(common.NewModelManagerBackend(s.otherModel, s.StatePool), nil) 145 c.Assert(err, jc.ErrorIsNil) 146 c.Assert(s.otherModel.Refresh(), jc.ErrorIsNil) 147 c.Assert(s.otherModel.Life(), gc.Equals, state.Dying) 148 c.Assert(s.otherModel.State().RemoveDyingModel(), jc.ErrorIsNil) 149 c.Assert(s.otherModel.Refresh(), jc.Satisfies, errors.IsNotFound) 150 151 err = s.controller.DestroyController(params.DestroyControllerArgs{}) 152 c.Assert(err, jc.ErrorIsNil) 153 154 model, err := s.State.Model() 155 c.Assert(err, jc.ErrorIsNil) 156 c.Assert(model.Life(), gc.Equals, state.Dying) 157 } 158 159 func (s *destroyControllerSuite) TestDestroyControllerErrsOnNoHostedModelsWithBlock(c *gc.C) { 160 err := common.DestroyModel(common.NewModelManagerBackend(s.otherModel, s.StatePool), nil) 161 c.Assert(err, jc.ErrorIsNil) 162 163 s.BlockDestroyModel(c, "TestBlockDestroyModel") 164 s.BlockRemoveObject(c, "TestBlockRemoveObject") 165 166 err = s.controller.DestroyController(params.DestroyControllerArgs{}) 167 c.Assert(err, gc.ErrorMatches, "found blocks in controller models") 168 models, err := s.State.Model() 169 c.Assert(err, jc.ErrorIsNil) 170 c.Assert(models.Life(), gc.Equals, state.Alive) 171 } 172 173 func (s *destroyControllerSuite) TestDestroyControllerNoHostedModelsWithBlockFail(c *gc.C) { 174 err := common.DestroyModel(common.NewModelManagerBackend(s.otherModel, s.StatePool), nil) 175 c.Assert(err, jc.ErrorIsNil) 176 177 s.BlockDestroyModel(c, "TestBlockDestroyModel") 178 s.BlockRemoveObject(c, "TestBlockRemoveObject") 179 180 err = s.controller.DestroyController(params.DestroyControllerArgs{}) 181 c.Assert(params.IsCodeOperationBlocked(err), jc.IsTrue) 182 183 numBlocks, err := s.State.AllBlocksForController() 184 c.Assert(err, jc.ErrorIsNil) 185 c.Assert(len(numBlocks), gc.Equals, 2) 186 } 187 188 func (s *destroyControllerSuite) TestDestroyControllerDestroyStorageNotSpecified(c *gc.C) { 189 f := factory.NewFactory(s.otherState, s.StatePool) 190 f.MakeUnit(c, &factory.UnitParams{ 191 Application: f.MakeApplication(c, &factory.ApplicationParams{ 192 Charm: f.MakeCharm(c, &factory.CharmParams{ 193 Name: "storage-block", 194 }), 195 Storage: map[string]state.StorageConstraints{ 196 "data": {Pool: "modelscoped"}, 197 }, 198 }), 199 }) 200 201 err := s.controller.DestroyController(params.DestroyControllerArgs{ 202 DestroyModels: true, 203 }) 204 c.Assert(err, jc.Satisfies, state.IsHasPersistentStorageError) 205 206 model, err := s.State.Model() 207 c.Assert(err, jc.ErrorIsNil) 208 c.Assert(model.Life(), gc.Equals, state.Alive) 209 } 210 211 func (s *destroyControllerSuite) TestDestroyControllerDestroyStorageSpecified(c *gc.C) { 212 f := factory.NewFactory(s.otherState, s.StatePool) 213 f.MakeUnit(c, &factory.UnitParams{ 214 Application: f.MakeApplication(c, &factory.ApplicationParams{ 215 Charm: f.MakeCharm(c, &factory.CharmParams{ 216 Name: "storage-block", 217 }), 218 Storage: map[string]state.StorageConstraints{ 219 "data": {Pool: "modelscoped"}, 220 }, 221 }), 222 }) 223 224 destroyStorage := false 225 err := s.controller.DestroyController(params.DestroyControllerArgs{ 226 DestroyModels: true, 227 DestroyStorage: &destroyStorage, 228 }) 229 c.Assert(err, jc.ErrorIsNil) 230 231 model, err := s.State.Model() 232 c.Assert(err, jc.ErrorIsNil) 233 c.Assert(model.Life(), gc.Equals, state.Dying) 234 } 235 236 func (s *destroyControllerSuite) TestDestroyControllerDestroyStorageNotSpecifiedV3(c *gc.C) { 237 controller, err := controller.NewControllerAPIv3(facadetest.Context{ 238 State_: s.State, 239 StatePool_: s.StatePool, 240 Resources_: s.resources, 241 Auth_: s.authorizer, 242 }) 243 c.Assert(err, jc.ErrorIsNil) 244 245 f := factory.NewFactory(s.otherState, s.StatePool) 246 f.MakeUnit(c, &factory.UnitParams{ 247 Application: f.MakeApplication(c, &factory.ApplicationParams{ 248 Charm: f.MakeCharm(c, &factory.CharmParams{ 249 Name: "storage-block", 250 }), 251 Storage: map[string]state.StorageConstraints{ 252 "data": {Pool: "modelscoped"}, 253 }, 254 }), 255 }) 256 257 err = controller.DestroyController(params.DestroyControllerArgs{ 258 DestroyModels: true, 259 }) 260 c.Assert(err, jc.ErrorIsNil) 261 262 model, err := s.State.Model() 263 c.Assert(err, jc.ErrorIsNil) 264 c.Assert(model.Life(), gc.Equals, state.Dying) 265 } 266 267 func (s *destroyControllerSuite) TestDestroyControllerDestroyStorageSpecifiedV3(c *gc.C) { 268 controller, err := controller.NewControllerAPIv3(facadetest.Context{ 269 State_: s.State, 270 StatePool_: s.StatePool, 271 Resources_: s.resources, 272 Auth_: s.authorizer, 273 }) 274 c.Assert(err, jc.ErrorIsNil) 275 276 destroyStorage := true 277 err = controller.DestroyController(params.DestroyControllerArgs{ 278 DestroyModels: true, 279 DestroyStorage: &destroyStorage, 280 }) 281 c.Assert(err, gc.ErrorMatches, "destroy-storage unexpected on the v3 API") 282 }