github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/network/containerizer/shim.go (about) 1 // Copyright 2018 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package containerizer 5 6 import ( 7 "github.com/juju/collections/set" 8 "github.com/juju/errors" 9 jujucharm "gopkg.in/juju/charm.v6" 10 11 "github.com/juju/juju/core/constraints" 12 "github.com/juju/juju/core/instance" 13 "github.com/juju/juju/state" 14 ) 15 16 // LinkLayerDevice is an indirection for state.LinkLayerDevice. 17 // It facilitates testing the provisioner's use of this package. 18 type LinkLayerDevice interface { 19 Name() string 20 Type() state.LinkLayerDeviceType 21 MACAddress() string 22 ParentName() string 23 ParentDevice() (LinkLayerDevice, error) 24 EthernetDeviceForBridge(name string) (state.LinkLayerDeviceArgs, error) 25 Addresses() ([]*state.Address, error) 26 27 // These are recruited in tests. See comment on Machine below. 28 MTU() uint 29 IsUp() bool 30 IsAutoStart() bool 31 } 32 33 // linkLayerDevice implements LinkLayerDevice. 34 // We need our own implementation of the indirection above in order to mock the 35 // return of ParentDevice, which in the state package returns a reference to a 36 // raw state.LinkLayerDevice. 37 type linkLayerDevice struct { 38 *state.LinkLayerDevice 39 } 40 41 // ParentDevice implements LinkLayerDevice by wrapping the response from the 42 // inner device's call in a new instance of linkLayerDevice. 43 func (l *linkLayerDevice) ParentDevice() (LinkLayerDevice, error) { 44 dev, err := l.LinkLayerDevice.ParentDevice() 45 if err != nil { 46 return nil, errors.Trace(err) 47 } 48 return &linkLayerDevice{dev}, nil 49 } 50 51 var _ LinkLayerDevice = (*linkLayerDevice)(nil) 52 53 // Machine is an indirection for state.Machine, 54 // describing a machine that is to host containers. 55 type Machine interface { 56 Id() string 57 AllSpaces() (set.Strings, error) 58 LinkLayerDevicesForSpaces([]string) (map[string][]LinkLayerDevice, error) 59 SetLinkLayerDevices(devicesArgs ...state.LinkLayerDeviceArgs) (err error) 60 AllLinkLayerDevices() ([]LinkLayerDevice, error) 61 62 // TODO (manadart 2018-10-10) These methods are used in tests, which rely 63 // on the StateSuite. Some of them are recruited via the Container 64 // interface below, but they are all located here for simplicity. 65 // A better approach could be sought that does not require their 66 // presence here. 67 SetDevicesAddresses(devicesAddresses ...state.LinkLayerDeviceAddress) (err error) 68 SetParentLinkLayerDevicesBeforeTheirChildren(devicesArgs []state.LinkLayerDeviceArgs) error 69 SetConstraints(cons constraints.Value) (err error) 70 RemoveAllAddresses() error 71 Raw() *state.Machine 72 } 73 74 // MachineShim implements Machine. 75 // It is required to mock the return of LinkLayerDevicesForSpaces, 76 // which includes raw state.LinkLayerDevice references. 77 type MachineShim struct { 78 *state.Machine 79 } 80 81 // LinkLayerDevicesForSpaces implements Machine by unwrapping the inner 82 // state.Machine call and wrapping the raw state.LinkLayerDevice references 83 // with the local LinkLayerDevice implementation. 84 func (m *MachineShim) LinkLayerDevicesForSpaces(spaces []string) (map[string][]LinkLayerDevice, error) { 85 spaceDevs, err := m.Machine.LinkLayerDevicesForSpaces(spaces) 86 if err != nil { 87 return nil, errors.Trace(err) 88 } 89 90 wrapped := make(map[string][]LinkLayerDevice, len(spaceDevs)) 91 for space, devs := range spaceDevs { 92 wrappedDevs := make([]LinkLayerDevice, len(devs)) 93 for i, d := range devs { 94 wrappedDevs[i] = &linkLayerDevice{d} 95 } 96 wrapped[space] = wrappedDevs 97 } 98 return wrapped, nil 99 } 100 101 // AllLinkLayerDevices implements Machine by wrapping each 102 // state.LinkLayerDevice reference in returned collection with the local 103 // LinkLayerDevice implementation. 104 func (m *MachineShim) AllLinkLayerDevices() ([]LinkLayerDevice, error) { 105 devs, err := m.Machine.AllLinkLayerDevices() 106 if err != nil { 107 return nil, errors.Trace(err) 108 } 109 110 wrapped := make([]LinkLayerDevice, len(devs)) 111 for i, d := range devs { 112 wrapped[i] = &linkLayerDevice{d} 113 } 114 return wrapped, nil 115 } 116 117 // Raw returns the inner state.Machine reference. 118 func (m *MachineShim) Raw() *state.Machine { 119 return m.Machine 120 } 121 122 // Machine is an indirection for state.Machine, 123 // describing a container. 124 type Container interface { 125 Machine 126 ContainerType() instance.ContainerType 127 DesiredSpaces() (set.Strings, error) 128 } 129 130 var _ Container = (*MachineShim)(nil) 131 132 func (m *MachineShim) Units() ([]Unit, error) { 133 units, err := m.Machine.Units() 134 if err != nil { 135 return nil, errors.Trace(err) 136 } 137 wrapped := make([]Unit, len(units)) 138 for i, u := range units { 139 wrapped[i] = &unitShim{u} 140 } 141 return wrapped, nil 142 } 143 144 // Unit, Application & Charm are used to facilitate mocks 145 // for testing in apiserver/.../agent/provisioner. This is a 146 // by product of bad design. 147 148 // unitShim implements Unit. 149 // It is required to mock the return of Units from MachineShim. 150 type unitShim struct { 151 *state.Unit 152 } 153 154 var _ Unit = (*unitShim)(nil) 155 156 type Unit interface { 157 Application() (Application, error) 158 Name() string 159 } 160 161 func (u *unitShim) Application() (Application, error) { 162 app, err := u.Unit.Application() 163 if err != nil { 164 return nil, errors.Trace(err) 165 } 166 return &applicationShim{app}, nil 167 } 168 169 // applicationShim implements Application. 170 // It is required to mock the return an Application from unitShim. 171 type applicationShim struct { 172 *state.Application 173 } 174 175 var _ Application = (*applicationShim)(nil) 176 177 type Application interface { 178 Charm() (Charm, bool, error) 179 Name() string 180 } 181 182 func (a *applicationShim) Charm() (Charm, bool, error) { 183 return a.Application.Charm() 184 } 185 186 type Charm interface { 187 LXDProfile() *jujucharm.LXDProfile 188 Revision() int 189 }