github.com/geofffranks/garden-linux@v0.0.0-20160715111146-26c893169cfa/integration/networking/net_in_test.go (about) 1 package networking_test 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os/exec" 7 "time" 8 9 "code.cloudfoundry.org/garden" 10 "code.cloudfoundry.org/garden-linux/integration/runner" 11 "github.com/onsi/gomega/gbytes" 12 13 . "github.com/onsi/ginkgo" 14 . "github.com/onsi/gomega" 15 ) 16 17 func restartGarden(argv ...string) *runner.RunningGarden { 18 Expect(client.Ping()).To(Succeed(), "tried to restart garden while it was not running") 19 Expect(client.Stop()).To(Succeed()) 20 return startGarden(argv...) 21 } 22 23 var _ = Describe("Net In", func() { 24 var ( 25 container garden.Container 26 containerPort uint32 27 hostPort uint32 28 externalIP string 29 ) 30 31 const containerHandle = "6e4ea858-6b31-4243-5dcc-093cfb83952d" 32 33 var listenInContainer = func(container garden.Container, containerPort uint32) error { 34 _, err := container.Run(garden.ProcessSpec{ 35 User: "alice", 36 Path: "sh", 37 Args: []string{"-c", fmt.Sprintf("echo %d | nc -l %d", containerPort, containerPort)}, 38 }, garden.ProcessIO{ 39 Stdout: GinkgoWriter, 40 Stderr: GinkgoWriter, 41 }) 42 Expect(err).ToNot(HaveOccurred()) 43 time.Sleep(2 * time.Second) 44 45 return err 46 } 47 48 var sendRequest = func(ip string, port uint32) *gbytes.Buffer { 49 stdout := gbytes.NewBuffer() 50 cmd := exec.Command("nc", "-w1", ip, fmt.Sprintf("%d", port)) 51 cmd.Stdout = stdout 52 cmd.Stderr = GinkgoWriter 53 54 err := cmd.Run() 55 Expect(err).ToNot(HaveOccurred()) 56 57 return stdout 58 } 59 60 BeforeEach(func() { 61 client = startGarden() 62 63 var err error 64 container, err = client.Create(garden.ContainerSpec{ 65 RootFSPath: "/opt/warden/nestable-rootfs", 66 Privileged: true, 67 }) 68 Expect(err).ToNot(HaveOccurred()) 69 70 info, err := container.Info() 71 Expect(err).ToNot(HaveOccurred()) 72 externalIP = info.ExternalIP 73 hostPort = 8888 74 containerPort = 8080 75 }) 76 77 AfterEach(func() { 78 err := client.Destroy(container.Handle()) 79 Expect(err).ToNot(HaveOccurred()) 80 }) 81 82 It("maps the provided host port to the container port", func() { 83 _, _, err := container.NetIn(hostPort, containerPort) 84 Expect(err).ToNot(HaveOccurred()) 85 86 Expect(listenInContainer(container, containerPort)).To(Succeed()) 87 88 stdout := sendRequest(externalIP, hostPort) 89 Expect(stdout).To(gbytes.Say(fmt.Sprintf("%d", containerPort))) 90 }) 91 92 Context("when multiple netin calls map the same host port to distinct container ports", func() { 93 var containerPort2 uint32 94 95 BeforeEach(func() { 96 containerPort2 = uint32(8081) 97 98 _, _, err := container.NetIn(hostPort, containerPort) 99 Expect(err).ToNot(HaveOccurred()) 100 101 _, _, err = container.NetIn(hostPort, containerPort2) 102 Expect(err).ToNot(HaveOccurred()) 103 }) 104 105 // The following behaviour is a bug. See #98463890. 106 It("routes the request to the first container port", func() { 107 Expect(listenInContainer(container, containerPort)).To(Succeed()) 108 Expect(listenInContainer(container, containerPort2)).To(Succeed()) 109 110 stdout := sendRequest(externalIP, hostPort) 111 Expect(stdout).To(gbytes.Say(fmt.Sprintf("%d", containerPort))) 112 }) 113 }) 114 115 Context("when multiple netin calls map distinct host ports to the same container port", func() { 116 var hostPort2 uint32 117 118 BeforeEach(func() { 119 hostPort2 = uint32(8889) 120 121 _, _, err := container.NetIn(hostPort, containerPort) 122 Expect(err).ToNot(HaveOccurred()) 123 124 _, _, err = container.NetIn(hostPort2, containerPort) 125 Expect(err).ToNot(HaveOccurred()) 126 }) 127 128 It("routes request from either host port to the container port", func() { 129 Expect(listenInContainer(container, containerPort)).To(Succeed()) 130 stdout := sendRequest(externalIP, hostPort) 131 Expect(stdout).To(gbytes.Say(fmt.Sprintf("%d", containerPort))) 132 133 Expect(listenInContainer(container, containerPort)).To(Succeed()) 134 stdout = sendRequest(externalIP, hostPort2) 135 Expect(stdout).To(gbytes.Say(fmt.Sprintf("%d", containerPort))) 136 }) 137 }) 138 }) 139 140 var _ = Describe("Port Selection", func() { 141 var ( 142 portPoolSize int 143 extraArgs []string 144 ) 145 146 BeforeEach(func() { 147 portPoolSize = 100 148 extraArgs = []string{} 149 }) 150 151 JustBeforeEach(func() { 152 args := append( 153 []string{"--portPoolSize", fmt.Sprintf("%d", portPoolSize)}, 154 extraArgs..., 155 ) 156 client = startGarden(args...) 157 }) 158 159 It("should not reuse ports of destroyed containers", func() { 160 container, err := client.Create(garden.ContainerSpec{}) 161 Expect(err).NotTo(HaveOccurred()) 162 163 oldHostPort, _, err := container.NetIn(0, 0) 164 Expect(err).NotTo(HaveOccurred()) 165 166 client.Destroy(container.Handle()) 167 168 container, err = client.Create(garden.ContainerSpec{}) 169 Expect(err).NotTo(HaveOccurred()) 170 171 newHostPort, _, err := container.NetIn(0, 0) 172 Expect(err).NotTo(HaveOccurred()) 173 174 Expect(newHostPort).To(BeNumerically("==", oldHostPort+1)) 175 }) 176 177 Context("when server is restarted", func() { 178 It("should not reuse ports", func() { 179 var ( 180 containers []string 181 lastHostPort uint32 182 ) 183 184 for index := 0; index < 2; index++ { 185 container, err := client.Create(garden.ContainerSpec{}) 186 Expect(err).NotTo(HaveOccurred()) 187 188 hostPort, _, err := container.NetIn(0, 0) 189 Expect(err).NotTo(HaveOccurred()) 190 191 containers = append(containers, container.Handle()) 192 lastHostPort = hostPort 193 } 194 195 for index := 0; index < 2; index++ { 196 Expect(client.Destroy(containers[index])).To(Succeed()) 197 } 198 199 client = restartGarden("--portPoolSize", fmt.Sprintf("%d", portPoolSize)) 200 201 container, err := client.Create(garden.ContainerSpec{}) 202 Expect(err).NotTo(HaveOccurred()) 203 204 newHostPort, _, err := container.NetIn(0, 0) 205 Expect(err).NotTo(HaveOccurred()) 206 207 Expect(newHostPort).To(BeNumerically("==", lastHostPort+1)) 208 }) 209 210 Context("and the port range is reduced", func() { 211 It("should start from the first port", func() { 212 var ( 213 containers []string 214 firstHostPort uint32 215 ) 216 217 for index := 0; index < 2; index++ { 218 container, err := client.Create(garden.ContainerSpec{}) 219 Expect(err).NotTo(HaveOccurred()) 220 221 hostPort, _, err := container.NetIn(0, 0) 222 Expect(err).NotTo(HaveOccurred()) 223 224 containers = append(containers, container.Handle()) 225 if index == 0 { 226 firstHostPort = hostPort 227 } 228 } 229 230 for index := 0; index < 2; index++ { 231 Expect(client.Destroy(containers[index])).To(Succeed()) 232 } 233 234 client = restartGarden("--portPoolSize", fmt.Sprintf("%d", 1)) 235 236 container, err := client.Create(garden.ContainerSpec{}) 237 Expect(err).NotTo(HaveOccurred()) 238 239 newHostPort, _, err := container.NetIn(0, 0) 240 Expect(err).NotTo(HaveOccurred()) 241 242 Expect(newHostPort).To(BeNumerically("==", firstHostPort)) 243 }) 244 }) 245 246 Context("and the port range is exhausted with snapshotting disabled", func() { 247 BeforeEach(func() { 248 portPoolSize = 1 249 extraArgs = append(extraArgs, "--snapshots", "") 250 }) 251 252 It("returns the first port in the range", func() { 253 container, err := client.Create(garden.ContainerSpec{}) 254 Expect(err).NotTo(HaveOccurred()) 255 256 firstHostPort, _, err := container.NetIn(0, 0) 257 Expect(err).NotTo(HaveOccurred()) 258 259 client = restartGarden("--portPoolSize", fmt.Sprintf("%d", 2)) 260 261 container, err = client.Create(garden.ContainerSpec{}) 262 Expect(err).NotTo(HaveOccurred()) 263 264 newHostPort, _, err := container.NetIn(0, 0) 265 Expect(err).NotTo(HaveOccurred()) 266 267 Expect(newHostPort).To(BeNumerically("==", firstHostPort)) 268 }) 269 }) 270 271 Context("and the port range is exhausted with snapshotting enabled", func() { 272 BeforeEach(func() { 273 portPoolSize = 1 274 snapshotsPath, err := ioutil.TempDir("", "snapshots") 275 Expect(err).NotTo(HaveOccurred()) 276 extraArgs = append(extraArgs, "--snapshots", snapshotsPath) 277 }) 278 279 It("stays exhausted after a restart", func() { 280 container, err := client.Create(garden.ContainerSpec{}) 281 Expect(err).NotTo(HaveOccurred()) 282 283 _, _, err = container.NetIn(0, 0) 284 Expect(err).NotTo(HaveOccurred()) 285 286 args := append(extraArgs, "--portPoolSize", fmt.Sprintf("%d", portPoolSize)) 287 client = restartGarden(args...) 288 289 containers, err := client.Containers(garden.Properties{}) 290 Expect(err).NotTo(HaveOccurred()) 291 Expect(containers).To(HaveLen(1)) 292 293 container, err = client.Create(garden.ContainerSpec{}) 294 Expect(err).NotTo(HaveOccurred()) 295 296 _, _, err = container.NetIn(0, 0) 297 Expect(err).To(HaveOccurred()) 298 }) 299 }) 300 }) 301 })