github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/facades/client/applicationoffers/mock_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package applicationoffers_test 5 6 import ( 7 "fmt" 8 "time" 9 10 "github.com/juju/errors" 11 jtesting "github.com/juju/testing" 12 "gopkg.in/juju/charm.v6" 13 "gopkg.in/juju/names.v2" 14 "gopkg.in/macaroon-bakery.v2-unstable/bakery/checkers" 15 "gopkg.in/macaroon.v2-unstable" 16 17 "github.com/juju/juju/apiserver/authentication" 18 "github.com/juju/juju/apiserver/common" 19 "github.com/juju/juju/apiserver/common/crossmodel" 20 "github.com/juju/juju/apiserver/facades/client/applicationoffers" 21 jujucrossmodel "github.com/juju/juju/core/crossmodel" 22 "github.com/juju/juju/core/status" 23 "github.com/juju/juju/environs" 24 "github.com/juju/juju/environs/context" 25 "github.com/juju/juju/network" 26 "github.com/juju/juju/permission" 27 "github.com/juju/juju/state" 28 "github.com/juju/juju/testing" 29 ) 30 31 const ( 32 offerCall = "offerCall" 33 offerCallUUID = "offerCallUUID" 34 addOfferCall = "addOffersCall" 35 listOffersCall = "listOffersCall" 36 updateOfferCall = "updateOfferCall" 37 removeOfferCall = "removeOfferCall" 38 ) 39 40 type stubApplicationOffers struct { 41 jtesting.Stub 42 jujucrossmodel.ApplicationOffers 43 44 addOffer func(offer jujucrossmodel.AddApplicationOfferArgs) (*jujucrossmodel.ApplicationOffer, error) 45 listOffers func(filters ...jujucrossmodel.ApplicationOfferFilter) ([]jujucrossmodel.ApplicationOffer, error) 46 } 47 48 func (m *stubApplicationOffers) AddOffer(offer jujucrossmodel.AddApplicationOfferArgs) (*jujucrossmodel.ApplicationOffer, error) { 49 m.AddCall(addOfferCall) 50 return m.addOffer(offer) 51 } 52 53 func (m *stubApplicationOffers) ListOffers(filters ...jujucrossmodel.ApplicationOfferFilter) ([]jujucrossmodel.ApplicationOffer, error) { 54 m.AddCall(listOffersCall) 55 return m.listOffers(filters...) 56 } 57 58 func (m *stubApplicationOffers) UpdateOffer(offer jujucrossmodel.AddApplicationOfferArgs) (*jujucrossmodel.ApplicationOffer, error) { 59 m.AddCall(updateOfferCall) 60 panic("not implemented") 61 } 62 63 func (m *stubApplicationOffers) Remove(url string, force bool) error { 64 m.AddCall(removeOfferCall) 65 panic("not implemented") 66 } 67 68 func (m *stubApplicationOffers) ApplicationOffer(name string) (*jujucrossmodel.ApplicationOffer, error) { 69 m.AddCall(offerCall) 70 panic("not implemented") 71 } 72 73 func (m *stubApplicationOffers) ApplicationOfferForUUID(uuid string) (*jujucrossmodel.ApplicationOffer, error) { 74 m.AddCall(offerCallUUID) 75 panic("not implemented") 76 } 77 78 type mockEnviron struct { 79 environs.NetworkingEnviron 80 81 stub jtesting.Stub 82 spaceInfo *environs.ProviderSpaceInfo 83 } 84 85 func (e *mockEnviron) ProviderSpaceInfo(ctx context.ProviderCallContext, space *network.SpaceInfo) (*environs.ProviderSpaceInfo, error) { 86 e.stub.MethodCall(e, "ProviderSpaceInfo", space) 87 spaceName := environs.DefaultSpaceName 88 if space != nil { 89 spaceName = space.Name 90 } 91 if e.spaceInfo == nil || spaceName != e.spaceInfo.Name { 92 return nil, errors.NotFoundf("space %q", spaceName) 93 } 94 return e.spaceInfo, e.stub.NextErr() 95 } 96 97 type mockModel struct { 98 uuid string 99 name string 100 owner string 101 modelType state.ModelType 102 } 103 104 func (m *mockModel) UUID() string { 105 return m.uuid 106 } 107 108 func (m *mockModel) ModelTag() names.ModelTag { 109 return names.NewModelTag(m.uuid) 110 } 111 112 func (m *mockModel) Type() state.ModelType { 113 return m.modelType 114 } 115 116 func (m *mockModel) Name() string { 117 return m.name 118 } 119 120 func (m *mockModel) Owner() names.UserTag { 121 return names.NewUserTag(m.owner) 122 } 123 124 type mockCharm struct { 125 meta *charm.Meta 126 } 127 128 func (m *mockCharm) Meta() *charm.Meta { 129 return m.meta 130 } 131 132 func (m *mockCharm) StoragePath() string { 133 return "storage-path" 134 } 135 136 type mockApplication struct { 137 crossmodel.Application 138 name string 139 charm *mockCharm 140 curl *charm.URL 141 endpoints []state.Endpoint 142 bindings map[string]string 143 } 144 145 func (m *mockApplication) Name() string { 146 return m.name 147 } 148 149 func (m *mockApplication) Charm() (crossmodel.Charm, bool, error) { 150 return m.charm, true, nil 151 } 152 153 func (m *mockApplication) CharmURL() (curl *charm.URL, force bool) { 154 return m.curl, true 155 } 156 157 func (m *mockApplication) Endpoints() ([]state.Endpoint, error) { 158 return m.endpoints, nil 159 } 160 161 func (m *mockApplication) EndpointBindings() (map[string]string, error) { 162 return m.bindings, nil 163 } 164 165 type mockSpace struct { 166 name string 167 providerId network.Id 168 subnets []applicationoffers.Subnet 169 } 170 171 func (m *mockSpace) Name() string { 172 return m.name 173 } 174 175 func (m *mockSpace) Subnets() ([]applicationoffers.Subnet, error) { 176 return m.subnets, nil 177 } 178 179 func (m *mockSpace) ProviderId() network.Id { 180 return m.providerId 181 } 182 183 type mockSubnet struct { 184 cidr string 185 vlantag int 186 providerId network.Id 187 providerNetworkId network.Id 188 zones []string 189 } 190 191 func (m *mockSubnet) CIDR() string { 192 return m.cidr 193 } 194 195 func (m *mockSubnet) VLANTag() int { 196 return m.vlantag 197 } 198 199 func (m *mockSubnet) ProviderId() network.Id { 200 return m.providerId 201 } 202 203 func (m *mockSubnet) ProviderNetworkId() network.Id { 204 return m.providerNetworkId 205 } 206 207 func (m *mockSubnet) AvailabilityZones() []string { 208 return m.zones 209 } 210 211 type mockRelation struct { 212 crossmodel.Relation 213 id int 214 endpoint state.Endpoint 215 } 216 217 func (m *mockRelation) Status() (status.StatusInfo, error) { 218 return status.StatusInfo{Status: status.Joined}, nil 219 } 220 221 func (m *mockRelation) Endpoint(appName string) (state.Endpoint, error) { 222 if m.endpoint.ApplicationName != appName { 223 return state.Endpoint{}, errors.NotFoundf("endpoint for %q", appName) 224 } 225 return m.endpoint, nil 226 } 227 228 type mockOfferConnection struct { 229 modelUUID string 230 username string 231 relationKey string 232 relationId int 233 } 234 235 func (m *mockOfferConnection) SourceModelUUID() string { 236 return m.modelUUID 237 } 238 239 func (m *mockOfferConnection) UserName() string { 240 return m.username 241 } 242 243 func (m *mockOfferConnection) RelationKey() string { 244 return m.relationKey 245 } 246 247 func (m *mockOfferConnection) RelationId() int { 248 return m.relationId 249 } 250 251 type mockApplicationOffers struct { 252 jujucrossmodel.ApplicationOffers 253 st *mockState 254 } 255 256 func (m *mockApplicationOffers) ListOffers(filters ...jujucrossmodel.ApplicationOfferFilter) ([]jujucrossmodel.ApplicationOffer, error) { 257 var result []jujucrossmodel.ApplicationOffer 258 for _, f := range filters { 259 if offer, ok := m.st.applicationOffers[f.OfferName]; ok { 260 result = append(result, offer) 261 } 262 } 263 return result, nil 264 } 265 266 func (m *mockApplicationOffers) Remove(name string, force bool) error { 267 if len(m.st.connections) > 0 && !force { 268 return errors.Errorf("offer has %d relations", len(m.st.connections)) 269 } 270 _, ok := m.st.applicationOffers[name] 271 if !ok { 272 return errors.NotFoundf("application offer %q", name) 273 } 274 delete(m.st.applicationOffers, name) 275 return nil 276 } 277 278 type offerAccess struct { 279 user names.UserTag 280 offerUUID string 281 } 282 283 type mockState struct { 284 crossmodel.Backend 285 common.AddressAndCertGetter 286 modelUUID string 287 model *mockModel 288 allmodels []applicationoffers.Model 289 users map[string]applicationoffers.User 290 applications map[string]crossmodel.Application 291 applicationOffers map[string]jujucrossmodel.ApplicationOffer 292 spaces map[string]applicationoffers.Space 293 relations map[string]crossmodel.Relation 294 connections []applicationoffers.OfferConnection 295 accessPerms map[offerAccess]permission.Access 296 relationNetworks state.RelationNetworks 297 } 298 299 func (m *mockState) GetAddressAndCertGetter() common.AddressAndCertGetter { 300 return m 301 } 302 303 func (m *mockState) ControllerTag() names.ControllerTag { 304 return testing.ControllerTag 305 } 306 307 func (m *mockState) Charm(*charm.URL) (crossmodel.Charm, error) { 308 return &mockCharm{}, nil 309 } 310 311 func (m *mockState) Application(name string) (crossmodel.Application, error) { 312 app, ok := m.applications[name] 313 if !ok { 314 return nil, errors.NotFoundf("application %q", name) 315 } 316 return app, nil 317 } 318 319 func (m *mockState) ApplicationOffer(name string) (*jujucrossmodel.ApplicationOffer, error) { 320 offer, ok := m.applicationOffers[name] 321 if !ok { 322 return nil, errors.NotFoundf("application offer %q", name) 323 } 324 return &offer, nil 325 } 326 327 func (m *mockState) Space(name string) (applicationoffers.Space, error) { 328 space, ok := m.spaces[name] 329 if !ok { 330 return nil, errors.NotFoundf("space %q", name) 331 } 332 return space, nil 333 } 334 335 func (m *mockState) Model() (applicationoffers.Model, error) { 336 return m.model, nil 337 } 338 339 func (m *mockState) ModelUUID() string { 340 return m.modelUUID 341 } 342 343 func (m *mockState) ModelTag() names.ModelTag { 344 return names.NewModelTag(m.modelUUID) 345 } 346 347 func (m *mockState) AllModelUUIDs() ([]string, error) { 348 if len(m.allmodels) == 0 { 349 return []string{m.model.UUID()}, nil 350 } 351 352 var out []string 353 for _, model := range m.allmodels { 354 out = append(out, model.UUID()) 355 } 356 return out, nil 357 } 358 359 func (m *mockState) KeyRelation(key string) (crossmodel.Relation, error) { 360 rel, ok := m.relations[key] 361 if !ok { 362 return nil, errors.NotFoundf("relation key %v", key) 363 } 364 return rel, nil 365 } 366 367 func (m *mockState) OfferConnections(offerUUID string) ([]applicationoffers.OfferConnection, error) { 368 return m.connections, nil 369 } 370 371 func (m *mockState) User(tag names.UserTag) (applicationoffers.User, error) { 372 user, ok := m.users[tag.Id()] 373 if !ok { 374 return nil, errors.NotFoundf("user %v", tag.Id()) 375 } 376 return user, nil 377 } 378 379 type mockUser struct { 380 name string 381 } 382 383 func (m *mockUser) DisplayName() string { 384 return m.name 385 } 386 387 type mockRelationNetworks struct { 388 state.RelationNetworks 389 } 390 391 func (m *mockRelationNetworks) CIDRS() []string { 392 return []string{"192.168.1.0/32", "10.0.0.0/8"} 393 } 394 395 func (m *mockState) IngressNetworks(relationKey string) (state.RelationNetworks, error) { 396 if m.relationNetworks == nil { 397 return nil, errors.NotFoundf("ingress networks") 398 } 399 return m.relationNetworks, nil 400 } 401 402 func (m *mockState) GetOfferAccess(offerUUID string, user names.UserTag) (permission.Access, error) { 403 access, ok := m.accessPerms[offerAccess{user: user, offerUUID: offerUUID}] 404 if !ok { 405 return "", errors.NotFoundf("offer access for %v", user) 406 } 407 return access, nil 408 } 409 410 func (m *mockState) CreateOfferAccess(offer names.ApplicationOfferTag, user names.UserTag, access permission.Access) error { 411 if _, ok := m.users[user.Name()]; !ok { 412 return errors.NotFoundf("user %q", user.Name()) 413 } 414 if _, ok := m.accessPerms[offerAccess{user: user, offerUUID: offer.Id() + "-uuid"}]; ok { 415 return errors.NewAlreadyExists(nil, fmt.Sprintf("offer user %s", user.Name())) 416 } 417 m.accessPerms[offerAccess{user: user, offerUUID: offer.Id() + "-uuid"}] = access 418 return nil 419 } 420 421 func (m *mockState) UpdateOfferAccess(offer names.ApplicationOfferTag, user names.UserTag, access permission.Access) error { 422 if _, ok := m.users[user.Name()]; !ok { 423 return errors.NotFoundf("user %q", user.Name()) 424 } 425 if _, ok := m.accessPerms[offerAccess{user: user, offerUUID: offer.Id() + "-uuid"}]; !ok { 426 return errors.NewNotFound(nil, fmt.Sprintf("offer user %s", user.Name())) 427 } 428 m.accessPerms[offerAccess{user: user, offerUUID: offer.Id() + "-uuid"}] = access 429 return nil 430 } 431 432 func (m *mockState) RemoveOfferAccess(offer names.ApplicationOfferTag, user names.UserTag) error { 433 if _, ok := m.users[user.Name()]; !ok { 434 return errors.NewNotFound(nil, fmt.Sprintf("offer user %q does not exist", user.Name())) 435 } 436 delete(m.accessPerms, offerAccess{user: user, offerUUID: offer.Id() + "-uuid"}) 437 return nil 438 } 439 440 func (m *mockState) GetOfferUsers(offerUUID string) (map[string]permission.Access, error) { 441 result := make(map[string]permission.Access) 442 for offerAccess, access := range m.accessPerms { 443 if offerAccess.offerUUID != offerUUID { 444 continue 445 } 446 result[offerAccess.user.Id()] = access 447 } 448 return result, nil 449 } 450 451 type mockStatePool struct { 452 st map[string]applicationoffers.Backend 453 } 454 455 func (st *mockStatePool) Get(modelUUID string) (applicationoffers.Backend, func(), error) { 456 backend, ok := st.st[modelUUID] 457 if !ok { 458 return nil, nil, errors.NotFoundf("model for uuid %s", modelUUID) 459 } 460 return backend, func() {}, nil 461 } 462 463 func (st *mockStatePool) GetModel(modelUUID string) (applicationoffers.Model, func(), error) { 464 backend, ok := st.st[modelUUID] 465 if !ok { 466 return nil, nil, errors.NotFoundf("model for uuid %s", modelUUID) 467 } 468 model, err := backend.Model() 469 if err != nil { 470 return nil, nil, err 471 } 472 return model, func() {}, nil 473 } 474 475 type mockCommonStatePool struct { 476 *mockStatePool 477 } 478 479 func (st *mockCommonStatePool) Get(modelUUID string) (crossmodel.Backend, func(), error) { 480 return st.mockStatePool.Get(modelUUID) 481 } 482 483 type mockBakeryService struct { 484 authentication.ExpirableStorageBakeryService 485 jtesting.Stub 486 caveats map[string][]checkers.Caveat 487 } 488 489 func (s *mockBakeryService) NewMacaroon(caveats []checkers.Caveat) (*macaroon.Macaroon, error) { 490 s.MethodCall(s, "NewMacaroon", caveats) 491 s.caveats["id"] = caveats 492 return macaroon.New(nil, []byte("id"), "") 493 } 494 495 func (s *mockBakeryService) ExpireStorageAfter(when time.Duration) (authentication.ExpirableStorageBakeryService, error) { 496 s.MethodCall(s, "ExpireStorageAfter", when) 497 return s, nil 498 } 499 500 func getFakeControllerInfo() ([]string, string, error) { 501 return []string{"192.168.1.1:17070"}, testing.CACert, nil 502 }