func (s *lxcBrokerSuite) TestSetupRoutesAndIPTablesAddsRuleIfMissing(c *gc.C) { // Isolate the test from the host machine. Because PatchExecutable // does not allow us to assert on subsequent executions of the // same binary, we need to replace the iptables commands with // separate ones. The check returns code=1 to trigger calling // add. fakeptablesRules := map[string]provisioner.IptablesRule{ "IPTablesSNAT": { "nat", "POSTROUTING", "{{.HostIF}} {{.HostIP}}", }, } s.PatchValue(provisioner.IptablesRules, fakeptablesRules) gitjujutesting.PatchExecutableAsEchoArgs(c, s, "iptables", 1, 0) gitjujutesting.PatchExecutableAsEchoArgs(c, s, "ip") ifaceInfo := []network.InterfaceInfo{{ Address: network.NewAddress("0.1.2.3"), }} addr := network.NewAddress("0.1.2.1") err := provisioner.SetupRoutesAndIPTables("nic", addr, "bridge", ifaceInfo, false) c.Assert(err, jc.ErrorIsNil) // Now verify the expected commands - since check returns 1, add // will be called before ip route add. gitjujutesting.AssertEchoArgs(c, "iptables", "-t", "nat", "-C", "POSTROUTING", "nic", "0.1.2.1") gitjujutesting.AssertEchoArgs(c, "iptables", "-t", "nat", "-I", "POSTROUTING", "1", "nic", "0.1.2.1") gitjujutesting.AssertEchoArgs(c, "ip", "route", "add", "0.1.2.3", "dev", "bridge") }
func (s *lxcBrokerSuite) TestSetupRoutesAndIPTablesIPTablesAddError(c *gc.C) { // Isolate the test from the host machine. Patch iptables with a // script which returns code=1 for the check but fails when adding // the rule. script := `if [[ "$3" == "-C" ]]; then exit 1; else exit 42; fi` gitjujutesting.PatchExecutable(c, s, "iptables", script) gitjujutesting.PatchExecutableThrowError(c, s, "ip", 123) fakeptablesRules := map[string]provisioner.IptablesRule{ "IPTablesSNAT": { "nat", "POSTROUTING", "{{.HostIF}} {{.HostIP}}", }, } s.PatchValue(provisioner.IptablesRules, fakeptablesRules) ifaceInfo := []network.InterfaceInfo{{ Address: network.NewAddress("0.1.2.3"), }} addr := network.NewAddress("0.1.2.1") err := provisioner.SetupRoutesAndIPTables("nic", addr, "bridge", ifaceInfo, false) c.Assert(err, gc.ErrorMatches, `command "iptables -t nat -I .*" failed with exit code 42`) }
func (s *lxcBrokerSuite) TestSetupRoutesAndIPTablesIPTablesCheckError(c *gc.C) { // Isolate the test from the host machine. gitjujutesting.PatchExecutableThrowError(c, s, "iptables", 42) gitjujutesting.PatchExecutableThrowError(c, s, "ip", 123) ifaceInfo := []network.InterfaceInfo{{ Address: network.NewAddress("0.1.2.3"), }} addr := network.NewAddress("0.1.2.1") err := provisioner.SetupRoutesAndIPTables("nic", addr, "bridge", ifaceInfo, false) c.Assert(err, gc.ErrorMatches, "iptables failed with unexpected exit code 42") }
func (s *lxcBrokerSuite) TestSetupRoutesAndIPTablesIPRouteError(c *gc.C) { // Isolate the test from the host machine. // Returning code=0 from iptables means we won't add a rule. gitjujutesting.PatchExecutableThrowError(c, s, "iptables", 0) gitjujutesting.PatchExecutableThrowError(c, s, "ip", 123) ifaceInfo := []network.InterfaceInfo{{ Address: network.NewAddress("0.1.2.3"), }} addr := network.NewAddress("0.1.2.1") err := provisioner.SetupRoutesAndIPTables("nic", addr, "bridge", ifaceInfo, false) c.Assert(err, gc.ErrorMatches, `command "ip route add 0.1.2.3 dev bridge" failed with exit code 123`, ) }
func (s *lxcBrokerSuite) TestSetupRoutesAndIPTablesInvalidArgs(c *gc.C) { // Isolate the test from the host machine. gitjujutesting.PatchExecutableThrowError(c, s, "iptables", 42) gitjujutesting.PatchExecutableThrowError(c, s, "ip", 123) // Check that all the arguments are verified to be non-empty. expectStartupErr := "primaryNIC, primaryAddr, bridgeName, and ifaceInfo must be all set" emptyIfaceInfo := []network.InterfaceInfo{} for i, test := range []struct { about string primaryNIC string primaryAddr network.Address bridgeName string ifaceInfo []network.InterfaceInfo expectErr string }{{ about: "all empty", primaryNIC: "", primaryAddr: network.Address{}, bridgeName: "", ifaceInfo: nil, expectErr: expectStartupErr, }, { about: "all but primaryNIC empty", primaryNIC: "nic", primaryAddr: network.Address{}, bridgeName: "", ifaceInfo: nil, expectErr: expectStartupErr, }, { about: "all but primaryAddr empty", primaryNIC: "", primaryAddr: network.NewAddress("0.1.2.1"), bridgeName: "", ifaceInfo: nil, expectErr: expectStartupErr, }, { about: "all but bridgeName empty", primaryNIC: "", primaryAddr: network.Address{}, bridgeName: "bridge", ifaceInfo: nil, expectErr: expectStartupErr, }, { about: "all but primaryNIC and bridgeName empty", primaryNIC: "nic", primaryAddr: network.Address{}, bridgeName: "bridge", ifaceInfo: nil, expectErr: expectStartupErr, }, { about: "all but primaryNIC and primaryAddr empty", primaryNIC: "nic", primaryAddr: network.NewAddress("0.1.2.1"), bridgeName: "", ifaceInfo: nil, expectErr: expectStartupErr, }, { about: "all but primaryAddr and bridgeName empty", primaryNIC: "", primaryAddr: network.NewAddress("0.1.2.1"), bridgeName: "bridge", ifaceInfo: nil, expectErr: expectStartupErr, }, { about: "all set except ifaceInfo", primaryNIC: "nic", primaryAddr: network.NewAddress("0.1.2.1"), bridgeName: "bridge", ifaceInfo: nil, expectErr: expectStartupErr, }, { about: "all empty (ifaceInfo set but empty)", primaryNIC: "", primaryAddr: network.Address{}, bridgeName: "", ifaceInfo: emptyIfaceInfo, expectErr: expectStartupErr, }, { about: "all but primaryNIC empty (ifaceInfo set but empty)", primaryNIC: "nic", primaryAddr: network.Address{}, bridgeName: "", ifaceInfo: emptyIfaceInfo, expectErr: expectStartupErr, }, { about: "all but primaryAddr empty (ifaceInfo set but empty)", primaryNIC: "", primaryAddr: network.NewAddress("0.1.2.1"), bridgeName: "", ifaceInfo: emptyIfaceInfo, expectErr: expectStartupErr, }, { about: "all but bridgeName empty (ifaceInfo set but empty)", primaryNIC: "", primaryAddr: network.Address{}, bridgeName: "bridge", ifaceInfo: emptyIfaceInfo, expectErr: expectStartupErr, }, { about: "just primaryAddr is empty and ifaceInfo set but empty", primaryNIC: "nic", primaryAddr: network.Address{}, bridgeName: "bridge", ifaceInfo: emptyIfaceInfo, expectErr: expectStartupErr, }, { about: "just bridgeName is empty and ifaceInfo set but empty", primaryNIC: "nic", primaryAddr: network.NewAddress("0.1.2.1"), bridgeName: "", ifaceInfo: emptyIfaceInfo, expectErr: expectStartupErr, }, { about: "just primaryNIC is empty and ifaceInfo set but empty", primaryNIC: "", primaryAddr: network.NewAddress("0.1.2.1"), bridgeName: "bridge", ifaceInfo: emptyIfaceInfo, expectErr: expectStartupErr, }, { about: "all set except ifaceInfo, which is set but empty", primaryNIC: "nic", primaryAddr: network.NewAddress("0.1.2.1"), bridgeName: "bridge", ifaceInfo: emptyIfaceInfo, expectErr: expectStartupErr, }, { about: "all set, but ifaceInfo has empty Address", primaryNIC: "nic", primaryAddr: network.NewAddress("0.1.2.1"), bridgeName: "bridge", // No Address set. ifaceInfo: []network.InterfaceInfo{{DeviceIndex: 0}}, expectErr: `container IP "" must be set`, }} { c.Logf("test %d: %s", i, test.about) err := provisioner.SetupRoutesAndIPTables( test.primaryNIC, test.primaryAddr, test.bridgeName, test.ifaceInfo, false, // TODO(dimitern): Untested. ) c.Check(err, gc.ErrorMatches, test.expectErr) } }