github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/apiserver/common/firewall/mock_test.go (about)

     1  // Copyright 2017 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package firewall_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/apiserver/common/firewall"
    16  	"github.com/juju/juju/controller"
    17  	"github.com/juju/juju/core/crossmodel"
    18  	"github.com/juju/juju/core/network"
    19  	"github.com/juju/juju/core/watcher"
    20  	"github.com/juju/juju/environs/config"
    21  	"github.com/juju/juju/state"
    22  	coretesting "github.com/juju/juju/testing"
    23  )
    24  
    25  type mockState struct {
    26  	// TODO - implement when remaining firewaller tests become unit tests
    27  	state.ModelMachinesWatcher
    28  
    29  	testing.Stub
    30  	modelUUID      string
    31  	remoteEntities map[names.Tag]string
    32  	macaroons      map[names.Tag]*macaroon.Macaroon
    33  	applications   map[string]*mockApplication
    34  	units          map[string]*mockUnit
    35  	machines       map[string]*mockMachine
    36  	relations      map[string]*mockRelation
    37  	controllerInfo map[string]*mockControllerInfo
    38  	subnetsWatcher *mockStringsWatcher
    39  	modelWatcher   *mockNotifyWatcher
    40  	configAttrs    map[string]interface{}
    41  }
    42  
    43  func newMockState(modelUUID string) *mockState {
    44  	return &mockState{
    45  		modelUUID:      modelUUID,
    46  		relations:      make(map[string]*mockRelation),
    47  		applications:   make(map[string]*mockApplication),
    48  		units:          make(map[string]*mockUnit),
    49  		machines:       make(map[string]*mockMachine),
    50  		remoteEntities: make(map[names.Tag]string),
    51  		macaroons:      make(map[names.Tag]*macaroon.Macaroon),
    52  		controllerInfo: make(map[string]*mockControllerInfo),
    53  		subnetsWatcher: newMockStringsWatcher(),
    54  		modelWatcher:   newMockNotifyWatcher(),
    55  		configAttrs:    coretesting.FakeConfig(),
    56  	}
    57  }
    58  
    59  func (st *mockState) WatchForModelConfigChanges() state.NotifyWatcher {
    60  	return st.modelWatcher
    61  }
    62  
    63  func (st *mockState) ModelConfig() (*config.Config, error) {
    64  	return config.New(config.UseDefaults, st.configAttrs)
    65  }
    66  
    67  func (st *mockState) ControllerConfig() (controller.Config, error) {
    68  	return nil, errors.NotImplementedf("ControllerConfig")
    69  }
    70  
    71  func (st *mockState) ControllerInfo(modelUUID string) ([]string, string, error) {
    72  	if info, ok := st.controllerInfo[modelUUID]; !ok {
    73  		return nil, "", errors.NotFoundf("controller info for %v", modelUUID)
    74  	} else {
    75  		return info.ControllerInfo().Addrs, info.ControllerInfo().CACert, nil
    76  	}
    77  }
    78  
    79  func (st *mockState) GetMacaroon(model names.ModelTag, entity names.Tag) (*macaroon.Macaroon, error) {
    80  	st.MethodCall(st, "GetMacaroon", model, entity)
    81  	if err := st.NextErr(); err != nil {
    82  		return nil, err
    83  	}
    84  	mac, ok := st.macaroons[entity]
    85  	if !ok {
    86  		return nil, errors.NotFoundf("macaroon for %v", entity)
    87  	}
    88  	return mac, nil
    89  }
    90  
    91  func (st *mockState) ModelUUID() string {
    92  	return st.modelUUID
    93  }
    94  
    95  func (st *mockState) Application(id string) (firewall.Application, error) {
    96  	st.MethodCall(st, "Application", id)
    97  	if err := st.NextErr(); err != nil {
    98  		return nil, err
    99  	}
   100  	a, ok := st.applications[id]
   101  	if !ok {
   102  		return nil, errors.NotFoundf("application %q", id)
   103  	}
   104  	return a, nil
   105  }
   106  
   107  func (st *mockState) Unit(name string) (firewall.Unit, error) {
   108  	st.MethodCall(st, "Unit", name)
   109  	if err := st.NextErr(); err != nil {
   110  		return nil, err
   111  	}
   112  	u, ok := st.units[name]
   113  	if !ok {
   114  		return nil, errors.NotFoundf("unit %q", name)
   115  	}
   116  	return u, nil
   117  }
   118  
   119  func (st *mockState) Machine(id string) (firewall.Machine, error) {
   120  	st.MethodCall(st, "Machine", id)
   121  	if err := st.NextErr(); err != nil {
   122  		return nil, err
   123  	}
   124  	m, ok := st.machines[id]
   125  	if !ok {
   126  		return nil, errors.NotFoundf("machine %q", id)
   127  	}
   128  	return m, nil
   129  }
   130  
   131  func (st *mockState) WatchSubnets(func(id interface{}) bool) state.StringsWatcher {
   132  	st.MethodCall(st, "WatchSubnets")
   133  	return st.subnetsWatcher
   134  }
   135  
   136  func (st *mockState) WatchOpenedPorts() state.StringsWatcher {
   137  	st.MethodCall(st, "WatchOpenedPorts")
   138  	// TODO - implement when remaining firewaller tests become unit tests
   139  	return nil
   140  }
   141  
   142  func (st *mockState) FindEntity(tag names.Tag) (state.Entity, error) {
   143  	st.MethodCall(st, "FindEntity")
   144  	// TODO - implement when remaining firewaller tests become unit tests
   145  	return nil, errors.NotImplementedf("FindEntity")
   146  }
   147  
   148  func (st *mockState) GetModel(tag names.ModelTag) (*state.Model, error) {
   149  	st.MethodCall(st, "GetModel", tag)
   150  	// TODO - implement when remaining firewaller tests become unit tests
   151  	return nil, errors.NotImplementedf("GetModel")
   152  }
   153  
   154  type mockWatcher struct {
   155  	testing.Stub
   156  	tomb.Tomb
   157  }
   158  
   159  func (w *mockWatcher) Kill() {
   160  	w.MethodCall(w, "Kill")
   161  	w.Tomb.Kill(nil)
   162  }
   163  
   164  func (w *mockWatcher) Stop() error {
   165  	w.MethodCall(w, "Stop")
   166  	if err := w.NextErr(); err != nil {
   167  		return err
   168  	}
   169  	w.Tomb.Kill(nil)
   170  	return w.Tomb.Wait()
   171  }
   172  
   173  func (w *mockWatcher) Err() error {
   174  	w.MethodCall(w, "Err")
   175  	return w.Tomb.Err()
   176  }
   177  
   178  type mockStringsWatcher struct {
   179  	mockWatcher
   180  	changes chan []string
   181  }
   182  
   183  func newMockStringsWatcher() *mockStringsWatcher {
   184  	w := &mockStringsWatcher{changes: make(chan []string, 1)}
   185  	w.Tomb.Go(func() error {
   186  		<-w.Tomb.Dying()
   187  		return nil
   188  	})
   189  	return w
   190  }
   191  
   192  func (w *mockStringsWatcher) Changes() <-chan []string {
   193  	w.MethodCall(w, "Changes")
   194  	return w.changes
   195  }
   196  
   197  func newMockNotifyWatcher() *mockNotifyWatcher {
   198  	w := &mockNotifyWatcher{changes: make(chan struct{}, 1)}
   199  	// Initial event
   200  	w.changes <- struct{}{}
   201  	w.Tomb.Go(func() error {
   202  		<-w.Tomb.Dying()
   203  		return nil
   204  	})
   205  	return w
   206  }
   207  
   208  type mockNotifyWatcher struct {
   209  	mockWatcher
   210  	changes chan struct{}
   211  }
   212  
   213  func (w *mockNotifyWatcher) Changes() <-chan struct{} {
   214  	w.MethodCall(w, "Changes")
   215  	return w.changes
   216  }
   217  
   218  type mockApplication struct {
   219  	testing.Stub
   220  	name  string
   221  	units []*mockUnit
   222  }
   223  
   224  func newMockApplication(name string) *mockApplication {
   225  	return &mockApplication{
   226  		name: name,
   227  	}
   228  }
   229  
   230  func (a *mockApplication) Name() string {
   231  	a.MethodCall(a, "Name")
   232  	return a.name
   233  }
   234  
   235  func (a *mockApplication) AllUnits() (results []firewall.Unit, err error) {
   236  	a.MethodCall(a, "AllUnits")
   237  	for _, unit := range a.units {
   238  		results = append(results, unit)
   239  	}
   240  	return results, a.NextErr()
   241  }
   242  
   243  type mockControllerInfo struct {
   244  	uuid string
   245  	info crossmodel.ControllerInfo
   246  }
   247  
   248  func (c *mockControllerInfo) Id() string {
   249  	return c.uuid
   250  }
   251  
   252  func (c *mockControllerInfo) ControllerInfo() crossmodel.ControllerInfo {
   253  	return c.info
   254  }
   255  
   256  type mockRelation struct {
   257  	testing.Stub
   258  	firewall.Relation
   259  	id        int
   260  	endpoints []state.Endpoint
   261  	ruw       *mockRelationUnitsWatcher
   262  	ew        *mockStringsWatcher
   263  	ruwApp    string
   264  }
   265  
   266  func newMockRelation(id int) *mockRelation {
   267  	return &mockRelation{
   268  		id:  id,
   269  		ruw: newMockRelationUnitsWatcher(),
   270  		ew:  newMockStringsWatcher(),
   271  	}
   272  }
   273  
   274  func (r *mockRelation) Id() int {
   275  	r.MethodCall(r, "Id")
   276  	return r.id
   277  }
   278  
   279  func (r *mockRelation) Endpoints() []state.Endpoint {
   280  	r.MethodCall(r, "Endpoints")
   281  	return r.endpoints
   282  }
   283  
   284  func (r *mockRelation) WatchUnits(applicationName string) (state.RelationUnitsWatcher, error) {
   285  	if r.ruwApp != applicationName {
   286  		return nil, errors.Errorf("unexpected app %v", applicationName)
   287  	}
   288  	return r.ruw, nil
   289  }
   290  
   291  func (r *mockRelation) WatchRelationEgressNetworks() state.StringsWatcher {
   292  	return r.ew
   293  }
   294  
   295  func newMockRelationUnitsWatcher() *mockRelationUnitsWatcher {
   296  	w := &mockRelationUnitsWatcher{changes: make(chan watcher.RelationUnitsChange, 1)}
   297  	w.Tomb.Go(func() error {
   298  		<-w.Tomb.Dying()
   299  		return nil
   300  	})
   301  	return w
   302  }
   303  
   304  type mockRelationUnitsWatcher struct {
   305  	mockWatcher
   306  	changes chan watcher.RelationUnitsChange
   307  }
   308  
   309  func (w *mockRelationUnitsWatcher) Changes() watcher.RelationUnitsChannel {
   310  	return w.changes
   311  }
   312  
   313  func (st *mockState) GetRemoteEntity(sourceModel names.ModelTag, token string) (names.Tag, error) {
   314  	st.MethodCall(st, "GetRemoteEntity", sourceModel, token)
   315  	if err := st.NextErr(); err != nil {
   316  		return nil, err
   317  	}
   318  	for e, t := range st.remoteEntities {
   319  		if t == token {
   320  			return e, nil
   321  		}
   322  	}
   323  	return nil, errors.NotFoundf("token %v", token)
   324  }
   325  
   326  func (st *mockState) KeyRelation(key string) (firewall.Relation, error) {
   327  	st.MethodCall(st, "KeyRelation", key)
   328  	if err := st.NextErr(); err != nil {
   329  		return nil, err
   330  	}
   331  	r, ok := st.relations[key]
   332  	if !ok {
   333  		return nil, errors.NotFoundf("relation %q", key)
   334  	}
   335  	return r, nil
   336  }
   337  
   338  type mockUnit struct {
   339  	testing.Stub
   340  	mu            sync.Mutex
   341  	name          string
   342  	assigned      bool
   343  	publicAddress network.SpaceAddress
   344  	machineId     string
   345  }
   346  
   347  func newMockUnit(name string) *mockUnit {
   348  	return &mockUnit{
   349  		name:     name,
   350  		assigned: true,
   351  	}
   352  }
   353  
   354  func (u *mockUnit) Name() string {
   355  	u.MethodCall(u, "Name")
   356  	return u.name
   357  }
   358  
   359  func (u *mockUnit) PublicAddress() (network.SpaceAddress, error) {
   360  	u.MethodCall(u, "PublicAddress")
   361  	u.mu.Lock()
   362  	defer u.mu.Unlock()
   363  
   364  	if err := u.NextErr(); err != nil {
   365  		return network.SpaceAddress{}, err
   366  	}
   367  	if !u.assigned {
   368  		return network.SpaceAddress{}, errors.NotAssignedf(u.name)
   369  	}
   370  	if u.publicAddress.Value == "" {
   371  		return network.SpaceAddress{}, network.NoAddressError("public")
   372  	}
   373  	return u.publicAddress, nil
   374  }
   375  
   376  func (u *mockUnit) AssignedMachineId() (string, error) {
   377  	u.MethodCall(u, "AssignedMachineId")
   378  	if err := u.NextErr(); err != nil {
   379  		return "", err
   380  	}
   381  	if !u.assigned {
   382  		return "", errors.NotAssignedf(u.name)
   383  	}
   384  	return u.machineId, nil
   385  }
   386  
   387  func (u *mockUnit) updateAddress(value string) {
   388  	u.mu.Lock()
   389  	defer u.mu.Unlock()
   390  
   391  	u.publicAddress = network.NewSpaceAddress(value)
   392  }
   393  
   394  type mockMachine struct {
   395  	firewall.Machine
   396  
   397  	testing.Stub
   398  	id      string
   399  	watcher *mockAddressWatcher
   400  }
   401  
   402  func newMockMachine(id string) *mockMachine {
   403  	return &mockMachine{
   404  		id:      id,
   405  		watcher: newMockAddressWatcher(),
   406  	}
   407  }
   408  
   409  func (m *mockMachine) Id() string {
   410  	m.MethodCall(m, "Id")
   411  	return m.id
   412  }
   413  
   414  func (m *mockMachine) WatchAddresses() state.NotifyWatcher {
   415  	m.MethodCall(m, "WatchAddresses")
   416  	return m.watcher
   417  }
   418  
   419  type mockAddressWatcher struct {
   420  	mockWatcher
   421  	changes chan struct{}
   422  }
   423  
   424  func newMockAddressWatcher() *mockAddressWatcher {
   425  	w := &mockAddressWatcher{changes: make(chan struct{}, 1)}
   426  	w.Tomb.Go(func() error {
   427  		<-w.Tomb.Dying()
   428  		return nil
   429  	})
   430  	return w
   431  }
   432  
   433  func (w *mockAddressWatcher) Changes() <-chan struct{} {
   434  	w.MethodCall(w, "Changes")
   435  	return w.changes
   436  }