github.com/schwarzm/garden-linux@v0.0.0-20150507151835-33bca2147c47/linux_backend/hooks_test.go (about) 1 package linux_backend_test 2 3 import ( 4 "errors" 5 "fmt" 6 "os/exec" 7 8 "github.com/cloudfoundry-incubator/garden-linux/hook" 9 "github.com/cloudfoundry-incubator/garden-linux/linux_backend" 10 linuxBackendFakes "github.com/cloudfoundry-incubator/garden-linux/linux_backend/fakes" 11 "github.com/cloudfoundry/gunk/command_runner/fake_command_runner" 12 13 "io/ioutil" 14 15 "os" 16 17 "path/filepath" 18 19 "net" 20 21 networkFakes "github.com/cloudfoundry-incubator/garden-linux/network/fakes" 22 "github.com/cloudfoundry-incubator/garden-linux/process" 23 . "github.com/cloudfoundry/gunk/command_runner/fake_command_runner/matchers" 24 . "github.com/onsi/ginkgo" 25 . "github.com/onsi/gomega" 26 ) 27 28 var _ = Describe("Hooks", func() { 29 var hooks hook.HookSet 30 var fakeRunner *fake_command_runner.FakeCommandRunner 31 var config process.Env 32 var fakeContainerInitializer *linuxBackendFakes.FakeContainerInitializer 33 var fakeNetworkConfigurer *networkFakes.FakeConfigurer 34 35 BeforeEach(func() { 36 hooks = make(hook.HookSet) 37 fakeRunner = fake_command_runner.New() 38 config = process.Env{ 39 "id": "someID", 40 "network_cidr": "1.2.3.4/8", 41 "container_iface_mtu": "5000", 42 "network_container_ip": "1.6.6.6", 43 "network_host_ip": "1.2.3.5", 44 "network_host_iface": "hostIfc", 45 "network_container_iface": "containerIfc", 46 "bridge_iface": "bridgeName", 47 } 48 fakeContainerInitializer = &linuxBackendFakes.FakeContainerInitializer{} 49 fakeNetworkConfigurer = &networkFakes.FakeConfigurer{} 50 }) 51 52 Context("After RegisterHooks has been run", func() { 53 JustBeforeEach(func() { 54 linux_backend.RegisterHooks(hooks, fakeRunner, config, fakeContainerInitializer, fakeNetworkConfigurer) 55 }) 56 57 Context("Inside the host", func() { 58 Context("before container creation", func() { 59 It("runs the hook-parent-before-clone.sh legacy shell script", func() { 60 hooks.Main(hook.PARENT_BEFORE_CLONE) 61 Expect(fakeRunner).To(HaveExecutedSerially(fake_command_runner.CommandSpec{ 62 Path: "hook-parent-before-clone.sh", 63 })) 64 }) 65 66 Context("when the legacy shell script fails", func() { 67 BeforeEach(func() { 68 fakeRunner.WhenRunning(fake_command_runner.CommandSpec{ 69 Path: "hook-parent-before-clone.sh", 70 }, func(*exec.Cmd) error { 71 return errors.New("o no") 72 }) 73 }) 74 75 It("panics", func() { 76 Expect(func() { hooks.Main(hook.PARENT_BEFORE_CLONE) }).To(Panic()) 77 }) 78 }) 79 }) 80 81 Context("after container creation", func() { 82 var oldWd, testDir string 83 84 BeforeEach(func() { 85 // Write wshd.pid to a suitable temporary directory and change directory so that 86 // the PID file is in ../run. 87 var err error 88 oldWd, err = os.Getwd() 89 Expect(err).NotTo(HaveOccurred()) 90 91 testDir, err = ioutil.TempDir("", "test") 92 Expect(err).NotTo(HaveOccurred()) 93 runDir := filepath.Join(testDir, "run") 94 os.MkdirAll(runDir, 0755) 95 96 err = ioutil.WriteFile(filepath.Join(runDir, "wshd.pid"), []byte(fmt.Sprintf("%d\n", 99)), 0755) 97 Expect(err).NotTo(HaveOccurred()) 98 99 libDir := filepath.Join(testDir, "lib") 100 os.MkdirAll(libDir, 0755) 101 os.Chdir(libDir) 102 }) 103 104 AfterEach(func() { 105 if oldWd != "" { 106 os.Chdir(oldWd) 107 } 108 109 if testDir != "" { 110 os.RemoveAll(testDir) 111 } 112 }) 113 114 It("configures the host's network correctly", func() { 115 Expect(func() { hooks.Main(hook.PARENT_AFTER_CLONE) }).ToNot(Panic()) 116 117 Expect(fakeNetworkConfigurer.ConfigureHostCallCount()).To(Equal(1)) 118 hostConfig := fakeNetworkConfigurer.ConfigureHostArgsForCall(0) 119 Expect(hostConfig.HostIntf).To(Equal("hostIfc")) 120 Expect(hostConfig.ContainerIntf).To(Equal("containerIfc")) 121 Expect(hostConfig.BridgeName).To(Equal("bridgeName")) 122 Expect(hostConfig.ContainerPid).To(Equal(99)) 123 Expect(hostConfig.BridgeIP).To(Equal(net.ParseIP("1.2.3.5"))) 124 _, expectedSubnet, _ := net.ParseCIDR("1.2.3.4/8") 125 Expect(hostConfig.Subnet).To(Equal(expectedSubnet)) 126 Expect(hostConfig.Mtu).To(Equal(5000)) 127 }) 128 129 Context("when the network configurer fails", func() { 130 BeforeEach(func() { 131 fakeNetworkConfigurer.ConfigureHostReturns(errors.New("oh no!")) 132 }) 133 134 It("panics", func() { 135 Expect(func() { hooks.Main(hook.PARENT_AFTER_CLONE) }).To(Panic()) 136 }) 137 }) 138 139 Context("when the network CIDR is badly formatted", func() { 140 BeforeEach(func() { 141 config["network_cidr"] = "1.2.3.4/8/9" 142 }) 143 144 It("panics", func() { 145 Expect(func() { hooks.Main(hook.PARENT_AFTER_CLONE) }).To(Panic()) 146 }) 147 }) 148 149 Context("when the MTU is invalid", func() { 150 BeforeEach(func() { 151 config["container_iface_mtu"] = "x" 152 }) 153 154 It("panics", func() { 155 Expect(func() { hooks.Main(hook.PARENT_AFTER_CLONE) }).To(Panic()) 156 }) 157 }) 158 159 It("runs the hook-parent-after-clone.sh legacy shell script", func() { 160 Expect(func() { hooks.Main(hook.PARENT_AFTER_CLONE) }).ToNot(Panic()) 161 Expect(fakeRunner).To(HaveExecutedSerially(fake_command_runner.CommandSpec{ 162 Path: "hook-parent-after-clone.sh", 163 })) 164 }) 165 166 Context("when the legacy shell script fails", func() { 167 BeforeEach(func() { 168 fakeRunner.WhenRunning(fake_command_runner.CommandSpec{ 169 Path: "hook-parent-after-clone.sh", 170 }, func(*exec.Cmd) error { 171 return errors.New("o no") 172 }) 173 }) 174 175 It("panics", func() { 176 Expect(func() { hooks.Main(hook.PARENT_AFTER_CLONE) }).To(Panic()) 177 }) 178 }) 179 }) 180 }) 181 182 Context("Inside the child", func() { 183 184 Context("after pivotting in to the rootfs", func() { 185 It("mounts proc", func() { 186 fakeContainerInitializer.MountProcReturns(nil) 187 Expect(func() { hooks.Main(hook.CHILD_AFTER_PIVOT) }).ToNot(Panic()) 188 Expect(fakeContainerInitializer.MountProcCallCount()).To(Equal(1)) 189 }) 190 191 Context("when mounting proc fails", func() { 192 BeforeEach(func() { 193 fakeContainerInitializer.MountProcReturns(errors.New("oh no!")) 194 }) 195 196 It("panics", func() { 197 Expect(func() { hooks.Main(hook.CHILD_AFTER_PIVOT) }).To(Panic()) 198 }) 199 }) 200 201 It("mounts tmp", func() { 202 fakeContainerInitializer.MountTmpReturns(nil) 203 Expect(func() { hooks.Main(hook.CHILD_AFTER_PIVOT) }).ToNot(Panic()) 204 Expect(fakeContainerInitializer.MountTmpCallCount()).To(Equal(1)) 205 }) 206 207 Context("when mounting tmp fails", func() { 208 BeforeEach(func() { 209 fakeContainerInitializer.MountTmpReturns(errors.New("oh no!")) 210 }) 211 212 It("panics", func() { 213 Expect(func() { hooks.Main(hook.CHILD_AFTER_PIVOT) }).To(Panic()) 214 }) 215 }) 216 217 It("configures the container's network correctly", func() { 218 Expect(func() { hooks.Main(hook.CHILD_AFTER_PIVOT) }).ToNot(Panic()) 219 220 Expect(fakeNetworkConfigurer.ConfigureContainerCallCount()).To(Equal(1)) 221 222 networkConfig := fakeNetworkConfigurer.ConfigureContainerArgsForCall(0) 223 Expect(networkConfig.Hostname).To(Equal("someID")) 224 Expect(networkConfig.ContainerIntf).To(Equal("containerIfc")) 225 Expect(networkConfig.ContainerIP).To(Equal(net.ParseIP("1.6.6.6"))) 226 Expect(networkConfig.GatewayIP).To(Equal(net.ParseIP("1.2.3.5"))) 227 228 _, expectedSubnet, _ := net.ParseCIDR("1.2.3.4/8") 229 Expect(networkConfig.Subnet).To(Equal(expectedSubnet)) 230 Expect(networkConfig.Mtu).To(Equal(5000)) 231 }) 232 233 Context("when the network configurer returns an error", func() { 234 BeforeEach(func() { 235 fakeNetworkConfigurer.ConfigureContainerReturns(errors.New("oh no!")) 236 }) 237 238 It("panics", func() { 239 Expect(func() { hooks.Main(hook.CHILD_AFTER_PIVOT) }).To(Panic()) 240 }) 241 }) 242 243 Context("when the network CIDR is badly formatted", func() { 244 BeforeEach(func() { 245 config["network_cidr"] = "1.2.3.4/8/9" 246 }) 247 248 It("panics", func() { 249 Expect(func() { hooks.Main(hook.CHILD_AFTER_PIVOT) }).To(Panic()) 250 }) 251 }) 252 253 Context("when the MTU is invalid", func() { 254 BeforeEach(func() { 255 config["container_iface_mtu"] = "x" 256 }) 257 258 It("panics", func() { 259 Expect(func() { hooks.Main(hook.CHILD_AFTER_PIVOT) }).To(Panic()) 260 }) 261 }) 262 263 }) 264 }) 265 }) 266 })