github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/api/migrationmaster/client_test.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package migrationmaster_test 5 6 import ( 7 "encoding/json" 8 "time" 9 10 "github.com/juju/errors" 11 jujutesting "github.com/juju/testing" 12 jc "github.com/juju/testing/checkers" 13 "github.com/juju/utils" 14 "github.com/juju/version" 15 gc "gopkg.in/check.v1" 16 "gopkg.in/juju/names.v2" 17 "gopkg.in/macaroon.v1" 18 19 "github.com/juju/juju/api/base" 20 apitesting "github.com/juju/juju/api/base/testing" 21 "github.com/juju/juju/api/migrationmaster" 22 "github.com/juju/juju/apiserver/params" 23 "github.com/juju/juju/core/migration" 24 "github.com/juju/juju/watcher" 25 ) 26 27 type ClientSuite struct { 28 jujutesting.IsolationSuite 29 } 30 31 var _ = gc.Suite(&ClientSuite{}) 32 33 func (s *ClientSuite) TestWatch(c *gc.C) { 34 var stub jujutesting.Stub 35 apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { 36 stub.AddCall(objType+"."+request, id, arg) 37 *(result.(*params.NotifyWatchResult)) = params.NotifyWatchResult{ 38 NotifyWatcherId: "123", 39 } 40 return nil 41 }) 42 expectWatch := &struct{ watcher.NotifyWatcher }{} 43 newWatcher := func(caller base.APICaller, result params.NotifyWatchResult) watcher.NotifyWatcher { 44 c.Check(caller, gc.NotNil) 45 c.Check(result, jc.DeepEquals, params.NotifyWatchResult{NotifyWatcherId: "123"}) 46 return expectWatch 47 } 48 client := migrationmaster.NewClient(apiCaller, newWatcher) 49 50 w, err := client.Watch() 51 c.Check(err, jc.ErrorIsNil) 52 c.Check(w, gc.Equals, expectWatch) 53 stub.CheckCalls(c, []jujutesting.StubCall{{"MigrationMaster.Watch", []interface{}{"", nil}}}) 54 } 55 56 func (s *ClientSuite) TestWatchCallError(c *gc.C) { 57 apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { 58 return errors.New("boom") 59 }) 60 client := migrationmaster.NewClient(apiCaller, nil) 61 _, err := client.Watch() 62 c.Assert(err, gc.ErrorMatches, "boom") 63 } 64 65 func (s *ClientSuite) TestMigrationStatus(c *gc.C) { 66 mac, err := macaroon.New([]byte("secret"), "id", "location") 67 c.Assert(err, jc.ErrorIsNil) 68 macs := []macaroon.Slice{{mac}} 69 macsJSON, err := json.Marshal(macs) 70 c.Assert(err, jc.ErrorIsNil) 71 72 modelUUID := utils.MustNewUUID().String() 73 controllerUUID := utils.MustNewUUID().String() 74 controllerTag := names.NewControllerTag(controllerUUID) 75 timestamp := time.Date(2016, 6, 22, 16, 42, 44, 0, time.UTC) 76 apiCaller := apitesting.APICallerFunc(func(_ string, _ int, _, _ string, _, result interface{}) error { 77 out := result.(*params.MasterMigrationStatus) 78 *out = params.MasterMigrationStatus{ 79 Spec: params.MigrationSpec{ 80 ModelTag: names.NewModelTag(modelUUID).String(), 81 TargetInfo: params.MigrationTargetInfo{ 82 ControllerTag: controllerTag.String(), 83 Addrs: []string{"2.2.2.2:2"}, 84 CACert: "cert", 85 AuthTag: names.NewUserTag("admin").String(), 86 Password: "secret", 87 Macaroons: string(macsJSON), 88 }, 89 ExternalControl: true, 90 }, 91 MigrationId: "id", 92 Phase: "IMPORT", 93 PhaseChangedTime: timestamp, 94 } 95 return nil 96 }) 97 client := migrationmaster.NewClient(apiCaller, nil) 98 99 status, err := client.MigrationStatus() 100 c.Assert(err, jc.ErrorIsNil) 101 c.Assert(status, gc.DeepEquals, migration.MigrationStatus{ 102 MigrationId: "id", 103 ModelUUID: modelUUID, 104 Phase: migration.IMPORT, 105 PhaseChangedTime: timestamp, 106 ExternalControl: true, 107 TargetInfo: migration.TargetInfo{ 108 ControllerTag: controllerTag, 109 Addrs: []string{"2.2.2.2:2"}, 110 CACert: "cert", 111 AuthTag: names.NewUserTag("admin"), 112 Password: "secret", 113 Macaroons: macs, 114 }, 115 }) 116 } 117 118 func (s *ClientSuite) TestSetPhase(c *gc.C) { 119 var stub jujutesting.Stub 120 apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { 121 stub.AddCall(objType+"."+request, id, arg) 122 return nil 123 }) 124 client := migrationmaster.NewClient(apiCaller, nil) 125 err := client.SetPhase(migration.QUIESCE) 126 c.Assert(err, jc.ErrorIsNil) 127 expectedArg := params.SetMigrationPhaseArgs{Phase: "QUIESCE"} 128 stub.CheckCalls(c, []jujutesting.StubCall{ 129 {"MigrationMaster.SetPhase", []interface{}{"", expectedArg}}, 130 }) 131 } 132 133 func (s *ClientSuite) TestSetPhaseError(c *gc.C) { 134 apiCaller := apitesting.APICallerFunc(func(string, int, string, string, interface{}, interface{}) error { 135 return errors.New("boom") 136 }) 137 client := migrationmaster.NewClient(apiCaller, nil) 138 err := client.SetPhase(migration.QUIESCE) 139 c.Assert(err, gc.ErrorMatches, "boom") 140 } 141 142 func (s *ClientSuite) TestSetStatusMessage(c *gc.C) { 143 var stub jujutesting.Stub 144 apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { 145 stub.AddCall(objType+"."+request, id, arg) 146 return nil 147 }) 148 client := migrationmaster.NewClient(apiCaller, nil) 149 err := client.SetStatusMessage("foo") 150 c.Assert(err, jc.ErrorIsNil) 151 expectedArg := params.SetMigrationStatusMessageArgs{Message: "foo"} 152 stub.CheckCalls(c, []jujutesting.StubCall{ 153 {"MigrationMaster.SetStatusMessage", []interface{}{"", expectedArg}}, 154 }) 155 } 156 157 func (s *ClientSuite) TestSetStatusMessageError(c *gc.C) { 158 apiCaller := apitesting.APICallerFunc(func(string, int, string, string, interface{}, interface{}) error { 159 return errors.New("boom") 160 }) 161 client := migrationmaster.NewClient(apiCaller, nil) 162 err := client.SetStatusMessage("foo") 163 c.Assert(err, gc.ErrorMatches, "boom") 164 } 165 166 func (s *ClientSuite) TestModelInfo(c *gc.C) { 167 var stub jujutesting.Stub 168 owner := names.NewUserTag("owner") 169 apiCaller := apitesting.APICallerFunc(func(objType string, v int, id, request string, arg, result interface{}) error { 170 stub.AddCall(objType+"."+request, id, arg) 171 *(result.(*params.MigrationModelInfo)) = params.MigrationModelInfo{ 172 UUID: "uuid", 173 Name: "name", 174 OwnerTag: owner.String(), 175 AgentVersion: version.MustParse("1.2.3"), 176 } 177 return nil 178 }) 179 client := migrationmaster.NewClient(apiCaller, nil) 180 model, err := client.ModelInfo() 181 stub.CheckCalls(c, []jujutesting.StubCall{ 182 {"MigrationMaster.ModelInfo", []interface{}{"", nil}}, 183 }) 184 c.Check(err, jc.ErrorIsNil) 185 c.Check(model, jc.DeepEquals, migration.ModelInfo{ 186 UUID: "uuid", 187 Name: "name", 188 Owner: owner, 189 AgentVersion: version.MustParse("1.2.3"), 190 }) 191 } 192 193 func (s *ClientSuite) TestPrechecks(c *gc.C) { 194 var stub jujutesting.Stub 195 apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { 196 stub.AddCall(objType+"."+request, id, arg) 197 return errors.New("blam") 198 }) 199 client := migrationmaster.NewClient(apiCaller, nil) 200 err := client.Prechecks() 201 c.Check(err, gc.ErrorMatches, "blam") 202 stub.CheckCalls(c, []jujutesting.StubCall{ 203 {"MigrationMaster.Prechecks", []interface{}{"", nil}}, 204 }) 205 } 206 207 func (s *ClientSuite) TestExport(c *gc.C) { 208 var stub jujutesting.Stub 209 apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { 210 stub.AddCall(objType+"."+request, id, arg) 211 out := result.(*params.SerializedModel) 212 *out = params.SerializedModel{ 213 Bytes: []byte("foo"), 214 Charms: []string{"cs:foo-1"}, 215 Tools: []params.SerializedModelTools{{ 216 Version: "2.0.0-trusty-amd64", 217 URI: "/tools/0", 218 }}, 219 } 220 return nil 221 }) 222 client := migrationmaster.NewClient(apiCaller, nil) 223 out, err := client.Export() 224 c.Assert(err, jc.ErrorIsNil) 225 stub.CheckCalls(c, []jujutesting.StubCall{ 226 {"MigrationMaster.Export", []interface{}{"", nil}}, 227 }) 228 c.Assert(out, gc.DeepEquals, migration.SerializedModel{ 229 Bytes: []byte("foo"), 230 Charms: []string{"cs:foo-1"}, 231 Tools: map[version.Binary]string{ 232 version.MustParseBinary("2.0.0-trusty-amd64"): "/tools/0", 233 }, 234 }) 235 } 236 237 func (s *ClientSuite) TestExportError(c *gc.C) { 238 apiCaller := apitesting.APICallerFunc(func(string, int, string, string, interface{}, interface{}) error { 239 return errors.New("blam") 240 }) 241 client := migrationmaster.NewClient(apiCaller, nil) 242 _, err := client.Export() 243 c.Assert(err, gc.ErrorMatches, "blam") 244 } 245 246 func (s *ClientSuite) TestReap(c *gc.C) { 247 var stub jujutesting.Stub 248 apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { 249 stub.AddCall(objType+"."+request, id, arg) 250 return nil 251 }) 252 client := migrationmaster.NewClient(apiCaller, nil) 253 err := client.Reap() 254 c.Check(err, jc.ErrorIsNil) 255 stub.CheckCalls(c, []jujutesting.StubCall{ 256 {"MigrationMaster.Reap", []interface{}{"", nil}}, 257 }) 258 } 259 260 func (s *ClientSuite) TestReapError(c *gc.C) { 261 apiCaller := apitesting.APICallerFunc(func(string, int, string, string, interface{}, interface{}) error { 262 return errors.New("blam") 263 }) 264 client := migrationmaster.NewClient(apiCaller, nil) 265 err := client.Reap() 266 c.Assert(err, gc.ErrorMatches, "blam") 267 } 268 269 func (s *ClientSuite) TestWatchMinionReports(c *gc.C) { 270 var stub jujutesting.Stub 271 apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { 272 stub.AddCall(objType+"."+request, id, arg) 273 *(result.(*params.NotifyWatchResult)) = params.NotifyWatchResult{ 274 NotifyWatcherId: "123", 275 } 276 return nil 277 }) 278 279 expectWatch := &struct{ watcher.NotifyWatcher }{} 280 newWatcher := func(caller base.APICaller, result params.NotifyWatchResult) watcher.NotifyWatcher { 281 c.Check(caller, gc.NotNil) 282 c.Check(result, jc.DeepEquals, params.NotifyWatchResult{NotifyWatcherId: "123"}) 283 return expectWatch 284 } 285 client := migrationmaster.NewClient(apiCaller, newWatcher) 286 287 w, err := client.WatchMinionReports() 288 c.Check(err, jc.ErrorIsNil) 289 c.Check(w, gc.Equals, expectWatch) 290 stub.CheckCalls(c, []jujutesting.StubCall{{"MigrationMaster.WatchMinionReports", []interface{}{"", nil}}}) 291 } 292 293 func (s *ClientSuite) TestWatchMinionReportsError(c *gc.C) { 294 apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { 295 return errors.New("boom") 296 }) 297 client := migrationmaster.NewClient(apiCaller, nil) 298 _, err := client.WatchMinionReports() 299 c.Assert(err, gc.ErrorMatches, "boom") 300 } 301 302 func (s *ClientSuite) TestMinionReports(c *gc.C) { 303 var stub jujutesting.Stub 304 apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { 305 stub.AddCall(objType+"."+request, id, arg) 306 out := result.(*params.MinionReports) 307 *out = params.MinionReports{ 308 MigrationId: "id", 309 Phase: "IMPORT", 310 SuccessCount: 4, 311 UnknownCount: 3, 312 UnknownSample: []string{ 313 names.NewMachineTag("3").String(), 314 names.NewMachineTag("4").String(), 315 names.NewUnitTag("foo/0").String(), 316 }, 317 Failed: []string{ 318 names.NewMachineTag("5").String(), 319 names.NewUnitTag("foo/1").String(), 320 names.NewUnitTag("foo/2").String(), 321 }, 322 } 323 return nil 324 }) 325 client := migrationmaster.NewClient(apiCaller, nil) 326 out, err := client.MinionReports() 327 c.Assert(err, jc.ErrorIsNil) 328 stub.CheckCalls(c, []jujutesting.StubCall{ 329 {"MigrationMaster.MinionReports", []interface{}{"", nil}}, 330 }) 331 c.Assert(out, gc.DeepEquals, migration.MinionReports{ 332 MigrationId: "id", 333 Phase: migration.IMPORT, 334 SuccessCount: 4, 335 UnknownCount: 3, 336 SomeUnknownMachines: []string{"3", "4"}, 337 SomeUnknownUnits: []string{"foo/0"}, 338 FailedMachines: []string{"5"}, 339 FailedUnits: []string{"foo/1", "foo/2"}, 340 }) 341 } 342 343 func (s *ClientSuite) TestMinionReportsFailedCall(c *gc.C) { 344 apiCaller := apitesting.APICallerFunc(func(string, int, string, string, interface{}, interface{}) error { 345 return errors.New("blam") 346 }) 347 client := migrationmaster.NewClient(apiCaller, nil) 348 _, err := client.MinionReports() 349 c.Assert(err, gc.ErrorMatches, "blam") 350 } 351 352 func (s *ClientSuite) TestMinionReportsInvalidPhase(c *gc.C) { 353 apiCaller := apitesting.APICallerFunc(func(_ string, _ int, _ string, _ string, _ interface{}, result interface{}) error { 354 out := result.(*params.MinionReports) 355 *out = params.MinionReports{ 356 Phase: "BLARGH", 357 } 358 return nil 359 }) 360 client := migrationmaster.NewClient(apiCaller, nil) 361 _, err := client.MinionReports() 362 c.Assert(err, gc.ErrorMatches, `invalid phase: "BLARGH"`) 363 } 364 365 func (s *ClientSuite) TestMinionReportsBadUnknownTag(c *gc.C) { 366 apiCaller := apitesting.APICallerFunc(func(_ string, _ int, _ string, _ string, _ interface{}, result interface{}) error { 367 out := result.(*params.MinionReports) 368 *out = params.MinionReports{ 369 Phase: "IMPORT", 370 UnknownSample: []string{"carl"}, 371 } 372 return nil 373 }) 374 client := migrationmaster.NewClient(apiCaller, nil) 375 _, err := client.MinionReports() 376 c.Assert(err, gc.ErrorMatches, `processing unknown agents: "carl" is not a valid tag`) 377 } 378 379 func (s *ClientSuite) TestMinionReportsBadFailedTag(c *gc.C) { 380 apiCaller := apitesting.APICallerFunc(func(_ string, _ int, _ string, _ string, _ interface{}, result interface{}) error { 381 out := result.(*params.MinionReports) 382 *out = params.MinionReports{ 383 Phase: "IMPORT", 384 Failed: []string{"dave"}, 385 } 386 return nil 387 }) 388 client := migrationmaster.NewClient(apiCaller, nil) 389 _, err := client.MinionReports() 390 c.Assert(err, gc.ErrorMatches, `processing failed agents: "dave" is not a valid tag`) 391 }