github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/facades/controller/firewaller/mock_test.go (about) 1 // Copyright 2017 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package firewaller_test 5 6 import ( 7 "sync" 8 9 "github.com/juju/collections/set" 10 "github.com/juju/errors" 11 "github.com/juju/testing" 12 "gopkg.in/juju/names.v2" 13 "gopkg.in/macaroon.v2-unstable" 14 "gopkg.in/tomb.v2" 15 16 "github.com/juju/juju/apiserver/common/cloudspec" 17 "github.com/juju/juju/apiserver/common/firewall" 18 "github.com/juju/juju/apiserver/params" 19 "github.com/juju/juju/controller" 20 "github.com/juju/juju/core/crossmodel" 21 "github.com/juju/juju/core/status" 22 "github.com/juju/juju/environs/config" 23 "github.com/juju/juju/network" 24 "github.com/juju/juju/state" 25 coretesting "github.com/juju/juju/testing" 26 ) 27 28 type mockCloudSpecAPI struct { 29 // TODO - implement when remaining firewaller tests become unit tests 30 cloudspec.CloudSpecAPI 31 } 32 33 type mockState struct { 34 firewall.State 35 36 testing.Stub 37 modelUUID string 38 remoteEntities map[names.Tag]string 39 macaroons map[names.Tag]*macaroon.Macaroon 40 relations map[string]*mockRelation 41 controllerInfo map[string]*mockControllerInfo 42 firewallRules map[state.WellKnownServiceType]*state.FirewallRule 43 subnetsWatcher *mockStringsWatcher 44 modelWatcher *mockNotifyWatcher 45 configAttrs map[string]interface{} 46 } 47 48 func newMockState(modelUUID string) *mockState { 49 return &mockState{ 50 modelUUID: modelUUID, 51 relations: make(map[string]*mockRelation), 52 remoteEntities: make(map[names.Tag]string), 53 macaroons: make(map[names.Tag]*macaroon.Macaroon), 54 controllerInfo: make(map[string]*mockControllerInfo), 55 firewallRules: make(map[state.WellKnownServiceType]*state.FirewallRule), 56 subnetsWatcher: newMockStringsWatcher(), 57 modelWatcher: newMockNotifyWatcher(), 58 configAttrs: coretesting.FakeConfig(), 59 } 60 } 61 62 func (st *mockState) WatchForModelConfigChanges() state.NotifyWatcher { 63 return st.modelWatcher 64 } 65 66 func (st *mockState) ModelConfig() (*config.Config, error) { 67 return config.New(config.UseDefaults, st.configAttrs) 68 } 69 70 func (st *mockState) ControllerConfig() (controller.Config, error) { 71 return nil, errors.NotImplementedf("ControllerConfig") 72 } 73 74 func (st *mockState) ControllerInfo(modelUUID string) ([]string, string, error) { 75 if info, ok := st.controllerInfo[modelUUID]; !ok { 76 return nil, "", errors.NotFoundf("controller info for %v", modelUUID) 77 } else { 78 return info.ControllerInfo().Addrs, info.ControllerInfo().CACert, nil 79 } 80 } 81 82 func (st *mockState) GetMacaroon(entity names.Tag) (*macaroon.Macaroon, error) { 83 st.MethodCall(st, "GetMacaroon", entity) 84 if err := st.NextErr(); err != nil { 85 return nil, err 86 } 87 mac, ok := st.macaroons[entity] 88 if !ok { 89 return nil, errors.NotFoundf("macaroon for %v", entity) 90 } 91 return mac, nil 92 } 93 94 func (st *mockState) ModelUUID() string { 95 return st.modelUUID 96 } 97 98 func (st *mockState) WatchSubnets(func(id interface{}) bool) state.StringsWatcher { 99 st.MethodCall(st, "WatchSubnets") 100 return st.subnetsWatcher 101 } 102 103 func (st *mockState) WatchOpenedPorts() state.StringsWatcher { 104 st.MethodCall(st, "WatchOpenedPorts") 105 // TODO - implement when remaining firewaller tests become unit tests 106 return nil 107 } 108 109 func (st *mockState) FindEntity(tag names.Tag) (state.Entity, error) { 110 st.MethodCall(st, "FindEntity") 111 // TODO - implement when remaining firewaller tests become unit tests 112 return nil, errors.NotImplementedf("FindEntity") 113 } 114 115 func (st *mockState) FirewallRule(service state.WellKnownServiceType) (*state.FirewallRule, error) { 116 r, ok := st.firewallRules[service] 117 if !ok { 118 return nil, errors.NotFoundf("firewall rule for %q", service) 119 } 120 return r, nil 121 } 122 123 type mockWatcher struct { 124 testing.Stub 125 tomb.Tomb 126 } 127 128 func (w *mockWatcher) Kill() { 129 w.MethodCall(w, "Kill") 130 w.Tomb.Kill(nil) 131 } 132 133 func (w *mockWatcher) Stop() error { 134 w.MethodCall(w, "Stop") 135 if err := w.NextErr(); err != nil { 136 return err 137 } 138 w.Tomb.Kill(nil) 139 return w.Tomb.Wait() 140 } 141 142 func (w *mockWatcher) Err() error { 143 w.MethodCall(w, "Err") 144 return w.Tomb.Err() 145 } 146 147 type mockStringsWatcher struct { 148 mockWatcher 149 changes chan []string 150 } 151 152 func newMockStringsWatcher() *mockStringsWatcher { 153 w := &mockStringsWatcher{changes: make(chan []string, 1)} 154 w.Tomb.Go(func() error { 155 <-w.Tomb.Dying() 156 return nil 157 }) 158 return w 159 } 160 161 func (w *mockStringsWatcher) Changes() <-chan []string { 162 w.MethodCall(w, "Changes") 163 return w.changes 164 } 165 166 func newMockNotifyWatcher() *mockNotifyWatcher { 167 w := &mockNotifyWatcher{changes: make(chan struct{}, 1)} 168 // Initial event 169 w.changes <- struct{}{} 170 w.Tomb.Go(func() error { 171 <-w.Tomb.Dying() 172 return nil 173 }) 174 return w 175 } 176 177 type mockNotifyWatcher struct { 178 mockWatcher 179 changes chan struct{} 180 } 181 182 func (w *mockNotifyWatcher) Changes() <-chan struct{} { 183 w.MethodCall(w, "Changes") 184 return w.changes 185 } 186 187 type mockApplication struct { 188 testing.Stub 189 name string 190 units []*mockUnit 191 } 192 193 func newMockApplication(name string) *mockApplication { 194 return &mockApplication{ 195 name: name, 196 } 197 } 198 199 type mockControllerInfo struct { 200 uuid string 201 info crossmodel.ControllerInfo 202 } 203 204 func (c *mockControllerInfo) Id() string { 205 return c.uuid 206 } 207 208 func (c *mockControllerInfo) ControllerInfo() crossmodel.ControllerInfo { 209 return c.info 210 } 211 212 type mockRelation struct { 213 testing.Stub 214 firewall.Relation 215 id int 216 key string 217 endpoints []state.Endpoint 218 ruw *mockRelationUnitsWatcher 219 ruwApp string 220 inScope set.Strings 221 status status.StatusInfo 222 } 223 224 func newMockRelation(id int) *mockRelation { 225 return &mockRelation{ 226 id: id, 227 ruw: newMockRelationUnitsWatcher(), 228 inScope: make(set.Strings), 229 } 230 } 231 232 func (r *mockRelation) Id() int { 233 r.MethodCall(r, "Id") 234 return r.id 235 } 236 237 func (r *mockRelation) WatchRelationIngressNetworks() state.StringsWatcher { 238 w := newMockStringsWatcher() 239 w.changes <- []string{"1.2.3.4/32"} 240 return w 241 } 242 243 func (r *mockRelation) SetStatus(info status.StatusInfo) error { 244 r.status = info 245 return nil 246 } 247 248 func newMockRelationUnitsWatcher() *mockRelationUnitsWatcher { 249 w := &mockRelationUnitsWatcher{changes: make(chan params.RelationUnitsChange, 1)} 250 w.Tomb.Go(func() error { 251 <-w.Tomb.Dying() 252 return nil 253 }) 254 return w 255 } 256 257 type mockRelationUnitsWatcher struct { 258 mockWatcher 259 changes chan params.RelationUnitsChange 260 } 261 262 func (w *mockRelationUnitsWatcher) Changes() <-chan params.RelationUnitsChange { 263 return w.changes 264 } 265 266 func (st *mockState) GetRemoteEntity(sourceModel names.ModelTag, token string) (names.Tag, error) { 267 st.MethodCall(st, "GetRemoteEntity", sourceModel, token) 268 if err := st.NextErr(); err != nil { 269 return nil, err 270 } 271 for e, t := range st.remoteEntities { 272 if t == token { 273 return e, nil 274 } 275 } 276 return nil, errors.NotFoundf("token %v", token) 277 } 278 279 func (st *mockState) KeyRelation(key string) (firewall.Relation, error) { 280 st.MethodCall(st, "KeyRelation", key) 281 if err := st.NextErr(); err != nil { 282 return nil, err 283 } 284 r, ok := st.relations[key] 285 if !ok { 286 return nil, errors.NotFoundf("relation %q", key) 287 } 288 return r, nil 289 } 290 291 type mockUnit struct { 292 testing.Stub 293 mu sync.Mutex 294 name string 295 assigned bool 296 publicAddress network.Address 297 machineId string 298 } 299 300 func newMockUnit(name string) *mockUnit { 301 return &mockUnit{ 302 name: name, 303 assigned: true, 304 } 305 } 306 307 func (u *mockUnit) Name() string { 308 u.MethodCall(u, "Name") 309 return u.name 310 } 311 312 func (u *mockUnit) PublicAddress() (network.Address, error) { 313 u.MethodCall(u, "PublicAddress") 314 u.mu.Lock() 315 defer u.mu.Unlock() 316 317 if err := u.NextErr(); err != nil { 318 return network.Address{}, err 319 } 320 if !u.assigned { 321 return network.Address{}, errors.NotAssignedf(u.name) 322 } 323 if u.publicAddress.Value == "" { 324 return network.Address{}, network.NoAddressError("public") 325 } 326 return u.publicAddress, nil 327 } 328 329 func (u *mockUnit) AssignedMachineId() (string, error) { 330 u.MethodCall(u, "AssignedMachineId") 331 if err := u.NextErr(); err != nil { 332 return "", err 333 } 334 if !u.assigned { 335 return "", errors.NotAssignedf(u.name) 336 } 337 return u.machineId, nil 338 } 339 340 func (u *mockUnit) updateAddress(value string) { 341 u.mu.Lock() 342 defer u.mu.Unlock() 343 344 u.publicAddress = network.Address{Value: value} 345 }