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  })