github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/common/modeldestroy_test.go (about) 1 // Copyright 2012-2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package common_test 5 6 import ( 7 "github.com/juju/errors" 8 jtesting "github.com/juju/testing" 9 jc "github.com/juju/testing/checkers" 10 gc "gopkg.in/check.v1" 11 "gopkg.in/juju/names.v2" 12 13 "github.com/juju/juju/apiserver/common" 14 "github.com/juju/juju/apiserver/facades/agent/metricsender" 15 "github.com/juju/juju/state" 16 "github.com/juju/juju/testing" 17 ) 18 19 type destroyModelSuite struct { 20 jtesting.IsolationSuite 21 22 modelManager *mockModelManager 23 metricSender *testMetricSender 24 } 25 26 var _ = gc.Suite(&destroyModelSuite{}) 27 28 func (s *destroyModelSuite) SetUpTest(c *gc.C) { 29 s.IsolationSuite.SetUpTest(c) 30 31 otherModelTag := names.NewModelTag("deadbeef-0bad-400d-8000-4b1d0d06f33d") 32 s.modelManager = &mockModelManager{ 33 models: []*mockModel{ 34 {tag: testing.ModelTag}, 35 {tag: otherModelTag}, 36 }, 37 } 38 s.metricSender = &testMetricSender{} 39 s.PatchValue(common.SendMetrics, s.metricSender.SendMetrics) 40 } 41 42 func (s *destroyModelSuite) TestDestroyModelSendsMetrics(c *gc.C) { 43 err := common.DestroyModel(s.modelManager, nil) 44 c.Assert(err, jc.ErrorIsNil) 45 s.metricSender.CheckCalls(c, []jtesting.StubCall{ 46 {"SendMetrics", []interface{}{s.modelManager}}, 47 }) 48 } 49 50 func (s *destroyModelSuite) TestDestroyModel(c *gc.C) { 51 true_ := true 52 false_ := false 53 s.testDestroyModel(c, nil) 54 s.testDestroyModel(c, &true_) 55 s.testDestroyModel(c, &false_) 56 } 57 58 func (s *destroyModelSuite) testDestroyModel(c *gc.C, destroyStorage *bool) { 59 s.modelManager.ResetCalls() 60 s.modelManager.models[0].ResetCalls() 61 62 err := common.DestroyModel(s.modelManager, destroyStorage) 63 c.Assert(err, jc.ErrorIsNil) 64 65 s.modelManager.CheckCalls(c, []jtesting.StubCall{ 66 {"GetBlockForType", []interface{}{state.DestroyBlock}}, 67 {"GetBlockForType", []interface{}{state.RemoveBlock}}, 68 {"GetBlockForType", []interface{}{state.ChangeBlock}}, 69 {"Model", nil}, 70 }) 71 72 s.modelManager.models[0].CheckCalls(c, []jtesting.StubCall{ 73 {"Destroy", []interface{}{state.DestroyModelParams{ 74 DestroyStorage: destroyStorage, 75 }}}, 76 }) 77 } 78 79 func (s *destroyModelSuite) TestDestroyModelBlocked(c *gc.C) { 80 s.modelManager.SetErrors(errors.New("nope")) 81 82 err := common.DestroyModel(s.modelManager, nil) 83 c.Assert(err, gc.ErrorMatches, "nope") 84 85 s.modelManager.CheckCallNames(c, "GetBlockForType") 86 s.modelManager.models[0].CheckNoCalls(c) 87 } 88 89 func (s *destroyModelSuite) TestDestroyControllerNonControllerModel(c *gc.C) { 90 s.modelManager.models[0].tag = s.modelManager.models[1].tag 91 err := common.DestroyController(s.modelManager, false, nil) 92 c.Assert(err, gc.ErrorMatches, `expected state for controller model UUID deadbeef-0bad-400d-8000-4b1d0d06f33d, got deadbeef-0bad-400d-8000-4b1d0d06f00d`) 93 } 94 95 func (s *destroyModelSuite) TestDestroyController(c *gc.C) { 96 err := common.DestroyController(s.modelManager, false, nil) 97 c.Assert(err, jc.ErrorIsNil) 98 99 s.modelManager.CheckCalls(c, []jtesting.StubCall{ 100 {"ControllerModelTag", nil}, 101 {"GetBlockForType", []interface{}{state.DestroyBlock}}, 102 {"GetBlockForType", []interface{}{state.RemoveBlock}}, 103 {"GetBlockForType", []interface{}{state.ChangeBlock}}, 104 {"Model", nil}, 105 }) 106 s.modelManager.models[0].CheckCalls(c, []jtesting.StubCall{ 107 {"Destroy", []interface{}{state.DestroyModelParams{}}}, 108 }) 109 } 110 111 func (s *destroyModelSuite) TestDestroyControllerReleaseStorage(c *gc.C) { 112 destroyStorage := false 113 err := common.DestroyController(s.modelManager, false, &destroyStorage) 114 c.Assert(err, jc.ErrorIsNil) 115 116 s.modelManager.CheckCalls(c, []jtesting.StubCall{ 117 {"ControllerModelTag", nil}, 118 {"GetBlockForType", []interface{}{state.DestroyBlock}}, 119 {"GetBlockForType", []interface{}{state.RemoveBlock}}, 120 {"GetBlockForType", []interface{}{state.ChangeBlock}}, 121 {"Model", nil}, 122 }) 123 s.modelManager.models[0].CheckCalls(c, []jtesting.StubCall{ 124 {"Destroy", []interface{}{state.DestroyModelParams{ 125 DestroyStorage: &destroyStorage, 126 }}}, 127 }) 128 } 129 130 func (s *destroyModelSuite) TestDestroyControllerDestroyHostedModels(c *gc.C) { 131 err := common.DestroyController(s.modelManager, true, nil) 132 c.Assert(err, jc.ErrorIsNil) 133 134 s.modelManager.CheckCalls(c, []jtesting.StubCall{ 135 {"ControllerModelTag", nil}, 136 {"AllModelUUIDs", nil}, 137 138 {"GetBackend", []interface{}{s.modelManager.models[0].tag.Id()}}, 139 {"GetBlockForType", []interface{}{state.DestroyBlock}}, 140 {"GetBlockForType", []interface{}{state.RemoveBlock}}, 141 {"GetBlockForType", []interface{}{state.ChangeBlock}}, 142 143 {"GetBackend", []interface{}{s.modelManager.models[1].tag.Id()}}, 144 {"GetBlockForType", []interface{}{state.DestroyBlock}}, 145 {"GetBlockForType", []interface{}{state.RemoveBlock}}, 146 {"GetBlockForType", []interface{}{state.ChangeBlock}}, 147 148 {"GetBlockForType", []interface{}{state.DestroyBlock}}, 149 {"GetBlockForType", []interface{}{state.RemoveBlock}}, 150 {"GetBlockForType", []interface{}{state.ChangeBlock}}, 151 {"Model", nil}, 152 }) 153 s.modelManager.models[0].CheckCalls(c, []jtesting.StubCall{ 154 {"Destroy", []interface{}{state.DestroyModelParams{ 155 DestroyHostedModels: true, 156 }}}, 157 }) 158 s.metricSender.CheckCalls(c, []jtesting.StubCall{ 159 // One call per hosted model, and one for the controller model. 160 {"SendMetrics", []interface{}{s.modelManager}}, 161 {"SendMetrics", []interface{}{s.modelManager}}, 162 {"SendMetrics", []interface{}{s.modelManager}}, 163 }) 164 } 165 166 func (s *destroyModelSuite) TestDestroyControllerModelErrs(c *gc.C) { 167 // This is similar to what we'd see if a model was destroyed 168 // but there are still some connections to it lingering. 169 s.modelManager.SetErrors( 170 nil, // for GetBackend, 1st model 171 nil, // for GetBlockForType, 1st model 172 nil, // for GetBlockForType, 1st model 173 nil, // for GetBlockForType, 1st model 174 errors.NotFoundf("pretend I am not here"), // for GetBackend, 2nd model 175 ) 176 err := common.DestroyController(s.modelManager, true, nil) 177 // Processing continued despite one model erring out. 178 c.Assert(err, jc.ErrorIsNil) 179 180 s.modelManager.SetErrors( 181 nil, // for GetBackend, 1st model 182 nil, // for GetBlockForType, 1st model 183 nil, // for GetBlockForType, 1st model 184 nil, // for GetBlockForType, 1st model 185 errors.New("I have a problem"), // for GetBackend, 2nd model 186 ) 187 err = common.DestroyController(s.modelManager, true, nil) 188 // Processing erred out since a model seriously failed. 189 c.Assert(err, gc.ErrorMatches, "I have a problem") 190 } 191 192 type testMetricSender struct { 193 jtesting.Stub 194 } 195 196 func (t *testMetricSender) SendMetrics(st metricsender.ModelBackend) error { 197 t.MethodCall(t, "SendMetrics", st) 198 return t.NextErr() 199 } 200 201 type mockModelManager struct { 202 common.ModelManagerBackend 203 jtesting.Stub 204 205 models []*mockModel 206 } 207 208 func (m *mockModelManager) ControllerModelUUID() string { 209 m.MethodCall(m, "ControllerModelUUID") 210 return m.models[0].UUID() 211 } 212 213 func (m *mockModelManager) ControllerModelTag() names.ModelTag { 214 m.MethodCall(m, "ControllerModelTag") 215 return m.models[0].ModelTag() 216 } 217 218 func (m *mockModelManager) ModelTag() names.ModelTag { 219 return testing.ModelTag 220 } 221 222 func (m *mockModelManager) GetBlockForType(t state.BlockType) (state.Block, bool, error) { 223 m.MethodCall(m, "GetBlockForType", t) 224 return nil, false, m.NextErr() 225 } 226 227 func (m *mockModelManager) AllModelUUIDs() ([]string, error) { 228 m.MethodCall(m, "AllModelUUIDs") 229 var out []string 230 for _, model := range m.models { 231 out = append(out, model.UUID()) 232 } 233 return out, nil 234 } 235 236 func (m *mockModelManager) Model() (common.Model, error) { 237 m.MethodCall(m, "Model") 238 return m.models[0], m.NextErr() 239 } 240 241 func (m *mockModelManager) GetBackend(uuid string) (common.ModelManagerBackend, func() bool, error) { 242 m.MethodCall(m, "GetBackend", uuid) 243 return m, func() bool { return true }, m.NextErr() 244 } 245 246 func (m *mockModelManager) Close() error { 247 m.MethodCall(m, "Close") 248 return m.NextErr() 249 } 250 251 type mockModel struct { 252 common.Model 253 jtesting.Stub 254 tag names.ModelTag 255 } 256 257 func (m *mockModel) ModelTag() names.ModelTag { 258 return m.tag 259 } 260 261 func (m *mockModel) UUID() string { 262 return m.tag.Id() 263 } 264 265 func (m *mockModel) Destroy(args state.DestroyModelParams) error { 266 m.MethodCall(m, "Destroy", args) 267 return m.NextErr() 268 }