github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/worker/remoterelations/mock_test.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package remoterelations_test 5 6 import ( 7 "sync" 8 9 "github.com/juju/errors" 10 "github.com/juju/names/v5" 11 "github.com/juju/testing" 12 "gopkg.in/macaroon.v2" 13 "gopkg.in/tomb.v2" 14 15 "github.com/juju/juju/api" 16 apitesting "github.com/juju/juju/api/testing" 17 apiwatcher "github.com/juju/juju/api/watcher" 18 apiservererrors "github.com/juju/juju/apiserver/errors" 19 "github.com/juju/juju/core/crossmodel" 20 "github.com/juju/juju/core/life" 21 "github.com/juju/juju/core/status" 22 "github.com/juju/juju/core/watcher" 23 "github.com/juju/juju/rpc/params" 24 ) 25 26 type mockRelationsFacade struct { 27 mu sync.Mutex 28 stub *testing.Stub 29 remoteApplicationsWatcher *mockStringsWatcher 30 remoteApplicationRelationsWatchers map[string]*mockStringsWatcher 31 remoteApplications map[string]*mockRemoteApplication 32 relations map[string]*mockRelation 33 relationsEndpoints map[string]*relationEndpointInfo 34 remoteRelationWatchers map[string]*mockRemoteRelationWatcher 35 controllerInfo map[string]*api.Info 36 } 37 38 func newMockRelationsFacade(stub *testing.Stub) *mockRelationsFacade { 39 return &mockRelationsFacade{ 40 stub: stub, 41 remoteApplications: make(map[string]*mockRemoteApplication), 42 relations: make(map[string]*mockRelation), 43 relationsEndpoints: make(map[string]*relationEndpointInfo), 44 remoteApplicationsWatcher: newMockStringsWatcher(), 45 remoteApplicationRelationsWatchers: make(map[string]*mockStringsWatcher), 46 remoteRelationWatchers: make(map[string]*mockRemoteRelationWatcher), 47 controllerInfo: make(map[string]*api.Info), 48 } 49 } 50 51 func (m *mockRelationsFacade) WatchRemoteApplications() (watcher.StringsWatcher, error) { 52 m.mu.Lock() 53 defer m.mu.Unlock() 54 m.stub.MethodCall(m, "WatchRemoteApplications") 55 if err := m.stub.NextErr(); err != nil { 56 return nil, err 57 } 58 return m.remoteApplicationsWatcher, nil 59 } 60 61 func (m *mockRelationsFacade) remoteApplicationRelationsWatcher(name string) (*mockStringsWatcher, bool) { 62 m.mu.Lock() 63 defer m.mu.Unlock() 64 w, ok := m.remoteApplicationRelationsWatchers[name] 65 return w, ok 66 } 67 68 func (m *mockRelationsFacade) removeApplication(name string) (*mockStringsWatcher, bool) { 69 m.mu.Lock() 70 defer m.mu.Unlock() 71 w, ok := m.remoteApplicationRelationsWatchers[name] 72 delete(m.remoteApplications, name) 73 return w, ok 74 } 75 76 func (m *mockRelationsFacade) removeRelation(key string) (*mockRemoteRelationWatcher, bool) { 77 m.mu.Lock() 78 defer m.mu.Unlock() 79 w, ok := m.remoteRelationWatchers[key] 80 delete(m.relations, key) 81 return w, ok 82 } 83 84 func (m *mockRelationsFacade) updateRelationLife(key string, life life.Value) (*mockRemoteRelationWatcher, bool) { 85 m.mu.Lock() 86 defer m.mu.Unlock() 87 w, ok := m.remoteRelationWatchers[key] 88 m.relations[key].life = life 89 return w, ok 90 } 91 92 func (m *mockRelationsFacade) WatchRemoteApplicationRelations(application string) (watcher.StringsWatcher, error) { 93 m.mu.Lock() 94 defer m.mu.Unlock() 95 m.stub.MethodCall(m, "WatchRemoteApplicationRelations", application) 96 if err := m.stub.NextErr(); err != nil { 97 return nil, err 98 } 99 m.remoteApplicationRelationsWatchers[application] = newMockStringsWatcher() 100 return m.remoteApplicationRelationsWatchers[application], nil 101 } 102 103 func (m *mockRelationsFacade) ExportEntities(entities []names.Tag) ([]params.TokenResult, error) { 104 m.stub.MethodCall(m, "ExportEntities", entities) 105 if err := m.stub.NextErr(); err != nil { 106 return nil, err 107 } 108 result := make([]params.TokenResult, len(entities)) 109 for i, e := range entities { 110 result[i] = params.TokenResult{ 111 Token: "token-" + e.Id(), 112 } 113 } 114 return result, nil 115 } 116 117 func (m *mockRelationsFacade) ImportRemoteEntity(entity names.Tag, token string) error { 118 m.stub.MethodCall(m, "ImportRemoteEntity", entity, token) 119 return m.stub.NextErr() 120 } 121 122 func (m *mockRelationsFacade) SaveMacaroon(entity names.Tag, mac *macaroon.Macaroon) error { 123 m.stub.MethodCall(m, "SaveMacaroon", entity, mac) 124 return m.stub.NextErr() 125 } 126 127 func (m *mockRelationsFacade) GetToken(entity names.Tag) (string, error) { 128 m.stub.MethodCall(m, "GetToken", entity) 129 if err := m.stub.NextErr(); err != nil { 130 return "", err 131 } 132 return "token-" + entity.Id(), nil 133 } 134 135 func (m *mockRelationsFacade) RemoteApplications(names []string) ([]params.RemoteApplicationResult, error) { 136 m.mu.Lock() 137 defer m.mu.Unlock() 138 m.stub.MethodCall(m, "RemoteApplications", names) 139 if err := m.stub.NextErr(); err != nil { 140 return nil, err 141 } 142 mac, err := apitesting.NewMacaroon("test") 143 if err != nil { 144 return nil, err 145 } 146 result := make([]params.RemoteApplicationResult, len(names)) 147 for i, name := range names { 148 if app, ok := m.remoteApplications[name]; ok { 149 result[i] = params.RemoteApplicationResult{ 150 Result: ¶ms.RemoteApplication{ 151 Name: app.name, 152 OfferUUID: app.offeruuid, 153 Life: app.life, 154 ModelUUID: app.modelUUID, 155 IsConsumerProxy: app.registered, 156 Status: string(app.status), 157 ConsumeVersion: app.consumeVersion, 158 Macaroon: mac, 159 }, 160 } 161 } else { 162 result[i] = params.RemoteApplicationResult{ 163 Error: apiservererrors.ServerError(errors.NotFoundf(name))} 164 } 165 } 166 return result, nil 167 } 168 169 func (m *mockRelationsFacade) ConsumeRemoteSecretChanges(changes []watcher.SecretRevisionChange) error { 170 m.mu.Lock() 171 defer m.mu.Unlock() 172 m.stub.MethodCall(m, "ConsumeRemoteSecretChanges", changes) 173 return nil 174 } 175 176 type relationEndpointInfo struct { 177 localApplicationName string 178 localEndpoint params.RemoteEndpoint 179 remoteEndpointName string 180 } 181 182 func (m *mockRelationsFacade) Relations(keys []string) ([]params.RemoteRelationResult, error) { 183 m.mu.Lock() 184 defer m.mu.Unlock() 185 m.stub.MethodCall(m, "Relations", keys) 186 if err := m.stub.NextErr(); err != nil { 187 return nil, err 188 } 189 result := make([]params.RemoteRelationResult, len(keys)) 190 for i, key := range keys { 191 if rel, ok := m.relations[key]; ok { 192 result[i].Result = ¶ms.RemoteRelation{ 193 Id: rel.id, 194 Life: rel.life, 195 Suspended: rel.Suspended(), 196 Key: keys[i], 197 } 198 if epInfo, ok := m.relationsEndpoints[key]; ok { 199 result[i].Result.RemoteEndpointName = epInfo.remoteEndpointName 200 result[i].Result.Endpoint = epInfo.localEndpoint 201 result[i].Result.ApplicationName = epInfo.localApplicationName 202 } 203 } else { 204 result[i].Error = apiservererrors.ServerError(errors.NotFoundf(key)) 205 } 206 } 207 return result, nil 208 } 209 210 func (m *mockRelationsFacade) remoteRelationWatcher(key string) (*mockRemoteRelationWatcher, bool) { 211 m.mu.Lock() 212 defer m.mu.Unlock() 213 w, ok := m.remoteRelationWatchers[key] 214 return w, ok 215 } 216 217 func (m *mockRelationsFacade) WatchLocalRelationChanges(relationKey string) (apiwatcher.RemoteRelationWatcher, error) { 218 m.mu.Lock() 219 defer m.mu.Unlock() 220 m.stub.MethodCall(m, "WatchLocalRelationChanges", relationKey) 221 if err := m.stub.NextErr(); err != nil { 222 return nil, err 223 } 224 m.remoteRelationWatchers[relationKey] = newMockRemoteRelationWatcher() 225 return m.remoteRelationWatchers[relationKey], nil 226 } 227 228 func (m *mockRelationsFacade) ConsumeRemoteRelationChange(change params.RemoteRelationChangeEvent) error { 229 m.stub.MethodCall(m, "ConsumeRemoteRelationChange", change) 230 if err := m.stub.NextErr(); err != nil { 231 return err 232 } 233 return nil 234 } 235 236 func (m *mockRelationsFacade) ControllerAPIInfoForModel(modelUUID string) (*api.Info, error) { 237 m.stub.MethodCall(m, "ControllerAPIInfoForModel", modelUUID) 238 if err := m.stub.NextErr(); err != nil { 239 return nil, err 240 } 241 return m.controllerInfo[modelUUID], nil 242 } 243 244 func (m *mockRelationsFacade) SetRemoteApplicationStatus(applicationName string, status status.Status, message string) error { 245 m.stub.MethodCall(m, "SetRemoteApplicationStatus", applicationName, status.String(), message) 246 return nil 247 } 248 249 func (m *mockRelationsFacade) UpdateControllerForModel(controller crossmodel.ControllerInfo, modelUUID string) error { 250 m.stub.MethodCall(m, "UpdateControllerForModel", controller, modelUUID) 251 if err := m.stub.NextErr(); err != nil { 252 return err 253 } 254 return nil 255 } 256 257 type mockRemoteRelationsFacade struct { 258 mu sync.Mutex 259 stub *testing.Stub 260 remoteRelationWatchers map[string]*mockRemoteRelationWatcher 261 relationsStatusWatchers map[string]*mockRelationStatusWatcher 262 offersStatusWatchers map[string]*mockOfferStatusWatcher 263 secretsRevisionWatchers map[string]*mockSecretsRevisionWatcher 264 } 265 266 func newMockRemoteRelationsFacade(stub *testing.Stub) *mockRemoteRelationsFacade { 267 return &mockRemoteRelationsFacade{ 268 stub: stub, 269 remoteRelationWatchers: make(map[string]*mockRemoteRelationWatcher), 270 relationsStatusWatchers: make(map[string]*mockRelationStatusWatcher), 271 offersStatusWatchers: make(map[string]*mockOfferStatusWatcher), 272 secretsRevisionWatchers: make(map[string]*mockSecretsRevisionWatcher), 273 } 274 } 275 276 func (m *mockRemoteRelationsFacade) Close() error { 277 m.stub.MethodCall(m, "Close") 278 return nil 279 } 280 281 func (m *mockRemoteRelationsFacade) PublishRelationChange(change params.RemoteRelationChangeEvent) error { 282 m.stub.MethodCall(m, "PublishRelationChange", change) 283 if err := m.stub.NextErr(); err != nil { 284 return err 285 } 286 return nil 287 } 288 289 func (m *mockRemoteRelationsFacade) RegisterRemoteRelations(relations ...params.RegisterRemoteRelationArg) ([]params.RegisterRemoteRelationResult, error) { 290 m.stub.MethodCall(m, "RegisterRemoteRelations", relations) 291 if err := m.stub.NextErr(); err != nil { 292 return nil, err 293 } 294 result := make([]params.RegisterRemoteRelationResult, len(relations)) 295 mac, err := apitesting.NewMacaroon("apimac") 296 if err != nil { 297 return nil, err 298 } 299 for i, rel := range relations { 300 result[i].Result = ¶ms.RemoteRelationDetails{ 301 Token: "token-" + rel.OfferUUID, 302 Macaroon: mac, 303 } 304 } 305 return result, nil 306 } 307 308 func (m *mockRemoteRelationsFacade) remoteRelationWatcher(key string) (*mockRemoteRelationWatcher, bool) { 309 m.mu.Lock() 310 defer m.mu.Unlock() 311 w, ok := m.remoteRelationWatchers[key] 312 return w, ok 313 } 314 315 func (m *mockRemoteRelationsFacade) WatchRelationChanges(relationToken string, appToken string, mac macaroon.Slice) (apiwatcher.RemoteRelationWatcher, error) { 316 m.mu.Lock() 317 defer m.mu.Unlock() 318 m.stub.MethodCall(m, "WatchRelationChanges", relationToken, appToken, mac) 319 if err := m.stub.NextErr(); err != nil { 320 return nil, err 321 } 322 m.remoteRelationWatchers[relationToken] = newMockRemoteRelationWatcher() 323 return m.remoteRelationWatchers[relationToken], nil 324 } 325 326 func (m *mockRemoteRelationsFacade) relationsStatusWatcher(key string) (*mockRelationStatusWatcher, bool) { 327 m.mu.Lock() 328 defer m.mu.Unlock() 329 w, ok := m.relationsStatusWatchers[key] 330 return w, ok 331 } 332 333 func (m *mockRemoteRelationsFacade) secretsRevisionWatcher(key string) (*mockSecretsRevisionWatcher, bool) { 334 m.mu.Lock() 335 defer m.mu.Unlock() 336 w, ok := m.secretsRevisionWatchers[key] 337 return w, ok 338 } 339 340 func (m *mockRemoteRelationsFacade) WatchRelationSuspendedStatus(arg params.RemoteEntityArg) (watcher.RelationStatusWatcher, error) { 341 m.mu.Lock() 342 defer m.mu.Unlock() 343 m.stub.MethodCall(m, "WatchRelationSuspendedStatus", arg.Token, arg.Macaroons) 344 if err := m.stub.NextErr(); err != nil { 345 return nil, err 346 } 347 m.relationsStatusWatchers[arg.Token] = newMockRelationStatusWatcher() 348 return m.relationsStatusWatchers[arg.Token], nil 349 } 350 351 func (m *mockRemoteRelationsFacade) WatchOfferStatus(arg params.OfferArg) (watcher.OfferStatusWatcher, error) { 352 m.mu.Lock() 353 defer m.mu.Unlock() 354 m.stub.MethodCall(m, "WatchOfferStatus", arg.OfferUUID, arg.Macaroons) 355 if err := m.stub.NextErr(); err != nil { 356 return nil, err 357 } 358 m.offersStatusWatchers[arg.OfferUUID] = newMockOfferStatusWatcher() 359 return m.offersStatusWatchers[arg.OfferUUID], nil 360 } 361 362 // RelationUnitSettings returns the relation unit settings for the given relation units in the remote model. 363 func (m *mockRemoteRelationsFacade) RelationUnitSettings(relationUnits []params.RemoteRelationUnit) ([]params.SettingsResult, error) { 364 m.mu.Lock() 365 defer m.mu.Unlock() 366 m.stub.MethodCall(m, "RelationUnitSettings", relationUnits) 367 if err := m.stub.NextErr(); err != nil { 368 return nil, err 369 } 370 result := make([]params.SettingsResult, len(relationUnits)) 371 for i := range relationUnits { 372 result[i].Settings = map[string]string{ 373 "foo": "bar", 374 } 375 } 376 return result, nil 377 } 378 379 func (m *mockRemoteRelationsFacade) WatchConsumedSecretsChanges(appToken, relToken string, mac *macaroon.Macaroon) (watcher.SecretsRevisionWatcher, error) { 380 m.mu.Lock() 381 defer m.mu.Unlock() 382 m.stub.MethodCall(m, "WatchConsumedSecretsChanges", appToken, relToken, mac) 383 if err := m.stub.NextErr(); err != nil { 384 return nil, err 385 } 386 m.secretsRevisionWatchers[appToken] = newMockSecretsRevisionWatcher() 387 return m.secretsRevisionWatchers[appToken], nil 388 } 389 390 type mockWatcher struct { 391 testing.Stub 392 tomb.Tomb 393 mu sync.Mutex 394 terminated bool 395 } 396 397 func (w *mockWatcher) killed() bool { 398 w.mu.Lock() 399 defer w.mu.Unlock() 400 return w.terminated 401 } 402 403 func (w *mockWatcher) Kill() { 404 w.MethodCall(w, "Kill") 405 w.Tomb.Kill(nil) 406 w.mu.Lock() 407 defer w.mu.Unlock() 408 w.terminated = true 409 } 410 411 func (w *mockWatcher) Stop() error { 412 w.MethodCall(w, "Stop") 413 if err := w.NextErr(); err != nil { 414 return err 415 } 416 w.Tomb.Kill(nil) 417 return w.Tomb.Wait() 418 } 419 420 type mockStringsWatcher struct { 421 mockWatcher 422 changes chan []string 423 } 424 425 func newMockStringsWatcher() *mockStringsWatcher { 426 w := &mockStringsWatcher{changes: make(chan []string, 5)} 427 w.Tomb.Go(func() error { 428 <-w.Tomb.Dying() 429 return nil 430 }) 431 return w 432 } 433 434 func (w *mockStringsWatcher) Changes() watcher.StringsChannel { 435 w.MethodCall(w, "Changes") 436 return w.changes 437 } 438 439 type mockSecretsRevisionWatcher struct { 440 mockWatcher 441 changes chan []watcher.SecretRevisionChange 442 } 443 444 func newMockSecretsRevisionWatcher() *mockSecretsRevisionWatcher { 445 w := &mockSecretsRevisionWatcher{ 446 changes: make(chan []watcher.SecretRevisionChange, 1), 447 } 448 w.Tomb.Go(func() error { 449 <-w.Tomb.Dying() 450 return nil 451 }) 452 return w 453 } 454 455 func (w *mockSecretsRevisionWatcher) Changes() watcher.SecretRevisionChannel { 456 w.MethodCall(w, "Changes") 457 return w.changes 458 } 459 460 type mockRemoteApplication struct { 461 testing.Stub 462 name string 463 offeruuid string 464 url string 465 life life.Value 466 modelUUID string 467 registered bool 468 status status.Status 469 consumeVersion int 470 } 471 472 type mockRemoteRelationWatcher struct { 473 mockWatcher 474 changes chan params.RemoteRelationChangeEvent 475 } 476 477 func newMockRemoteRelationWatcher() *mockRemoteRelationWatcher { 478 w := &mockRemoteRelationWatcher{ 479 changes: make(chan params.RemoteRelationChangeEvent, 1), 480 } 481 w.Tomb.Go(func() error { 482 <-w.Tomb.Dying() 483 return nil 484 }) 485 return w 486 } 487 488 func (w *mockRemoteRelationWatcher) kill(err error) { 489 w.Tomb.Kill(err) 490 } 491 492 func (w *mockRemoteRelationWatcher) Changes() <-chan params.RemoteRelationChangeEvent { 493 w.MethodCall(w, "Changes") 494 return w.changes 495 } 496 497 type mockRelationStatusWatcher struct { 498 mockWatcher 499 changes chan []watcher.RelationStatusChange 500 } 501 502 func newMockRelationStatusWatcher() *mockRelationStatusWatcher { 503 w := &mockRelationStatusWatcher{ 504 changes: make(chan []watcher.RelationStatusChange, 1), 505 } 506 w.Tomb.Go(func() error { 507 <-w.Tomb.Dying() 508 return nil 509 }) 510 return w 511 } 512 513 func (w *mockRelationStatusWatcher) Changes() watcher.RelationStatusChannel { 514 w.MethodCall(w, "Changes") 515 return w.changes 516 } 517 518 type mockOfferStatusWatcher struct { 519 mockWatcher 520 changes chan []watcher.OfferStatusChange 521 } 522 523 func newMockOfferStatusWatcher() *mockOfferStatusWatcher { 524 w := &mockOfferStatusWatcher{ 525 changes: make(chan []watcher.OfferStatusChange, 1), 526 } 527 w.Tomb.Go(func() error { 528 <-w.Tomb.Dying() 529 return nil 530 }) 531 return w 532 } 533 534 func (w *mockOfferStatusWatcher) Changes() watcher.OfferStatusChannel { 535 w.MethodCall(w, "Changes") 536 return w.changes 537 } 538 539 func newMockRemoteApplication(name, url string) *mockRemoteApplication { 540 return &mockRemoteApplication{ 541 name: name, url: url, life: life.Alive, offeruuid: "offer-" + name + "-uuid", 542 modelUUID: "remote-model-uuid", 543 consumeVersion: 666, 544 } 545 } 546 547 func (r *mockRemoteApplication) Name() string { 548 r.MethodCall(r, "Name") 549 return r.name 550 } 551 552 func (r *mockRemoteApplication) SourceModel() names.ModelTag { 553 r.MethodCall(r, "SourceModel") 554 return names.NewModelTag(r.modelUUID) 555 } 556 557 func (r *mockRemoteApplication) Life() life.Value { 558 r.MethodCall(r, "Life") 559 return r.life 560 } 561 562 type mockRelation struct { 563 testing.Stub 564 sync.Mutex 565 id int 566 life life.Value 567 suspended bool 568 } 569 570 func newMockRelation(id int) *mockRelation { 571 return &mockRelation{ 572 id: id, 573 life: life.Alive, 574 } 575 } 576 577 func (r *mockRelation) Id() int { 578 r.MethodCall(r, "Id") 579 return r.id 580 } 581 582 func (r *mockRelation) Life() life.Value { 583 r.MethodCall(r, "Life") 584 return r.life 585 } 586 587 func (r *mockRelation) Suspended() bool { 588 r.Lock() 589 defer r.Unlock() 590 r.MethodCall(r, "Suspended") 591 return r.suspended 592 } 593 594 func (r *mockRelation) SetSuspended(suspended bool) { 595 r.Lock() 596 defer r.Unlock() 597 r.suspended = suspended 598 }