github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/worker/uniter/runner/context/ports_test.go (about) 1 // Copyright 2012-2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package context_test 5 6 import ( 7 envtesting "github.com/juju/testing" 8 jc "github.com/juju/testing/checkers" 9 gc "gopkg.in/check.v1" 10 "gopkg.in/juju/names.v2" 11 12 "github.com/juju/juju/apiserver/params" 13 "github.com/juju/juju/network" 14 "github.com/juju/juju/worker/uniter/runner/context" 15 ) 16 17 type PortsSuite struct { 18 envtesting.IsolationSuite 19 } 20 21 var _ = gc.Suite(&PortsSuite{}) 22 23 func (s *PortsSuite) TestValidatePortRange(c *gc.C) { 24 tests := []struct { 25 about string 26 proto string 27 ports []int 28 portRange network.PortRange 29 expectErr string 30 }{{ 31 about: "invalid range - 0-0/tcp", 32 proto: "tcp", 33 ports: []int{0, 0}, 34 expectErr: "invalid port range 0-0/tcp", 35 }, { 36 about: "invalid range - 0-1/tcp", 37 proto: "tcp", 38 ports: []int{0, 1}, 39 expectErr: "invalid port range 0-1/tcp", 40 }, { 41 about: "invalid range - -1-1/tcp", 42 proto: "tcp", 43 ports: []int{-1, 1}, 44 expectErr: "invalid port range -1-1/tcp", 45 }, { 46 about: "invalid range - 1-99999/tcp", 47 proto: "tcp", 48 ports: []int{1, 99999}, 49 expectErr: "invalid port range 1-99999/tcp", 50 }, { 51 about: "invalid range - 88888-99999/tcp", 52 proto: "tcp", 53 ports: []int{88888, 99999}, 54 expectErr: "invalid port range 88888-99999/tcp", 55 }, { 56 about: "invalid protocol - 1-65535/foo", 57 proto: "foo", 58 ports: []int{1, 65535}, 59 expectErr: `invalid protocol "foo", expected "tcp" or "udp"`, 60 }, { 61 about: "valid range - 100-200/udp", 62 proto: "UDP", 63 ports: []int{100, 200}, 64 portRange: network.PortRange{ 65 FromPort: 100, 66 ToPort: 200, 67 Protocol: "udp", 68 }, 69 }, { 70 about: "valid single port - 100/tcp", 71 proto: "TCP", 72 ports: []int{100, 100}, 73 portRange: network.PortRange{ 74 FromPort: 100, 75 ToPort: 100, 76 Protocol: "tcp", 77 }, 78 }} 79 for i, test := range tests { 80 c.Logf("test %d: %s", i, test.about) 81 portRange, err := context.ValidatePortRange( 82 test.proto, 83 test.ports[0], 84 test.ports[1], 85 ) 86 if test.expectErr != "" { 87 c.Check(err, gc.ErrorMatches, test.expectErr) 88 c.Check(portRange, jc.DeepEquals, network.PortRange{}) 89 } else { 90 c.Check(err, jc.ErrorIsNil) 91 c.Check(portRange, jc.DeepEquals, test.portRange) 92 } 93 } 94 } 95 96 func makeMachinePorts( 97 unitName, proto string, fromPort, toPort int, 98 ) map[network.PortRange]params.RelationUnit { 99 result := make(map[network.PortRange]params.RelationUnit) 100 portRange := network.PortRange{ 101 FromPort: fromPort, 102 ToPort: toPort, 103 Protocol: proto, 104 } 105 unitTag := "" 106 if unitName != "invalid" { 107 unitTag = names.NewUnitTag(unitName).String() 108 } else { 109 unitTag = unitName 110 } 111 result[portRange] = params.RelationUnit{ 112 Unit: unitTag, 113 } 114 return result 115 } 116 117 func makePendingPorts( 118 proto string, fromPort, toPort int, shouldOpen bool, 119 ) map[context.PortRange]context.PortRangeInfo { 120 result := make(map[context.PortRange]context.PortRangeInfo) 121 portRange := network.PortRange{ 122 FromPort: fromPort, 123 ToPort: toPort, 124 Protocol: proto, 125 } 126 key := context.PortRange{ 127 Ports: portRange, 128 RelationId: -1, 129 } 130 result[key] = context.PortRangeInfo{ 131 ShouldOpen: shouldOpen, 132 } 133 return result 134 } 135 136 type portsTest struct { 137 about string 138 proto string 139 ports []int 140 machinePorts map[network.PortRange]params.RelationUnit 141 pendingPorts map[context.PortRange]context.PortRangeInfo 142 expectErr string 143 expectPending map[context.PortRange]context.PortRangeInfo 144 } 145 146 func (p portsTest) withDefaults(proto string, fromPort, toPort int) portsTest { 147 if p.proto == "" { 148 p.proto = proto 149 } 150 if len(p.ports) != 2 { 151 p.ports = []int{fromPort, toPort} 152 } 153 if p.pendingPorts == nil { 154 p.pendingPorts = make(map[context.PortRange]context.PortRangeInfo) 155 } 156 return p 157 } 158 159 func (s *PortsSuite) TestTryOpenPorts(c *gc.C) { 160 tests := []portsTest{{ 161 about: "invalid port range", 162 ports: []int{0, 0}, 163 expectErr: "invalid port range 0-0/tcp", 164 }, { 165 about: "invalid protocol - 10-20/foo", 166 proto: "foo", 167 expectErr: `invalid protocol "foo", expected "tcp" or "udp"`, 168 }, { 169 about: "open a new range (no machine ports yet)", 170 expectPending: makePendingPorts("tcp", 10, 20, true), 171 }, { 172 about: "open an existing range (ignored)", 173 machinePorts: makeMachinePorts("u/0", "tcp", 10, 20), 174 expectPending: map[context.PortRange]context.PortRangeInfo{}, 175 }, { 176 about: "open a range pending to be closed already", 177 pendingPorts: makePendingPorts("tcp", 10, 20, false), 178 expectPending: makePendingPorts("tcp", 10, 20, true), 179 }, { 180 about: "open a range pending to be opened already (ignored)", 181 pendingPorts: makePendingPorts("tcp", 10, 20, true), 182 expectPending: makePendingPorts("tcp", 10, 20, true), 183 }, { 184 about: "try opening a range when machine ports has invalid unit tag", 185 machinePorts: makeMachinePorts("invalid", "tcp", 80, 90), 186 expectErr: `machine ports 80-90/tcp contain invalid unit tag: "invalid" is not a valid tag`, 187 }, { 188 about: "try opening a range conflicting with another unit", 189 machinePorts: makeMachinePorts("u/1", "tcp", 10, 20), 190 expectErr: `cannot open 10-20/tcp \(unit "u/0"\): conflicts with existing 10-20/tcp \(unit "u/1"\)`, 191 }, { 192 about: "open a range conflicting with the same unit (ignored)", 193 machinePorts: makeMachinePorts("u/0", "tcp", 10, 20), 194 expectPending: map[context.PortRange]context.PortRangeInfo{}, 195 }, { 196 about: "try opening a range conflicting with another pending range", 197 pendingPorts: makePendingPorts("tcp", 5, 25, true), 198 expectErr: `cannot open 10-20/tcp \(unit "u/0"\): conflicts with 5-25/tcp requested earlier`, 199 }} 200 for i, test := range tests { 201 c.Logf("test %d: %s", i, test.about) 202 203 test = test.withDefaults("tcp", 10, 20) 204 err := context.TryOpenPorts( 205 test.proto, 206 test.ports[0], 207 test.ports[1], 208 names.NewUnitTag("u/0"), 209 test.machinePorts, 210 test.pendingPorts, 211 ) 212 if test.expectErr != "" { 213 c.Check(err, gc.ErrorMatches, test.expectErr) 214 } else { 215 c.Check(err, jc.ErrorIsNil) 216 c.Check(test.pendingPorts, jc.DeepEquals, test.expectPending) 217 } 218 } 219 } 220 221 func (s *PortsSuite) TestTryClosePorts(c *gc.C) { 222 tests := []portsTest{{ 223 about: "invalid port range", 224 ports: []int{0, 0}, 225 expectErr: "invalid port range 0-0/tcp", 226 }, { 227 about: "invalid protocol - 10-20/foo", 228 proto: "foo", 229 expectErr: `invalid protocol "foo", expected "tcp" or "udp"`, 230 }, { 231 about: "close a new range (no machine ports yet; ignored)", 232 expectPending: map[context.PortRange]context.PortRangeInfo{}, 233 }, { 234 about: "close an existing range", 235 machinePorts: makeMachinePorts("u/0", "tcp", 10, 20), 236 expectPending: makePendingPorts("tcp", 10, 20, false), 237 }, { 238 about: "close a range pending to be opened already (removed from pending)", 239 pendingPorts: makePendingPorts("tcp", 10, 20, true), 240 expectPending: map[context.PortRange]context.PortRangeInfo{}, 241 }, { 242 about: "close a range pending to be closed already (ignored)", 243 pendingPorts: makePendingPorts("tcp", 10, 20, false), 244 expectPending: makePendingPorts("tcp", 10, 20, false), 245 }, { 246 about: "try closing an existing range when machine ports has invalid unit tag", 247 machinePorts: makeMachinePorts("invalid", "tcp", 10, 20), 248 expectErr: `machine ports 10-20/tcp contain invalid unit tag: "invalid" is not a valid tag`, 249 }, { 250 about: "try closing a range of another unit", 251 machinePorts: makeMachinePorts("u/1", "tcp", 10, 20), 252 expectErr: `cannot close 10-20/tcp \(opened by "u/1"\) from "u/0"`, 253 }} 254 for i, test := range tests { 255 c.Logf("test %d: %s", i, test.about) 256 257 test = test.withDefaults("tcp", 10, 20) 258 err := context.TryClosePorts( 259 test.proto, 260 test.ports[0], 261 test.ports[1], 262 names.NewUnitTag("u/0"), 263 test.machinePorts, 264 test.pendingPorts, 265 ) 266 if test.expectErr != "" { 267 c.Check(err, gc.ErrorMatches, test.expectErr) 268 } else { 269 c.Check(err, jc.ErrorIsNil) 270 c.Check(test.pendingPorts, jc.DeepEquals, test.expectPending) 271 } 272 } 273 }