github.com/schwarzm/garden-linux@v0.0.0-20150507151835-33bca2147c47/integration/networking/ip_test.go (about) 1 package networking_test 2 3 import ( 4 "fmt" 5 "net" 6 "net/http" 7 "os/exec" 8 "strconv" 9 "strings" 10 11 "github.com/cloudfoundry-incubator/garden" 12 "github.com/cloudfoundry/gunk/localip" 13 . "github.com/onsi/ginkgo" 14 . "github.com/onsi/gomega" 15 "github.com/onsi/gomega/gbytes" 16 ) 17 18 var _ = Describe("IP settings", func() { 19 var ( 20 container1 garden.Container 21 container2 garden.Container 22 23 containerNetwork1 string 24 containerNetwork2 string 25 26 containerInterface string 27 28 gardenParms []string 29 ) 30 31 BeforeEach(func() { 32 container1 = nil 33 container2 = nil 34 containerNetwork1 = "" 35 containerNetwork2 = "" 36 37 gardenParms = []string{} 38 }) 39 40 JustBeforeEach(func() { 41 client = startGarden(gardenParms...) 42 43 var err error 44 container1, err = client.Create(garden.ContainerSpec{Network: containerNetwork1}) 45 Expect(err).ToNot(HaveOccurred()) 46 47 if len(containerNetwork2) > 0 { 48 container2, err = client.Create(garden.ContainerSpec{Network: containerNetwork2}) 49 Expect(err).ToNot(HaveOccurred()) 50 } 51 52 containerInterface = "w" + strconv.Itoa(GinkgoParallelNode()) + container1.Handle() + "-1" 53 }) 54 55 AfterEach(func() { 56 if container1 != nil { 57 err := client.Destroy(container1.Handle()) 58 Expect(err).ToNot(HaveOccurred()) 59 } 60 61 if container2 != nil { 62 err := client.Destroy(container2.Handle()) 63 Expect(err).ToNot(HaveOccurred()) 64 } 65 }) 66 67 Context("when the Network parameter is a subnet address", func() { 68 BeforeEach(func() { 69 containerNetwork1 = fmt.Sprintf("10.%d.0.0/24", GinkgoParallelNode()) 70 }) 71 72 Describe("container's network interface", func() { 73 It("has the correct IP address", func() { 74 stdout := gbytes.NewBuffer() 75 stderr := gbytes.NewBuffer() 76 77 process, err := container1.Run(garden.ProcessSpec{ 78 Path: "/sbin/ifconfig", 79 Args: []string{containerInterface}, 80 }, garden.ProcessIO{ 81 Stdout: stdout, 82 Stderr: stderr, 83 }) 84 Expect(err).ToNot(HaveOccurred()) 85 rc, err := process.Wait() 86 Expect(err).ToNot(HaveOccurred()) 87 Expect(rc).To(Equal(0)) 88 89 Expect(stdout.Contents()).To(ContainSubstring(fmt.Sprintf(" inet addr:10.%d.0.1 ", GinkgoParallelNode()))) 90 }) 91 }) 92 }) 93 94 Context("when the Network parameter is not a subnet address", func() { 95 BeforeEach(func() { 96 containerNetwork1 = fmt.Sprintf("10.%d.0.2/24", GinkgoParallelNode()) 97 }) 98 99 Describe("container's network interface", func() { 100 It("has the specified IP address", func() { 101 stdout := gbytes.NewBuffer() 102 stderr := gbytes.NewBuffer() 103 104 process, err := container1.Run(garden.ProcessSpec{ 105 Path: "/sbin/ifconfig", 106 Args: []string{containerIfName(container1)}, 107 }, garden.ProcessIO{ 108 Stdout: stdout, 109 Stderr: stderr, 110 }) 111 Expect(err).ToNot(HaveOccurred()) 112 rc, err := process.Wait() 113 Expect(err).ToNot(HaveOccurred()) 114 Expect(rc).To(Equal(0)) 115 116 Expect(stdout.Contents()).To(ContainSubstring(fmt.Sprintf(" inet addr:10.%d.0.2 ", GinkgoParallelNode()))) 117 }) 118 }) 119 }) 120 121 Describe("the container's network", func() { 122 BeforeEach(func() { 123 containerNetwork1 = fmt.Sprintf("10.%d.0.0/24", GinkgoParallelNode()) 124 }) 125 126 It("is reachable from the host", func() { 127 info1, ierr := container1.Info() 128 Expect(ierr).ToNot(HaveOccurred()) 129 130 out, err := exec.Command("/bin/ping", "-c 2", info1.ContainerIP).Output() 131 Expect(out).To(ContainSubstring(" 0% packet loss")) 132 Expect(err).ToNot(HaveOccurred()) 133 }) 134 }) 135 136 Describe("another container on the same subnet", func() { 137 BeforeEach(func() { 138 containerNetwork1 = fmt.Sprintf("10.%d.0.0/24", GinkgoParallelNode()) 139 containerNetwork2 = containerNetwork1 140 }) 141 142 Context("when the first container is deleted", func() { 143 JustBeforeEach(func() { 144 Expect(client.Destroy(container1.Handle())).To(Succeed()) 145 container1 = nil 146 }) 147 148 Context("the second container", func() { 149 It("can still reach external networks", func() { 150 Expect(checkInternet(container2)).To(Succeed()) 151 }) 152 153 It("can still be reached from the host", func() { 154 info2, ierr := container2.Info() 155 Expect(ierr).ToNot(HaveOccurred()) 156 157 out, err := exec.Command("/bin/ping", "-c 2", info2.ContainerIP).Output() 158 Expect(out).To(ContainSubstring(" 0% packet loss")) 159 Expect(err).ToNot(HaveOccurred()) 160 }) 161 }) 162 163 Context("a newly created container in the same subnet", func() { 164 var ( 165 container3 garden.Container 166 ) 167 168 JustBeforeEach(func() { 169 var err error 170 container3, err = client.Create(garden.ContainerSpec{Network: containerNetwork1}) 171 Expect(err).ToNot(HaveOccurred()) 172 }) 173 174 AfterEach(func() { 175 err := client.Destroy(container3.Handle()) 176 Expect(err).ToNot(HaveOccurred()) 177 }) 178 179 It("can reach the second container", func() { 180 info2, err := container2.Info() 181 Expect(err).ToNot(HaveOccurred()) 182 183 listener, err := container2.Run(garden.ProcessSpec{ 184 Path: "sh", 185 Args: []string{"-c", "echo hi | nc -l -p 8080"}, 186 }, garden.ProcessIO{}) 187 Expect(err).ToNot(HaveOccurred()) 188 189 Expect(checkConnection(container3, info2.ContainerIP, 8080)).To(Succeed()) 190 191 Expect(listener.Wait()).To(Equal(0)) 192 }) 193 194 It("can be reached from the host", func() { 195 info3, ierr := container3.Info() 196 Expect(ierr).ToNot(HaveOccurred()) 197 198 out, err := exec.Command("/bin/ping", "-c 2", info3.ContainerIP).Output() 199 Expect(out).To(ContainSubstring(" 0% packet loss")) 200 Expect(err).ToNot(HaveOccurred()) 201 }) 202 }) 203 }) 204 }) 205 206 Describe("host's network", func() { 207 Context("when host access is explicitly allowed", func() { 208 BeforeEach(func() { 209 containerNetwork1 = fmt.Sprintf("10.%d.0.8/30", GinkgoParallelNode()) 210 gardenParms = []string{"-allowHostAccess=true"} 211 }) 212 213 It("is reachable from inside the container", func() { 214 checkHostAccess(container1, true) 215 }) 216 }) 217 218 Context("when host access is explicitly disallowed", func() { 219 BeforeEach(func() { 220 containerNetwork1 = fmt.Sprintf("10.%d.0.8/30", GinkgoParallelNode()) 221 gardenParms = []string{"-allowHostAccess=false"} 222 }) 223 224 It("is not reachable from inside the container", func() { 225 checkHostAccess(container1, false) 226 }) 227 }) 228 229 Context("when host access is implicitly disallowed", func() { 230 BeforeEach(func() { 231 containerNetwork1 = fmt.Sprintf("10.%d.0.8/30", GinkgoParallelNode()) 232 }) 233 234 It("is not reachable from inside the container", func() { 235 checkHostAccess(container1, false) 236 }) 237 }) 238 }) 239 240 Describe("the container's external ip", func() { 241 It("is the external IP of its host", func() { 242 info1, err := container1.Info() 243 Expect(err).ToNot(HaveOccurred()) 244 245 localIP, err := localip.LocalIP() 246 Expect(err).ToNot(HaveOccurred()) 247 248 Expect(localIP).To(Equal(info1.ExternalIP)) 249 }) 250 }) 251 }) 252 253 func checkHostAccess(container garden.Container, permitted bool) { 254 info1, ierr := container.Info() 255 Expect(ierr).ToNot(HaveOccurred()) 256 257 listener, err := net.Listen("tcp", fmt.Sprintf("%s:0", info1.HostIP)) 258 Expect(err).ToNot(HaveOccurred()) 259 defer listener.Close() 260 261 mux := http.NewServeMux() 262 mux.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) { 263 fmt.Fprintf(w, "Hello") 264 }) 265 266 go (&http.Server{Handler: mux}).Serve(listener) 267 268 port, err := strconv.Atoi(strings.Split(listener.Addr().String(), ":")[1]) 269 Expect(err).ToNot(HaveOccurred()) 270 err = checkConnection(container, info1.HostIP, port) 271 272 if permitted { 273 Expect(err).ToNot(HaveOccurred()) 274 } else { 275 Expect(err).To(HaveOccurred()) 276 } 277 }