github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/facades/controller/crossmodelrelations/mock_test.go (about)

     1  // Copyright 2017 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package crossmodelrelations_test
     5  
     6  import (
     7  	"fmt"
     8  	"sync"
     9  	"time"
    10  
    11  	"github.com/juju/errors"
    12  	"github.com/juju/testing"
    13  	"gopkg.in/juju/names.v2"
    14  	"gopkg.in/macaroon-bakery.v2-unstable/bakery/checkers"
    15  	"gopkg.in/macaroon.v2-unstable"
    16  
    17  	apitesting "github.com/juju/juju/api/testing"
    18  	"github.com/juju/juju/apiserver/authentication"
    19  	"github.com/juju/juju/apiserver/common"
    20  	commoncrossmodel "github.com/juju/juju/apiserver/common/crossmodel"
    21  	"github.com/juju/juju/apiserver/common/firewall"
    22  	"github.com/juju/juju/apiserver/facades/controller/crossmodelrelations"
    23  	"github.com/juju/juju/core/crossmodel"
    24  	"github.com/juju/juju/core/status"
    25  	"github.com/juju/juju/state"
    26  	coretesting "github.com/juju/juju/testing"
    27  )
    28  
    29  type mockStatePool struct {
    30  	st map[string]commoncrossmodel.Backend
    31  }
    32  
    33  func (st *mockStatePool) Get(modelUUID string) (commoncrossmodel.Backend, func(), error) {
    34  	backend, ok := st.st[modelUUID]
    35  	if !ok {
    36  		return nil, nil, errors.NotFoundf("model for uuid %s", modelUUID)
    37  	}
    38  	return backend, func() {}, nil
    39  }
    40  
    41  type mockState struct {
    42  	testing.Stub
    43  	crossmodelrelations.CrossModelRelationsState
    44  	relations             map[string]*mockRelation
    45  	remoteApplications    map[string]*mockRemoteApplication
    46  	applications          map[string]*mockApplication
    47  	offers                map[string]*crossmodel.ApplicationOffer
    48  	offerConnections      map[int]*mockOfferConnection
    49  	offerConnectionsByKey map[string]*mockOfferConnection
    50  	remoteEntities        map[names.Tag]string
    51  	firewallRules         map[state.WellKnownServiceType]*state.FirewallRule
    52  	ingressNetworks       map[string][]string
    53  }
    54  
    55  func newMockState() *mockState {
    56  	return &mockState{
    57  		relations:             make(map[string]*mockRelation),
    58  		remoteApplications:    make(map[string]*mockRemoteApplication),
    59  		applications:          make(map[string]*mockApplication),
    60  		remoteEntities:        make(map[names.Tag]string),
    61  		offers:                make(map[string]*crossmodel.ApplicationOffer),
    62  		offerConnections:      make(map[int]*mockOfferConnection),
    63  		offerConnectionsByKey: make(map[string]*mockOfferConnection),
    64  		firewallRules:         make(map[state.WellKnownServiceType]*state.FirewallRule),
    65  		ingressNetworks:       make(map[string][]string),
    66  	}
    67  }
    68  
    69  func (st *mockState) ApplicationOfferForUUID(offerUUID string) (*crossmodel.ApplicationOffer, error) {
    70  	offer, ok := st.offers[offerUUID]
    71  	if !ok {
    72  		return nil, errors.NotFoundf("offer %v", offerUUID)
    73  	}
    74  	return offer, nil
    75  }
    76  
    77  func (st *mockState) ApplicationOffer(offerName string) (*crossmodel.ApplicationOffer, error) {
    78  	for _, offer := range st.offers {
    79  		if offer.OfferName == offerName {
    80  			return offer, nil
    81  		}
    82  	}
    83  	return nil, errors.NotFoundf("offer %v", offerName)
    84  }
    85  
    86  func (st *mockState) ModelUUID() string {
    87  	return coretesting.ModelTag.Id()
    88  }
    89  
    90  func (st *mockState) Model() (crossmodelrelations.Model, error) {
    91  	return &mockModel{}, nil
    92  }
    93  
    94  func (st *mockState) AddRelation(eps ...state.Endpoint) (commoncrossmodel.Relation, error) {
    95  	rel := &mockRelation{
    96  		id:  len(st.relations),
    97  		key: fmt.Sprintf("%v:%v %v:%v", eps[0].ApplicationName, eps[0].Name, eps[1].ApplicationName, eps[1].Name),
    98  	}
    99  	if _, ok := st.relations[rel.key]; ok {
   100  		return nil, errors.AlreadyExistsf("relation %q", rel.key)
   101  	}
   102  	st.relations[rel.key] = rel
   103  	return rel, nil
   104  }
   105  
   106  func (st *mockState) AddOfferConnection(arg state.AddOfferConnectionParams) (crossmodelrelations.OfferConnection, error) {
   107  	if _, ok := st.offerConnections[arg.RelationId]; ok {
   108  		return nil, errors.AlreadyExistsf("offer connection for relation %d", arg.RelationId)
   109  	}
   110  	oc := &mockOfferConnection{
   111  		sourcemodelUUID: arg.SourceModelUUID,
   112  		relationId:      arg.RelationId,
   113  		relationKey:     arg.RelationKey,
   114  		username:        arg.Username,
   115  		offerUUID:       arg.OfferUUID,
   116  	}
   117  	st.offerConnections[arg.RelationId] = oc
   118  	st.offerConnectionsByKey[arg.RelationKey] = oc
   119  	return oc, nil
   120  }
   121  
   122  func (st *mockState) FirewallRule(service state.WellKnownServiceType) (*state.FirewallRule, error) {
   123  	if r, ok := st.firewallRules[service]; ok {
   124  		return r, nil
   125  	}
   126  	return nil, errors.NotFoundf("firewall rule for %v", service)
   127  }
   128  
   129  func (st *mockState) SaveIngressNetworks(relationKey string, cidrs []string) (state.RelationNetworks, error) {
   130  	st.ingressNetworks[relationKey] = cidrs
   131  	return nil, nil
   132  }
   133  
   134  func (st *mockState) OfferConnectionForRelation(relationKey string) (crossmodelrelations.OfferConnection, error) {
   135  	oc, ok := st.offerConnectionsByKey[relationKey]
   136  	if !ok {
   137  		return nil, errors.NotFoundf("offer connection details for relation %v", relationKey)
   138  	}
   139  	return oc, nil
   140  }
   141  
   142  func (st *mockState) EndpointsRelation(eps ...state.Endpoint) (commoncrossmodel.Relation, error) {
   143  	key := fmt.Sprintf("%v:%v %v:%v", eps[0].ApplicationName, eps[0].Name, eps[1].ApplicationName, eps[1].Name)
   144  	if rel, ok := st.relations[key]; ok {
   145  		return rel, nil
   146  	}
   147  	return nil, errors.NotFoundf("relation with key %q", key)
   148  }
   149  
   150  func (st *mockState) AddRemoteApplication(params state.AddRemoteApplicationParams) (commoncrossmodel.RemoteApplication, error) {
   151  	app := &mockRemoteApplication{
   152  		sourceModelUUID: params.SourceModel.Id(),
   153  		consumerproxy:   params.IsConsumerProxy}
   154  	st.remoteApplications[params.Name] = app
   155  	return app, nil
   156  }
   157  
   158  func (st *mockState) ImportRemoteEntity(entity names.Tag, token string) error {
   159  	st.MethodCall(st, "ImportRemoteEntity", entity, token)
   160  	if err := st.NextErr(); err != nil {
   161  		return err
   162  	}
   163  	if _, ok := st.remoteEntities[entity]; ok {
   164  		return errors.AlreadyExistsf(entity.Id())
   165  	}
   166  	st.remoteEntities[entity] = token
   167  	return nil
   168  }
   169  
   170  func (st *mockState) ExportLocalEntity(entity names.Tag) (string, error) {
   171  	st.MethodCall(st, "ExportLocalEntity", entity)
   172  	if err := st.NextErr(); err != nil {
   173  		return "", err
   174  	}
   175  	if token, ok := st.remoteEntities[entity]; ok {
   176  		return token, errors.AlreadyExistsf(entity.Id())
   177  	}
   178  	token := "token-" + entity.Id()
   179  	st.remoteEntities[entity] = token
   180  	return token, nil
   181  }
   182  
   183  func (st *mockState) GetRemoteEntity(token string) (names.Tag, error) {
   184  	st.MethodCall(st, "GetRemoteEntity", token)
   185  	if err := st.NextErr(); err != nil {
   186  		return nil, err
   187  	}
   188  	for e, t := range st.remoteEntities {
   189  		if t == token {
   190  			return e, nil
   191  		}
   192  	}
   193  	return nil, errors.NotFoundf("token %v", token)
   194  }
   195  
   196  func (st *mockState) GetToken(entity names.Tag) (string, error) {
   197  	st.MethodCall(st, "GetToken", entity)
   198  	if err := st.NextErr(); err != nil {
   199  		return "", err
   200  	}
   201  	for e, t := range st.remoteEntities {
   202  		if e.Id() == entity.Id() {
   203  			return t, nil
   204  		}
   205  	}
   206  	return "", errors.NotFoundf("entity %v", entity)
   207  }
   208  
   209  func (st *mockState) KeyRelation(key string) (commoncrossmodel.Relation, error) {
   210  	st.MethodCall(st, "KeyRelation", key)
   211  	if err := st.NextErr(); err != nil {
   212  		return nil, err
   213  	}
   214  	r, ok := st.relations[key]
   215  	if !ok {
   216  		return nil, errors.NotFoundf("relation %q", key)
   217  	}
   218  	return r, nil
   219  }
   220  
   221  func (st *mockState) RemoteApplication(id string) (commoncrossmodel.RemoteApplication, error) {
   222  	st.MethodCall(st, "RemoteApplication", id)
   223  	if err := st.NextErr(); err != nil {
   224  		return nil, err
   225  	}
   226  	a, ok := st.remoteApplications[id]
   227  	if !ok {
   228  		return nil, errors.NotFoundf("remote application %q", id)
   229  	}
   230  	return a, nil
   231  }
   232  
   233  func (st *mockState) Application(id string) (commoncrossmodel.Application, error) {
   234  	st.MethodCall(st, "Application", id)
   235  	if err := st.NextErr(); err != nil {
   236  		return nil, err
   237  	}
   238  	a, ok := st.applications[id]
   239  	if !ok {
   240  		return nil, errors.NotFoundf("application %q", id)
   241  	}
   242  	return a, nil
   243  }
   244  
   245  type mockFirewallState struct {
   246  	firewall.State
   247  }
   248  
   249  type mockWatcher struct {
   250  	mu      sync.Mutex
   251  	stopped chan struct{}
   252  }
   253  
   254  func (w *mockWatcher) Kill() {
   255  	w.mu.Lock()
   256  	defer w.mu.Unlock()
   257  	if !w.Stopped() {
   258  		close(w.stopped)
   259  	}
   260  }
   261  
   262  func (w *mockWatcher) Stop() error {
   263  	return nil
   264  }
   265  
   266  func (w *mockWatcher) Wait() error {
   267  	<-w.stopped
   268  	return nil
   269  }
   270  
   271  func (w *mockWatcher) Err() error {
   272  	return nil
   273  }
   274  
   275  func (w *mockWatcher) Stopped() bool {
   276  	select {
   277  	case <-w.stopped:
   278  		return true
   279  	default:
   280  		return false
   281  	}
   282  }
   283  
   284  type mockRelationStatusWatcher struct {
   285  	*mockWatcher
   286  	changes chan []string
   287  }
   288  
   289  func (w *mockRelationStatusWatcher) Changes() <-chan []string {
   290  	return w.changes
   291  }
   292  
   293  type mockOfferStatusWatcher struct {
   294  	*mockWatcher
   295  	offerUUID string
   296  	changes   chan struct{}
   297  }
   298  
   299  func (w *mockOfferStatusWatcher) Changes() <-chan struct{} {
   300  	return w.changes
   301  }
   302  
   303  func (w *mockOfferStatusWatcher) OfferUUID() string {
   304  	return w.offerUUID
   305  }
   306  
   307  type mockModel struct {
   308  }
   309  
   310  func (m *mockModel) Name() string {
   311  	return "prod"
   312  }
   313  
   314  func (m *mockModel) Owner() names.UserTag {
   315  	return names.NewUserTag("fred")
   316  }
   317  
   318  type mockRelation struct {
   319  	commoncrossmodel.Relation
   320  	testing.Stub
   321  	id              int
   322  	key             string
   323  	suspended       bool
   324  	suspendedReason string
   325  	status          status.Status
   326  	message         string
   327  	units           map[string]commoncrossmodel.RelationUnit
   328  }
   329  
   330  func newMockRelation(id int) *mockRelation {
   331  	return &mockRelation{
   332  		id:    id,
   333  		units: make(map[string]commoncrossmodel.RelationUnit),
   334  	}
   335  }
   336  
   337  func (r *mockRelation) Id() int {
   338  	r.MethodCall(r, "Id")
   339  	return r.id
   340  }
   341  
   342  func (r *mockRelation) Tag() names.Tag {
   343  	r.MethodCall(r, "Tag")
   344  	return names.NewRelationTag(r.key)
   345  }
   346  
   347  func (r *mockRelation) Destroy() error {
   348  	r.MethodCall(r, "Destroy")
   349  	return r.NextErr()
   350  }
   351  
   352  func (r *mockRelation) Life() state.Life {
   353  	return state.Alive
   354  }
   355  
   356  func (r *mockRelation) SetStatus(statusInfo status.StatusInfo) error {
   357  	r.MethodCall(r, "SetStatus")
   358  	r.status = statusInfo.Status
   359  	r.message = statusInfo.Message
   360  	return nil
   361  }
   362  
   363  func (r *mockRelation) SetSuspended(suspended bool, reason string) error {
   364  	r.MethodCall(r, "SetSuspended")
   365  	r.suspended = suspended
   366  	r.suspendedReason = reason
   367  	return nil
   368  }
   369  
   370  func (r *mockRelation) Suspended() bool {
   371  	r.MethodCall(r, "Suspended")
   372  	return r.suspended
   373  }
   374  
   375  func (r *mockRelation) SuspendedReason() string {
   376  	r.MethodCall(r, "SuspendedReason")
   377  	return r.suspendedReason
   378  }
   379  
   380  func (r *mockRelation) RemoteUnit(unitId string) (commoncrossmodel.RelationUnit, error) {
   381  	r.MethodCall(r, "RemoteUnit", unitId)
   382  	if err := r.NextErr(); err != nil {
   383  		return nil, err
   384  	}
   385  	u, ok := r.units[unitId]
   386  	if !ok {
   387  		return nil, errors.NotFoundf("unit %q", unitId)
   388  	}
   389  	return u, nil
   390  }
   391  
   392  func (r *mockRelation) AllRemoteUnits(appName string) ([]commoncrossmodel.RelationUnit, error) {
   393  	r.MethodCall(r, "AllRemoteUnits", appName)
   394  	if err := r.NextErr(); err != nil {
   395  		return nil, err
   396  	}
   397  	var result []commoncrossmodel.RelationUnit
   398  	for _, ru := range r.units {
   399  		result = append(result, ru)
   400  	}
   401  	return result, nil
   402  }
   403  
   404  func (r *mockRelation) Unit(unitId string) (commoncrossmodel.RelationUnit, error) {
   405  	r.MethodCall(r, "Unit", unitId)
   406  	if err := r.NextErr(); err != nil {
   407  		return nil, err
   408  	}
   409  	u, ok := r.units[unitId]
   410  	if !ok {
   411  		return nil, errors.NotFoundf("unit %q", unitId)
   412  	}
   413  	return u, nil
   414  }
   415  
   416  func (u *mockRelationUnit) Settings() (map[string]interface{}, error) {
   417  	u.MethodCall(u, "Settings")
   418  	return u.settings, u.NextErr()
   419  }
   420  
   421  type mockRemoteApplication struct {
   422  	commoncrossmodel.RemoteApplication
   423  	testing.Stub
   424  	consumerproxy   bool
   425  	sourceModelUUID string
   426  }
   427  
   428  func (r *mockRemoteApplication) IsConsumerProxy() bool {
   429  	r.MethodCall(r, "IsConsumerProxy")
   430  	return r.consumerproxy
   431  }
   432  
   433  func (r *mockRemoteApplication) Destroy() error {
   434  	r.MethodCall(r, "Destroy")
   435  	return r.NextErr()
   436  }
   437  
   438  type mockApplication struct {
   439  	commoncrossmodel.Application
   440  	testing.Stub
   441  	life state.Life
   442  	eps  []state.Endpoint
   443  }
   444  
   445  func (a *mockApplication) Endpoints() ([]state.Endpoint, error) {
   446  	a.MethodCall(a, "Endpoints")
   447  	return a.eps, nil
   448  }
   449  
   450  func (a *mockApplication) Life() state.Life {
   451  	a.MethodCall(a, "Life")
   452  	return a.life
   453  }
   454  
   455  func (a *mockApplication) Status() (status.StatusInfo, error) {
   456  	a.MethodCall(a, "Status")
   457  	return status.StatusInfo{}, nil
   458  }
   459  
   460  type mockOfferConnection struct {
   461  	crossmodelrelations.OfferConnection
   462  	sourcemodelUUID string
   463  	relationId      int
   464  	relationKey     string
   465  	username        string
   466  	offerUUID       string
   467  }
   468  
   469  func (m *mockOfferConnection) OfferUUID() string {
   470  	return m.offerUUID
   471  }
   472  
   473  type mockRelationUnit struct {
   474  	commoncrossmodel.RelationUnit
   475  	testing.Stub
   476  	inScope  bool
   477  	settings map[string]interface{}
   478  }
   479  
   480  func newMockRelationUnit() *mockRelationUnit {
   481  	return &mockRelationUnit{
   482  		settings: make(map[string]interface{}),
   483  	}
   484  }
   485  
   486  func (u *mockRelationUnit) InScope() (bool, error) {
   487  	u.MethodCall(u, "InScope")
   488  	return u.inScope, u.NextErr()
   489  }
   490  
   491  func (u *mockRelationUnit) LeaveScope() error {
   492  	u.MethodCall(u, "LeaveScope")
   493  	if err := u.NextErr(); err != nil {
   494  		return err
   495  	}
   496  	u.inScope = false
   497  	return nil
   498  }
   499  
   500  func (u *mockRelationUnit) EnterScope(settings map[string]interface{}) error {
   501  	u.MethodCall(u, "EnterScope", settings)
   502  	if err := u.NextErr(); err != nil {
   503  		return err
   504  	}
   505  	u.inScope = true
   506  	u.settings = make(map[string]interface{})
   507  	for k, v := range settings {
   508  		u.settings[k] = v
   509  	}
   510  	return nil
   511  }
   512  
   513  func (u *mockRelationUnit) ReplaceSettings(settings map[string]interface{}) error {
   514  	u.MethodCall(u, "ReplaceSettings", settings)
   515  	if err := u.NextErr(); err != nil {
   516  		return err
   517  	}
   518  	u.settings = make(map[string]interface{})
   519  	for k, v := range settings {
   520  		u.settings[k] = v
   521  	}
   522  	return nil
   523  }
   524  
   525  type mockBakeryService struct {
   526  	testing.Stub
   527  	authentication.ExpirableStorageBakeryService
   528  }
   529  
   530  func (s *mockBakeryService) NewMacaroon(caveats []checkers.Caveat) (*macaroon.Macaroon, error) {
   531  	s.MethodCall(s, "NewMacaroon", caveats)
   532  	mac, err := apitesting.NewMacaroon("id")
   533  	if err != nil {
   534  		return nil, err
   535  	}
   536  	for _, cav := range caveats {
   537  		if err := mac.AddFirstPartyCaveat(cav.Condition); err != nil {
   538  			return nil, err
   539  		}
   540  	}
   541  	return mac, nil
   542  }
   543  
   544  func (s *mockBakeryService) CheckAny(ms []macaroon.Slice, assert map[string]string, checker checkers.Checker) (map[string]string, error) {
   545  	if len(ms) != 1 {
   546  		return nil, errors.New("unexpected macaroons")
   547  	}
   548  	if len(ms[0]) == 0 {
   549  		return nil, errors.New("no macaroons")
   550  	}
   551  	declared := checkers.InferDeclared(ms[0])
   552  	for k, v := range assert {
   553  		if declared[k] != v {
   554  			return nil, common.ErrPerm
   555  		}
   556  	}
   557  	return declared, nil
   558  }
   559  
   560  func (s *mockBakeryService) ExpireStorageAfter(when time.Duration) (authentication.ExpirableStorageBakeryService, error) {
   561  	s.MethodCall(s, "ExpireStorageAfter", when)
   562  	return s, nil
   563  }