github.com/cloudfoundry-attic/garden-linux@v0.333.2-candidate/linux_container/iptables_manager/nat_test.go (about)

     1  package iptables_manager_test
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"os/exec"
     7  
     8  	"github.com/cloudfoundry/gunk/command_runner/fake_command_runner"
     9  
    10  	"net"
    11  
    12  	"github.com/cloudfoundry-incubator/garden-linux/linux_container/iptables_manager"
    13  	"github.com/cloudfoundry-incubator/garden-linux/sysconfig"
    14  	. "github.com/cloudfoundry/gunk/command_runner/fake_command_runner/matchers"
    15  	. "github.com/onsi/ginkgo"
    16  	. "github.com/onsi/ginkgo/extensions/table"
    17  	. "github.com/onsi/gomega"
    18  	"github.com/pivotal-golang/lager/lagertest"
    19  )
    20  
    21  var _ = Describe("natChain", func() {
    22  	var (
    23  		fakeRunner  *fake_command_runner.FakeCommandRunner
    24  		testCfg     *sysconfig.IPTablesNATConfig
    25  		chain       iptables_manager.Chain
    26  		containerID string
    27  		bridgeName  string
    28  		ip          net.IP
    29  		network     *net.IPNet
    30  	)
    31  
    32  	BeforeEach(func() {
    33  		var err error
    34  
    35  		fakeRunner = fake_command_runner.New()
    36  		testCfg = &sysconfig.IPTablesNATConfig{
    37  			PreroutingChain:  "nat-prerouting-chain",
    38  			PostroutingChain: "nat-postrouting-chain",
    39  			InstancePrefix:   "nat-instance-prefix",
    40  		}
    41  
    42  		containerID = "some-ctr-id"
    43  		bridgeName = "some-bridge"
    44  		ip, network, err = net.ParseCIDR("1.2.3.4/28")
    45  		Expect(err).NotTo(HaveOccurred())
    46  
    47  		chain = iptables_manager.NewNATChain(testCfg, fakeRunner, lagertest.NewTestLogger("test"))
    48  	})
    49  
    50  	Describe("ContainerSetup", func() {
    51  		var specs []fake_command_runner.CommandSpec
    52  		BeforeEach(func() {
    53  			expectedNatInstanceChain := testCfg.InstancePrefix + containerID
    54  			specs = []fake_command_runner.CommandSpec{
    55  				fake_command_runner.CommandSpec{
    56  					Path: "iptables",
    57  					Args: []string{"--wait", "--table", "nat", "-N", expectedNatInstanceChain},
    58  				},
    59  				fake_command_runner.CommandSpec{
    60  					Path: "iptables",
    61  					Args: []string{"--wait", "--table", "nat", "-A", testCfg.PreroutingChain,
    62  						"--jump", expectedNatInstanceChain},
    63  				},
    64  				fake_command_runner.CommandSpec{
    65  					Path: "sh",
    66  					Args: []string{"-c", fmt.Sprintf(
    67  						`(iptables --wait --table nat -S %s | grep "\-j MASQUERADE\b" | grep -q -F -- "-s %s") || iptables --wait --table nat -A %s --source %s ! --destination %s --jump MASQUERADE`,
    68  						testCfg.PostroutingChain, network.String(), testCfg.PostroutingChain,
    69  						network.String(), network.String(),
    70  					)},
    71  				},
    72  			}
    73  		})
    74  
    75  		It("should set up the chain", func() {
    76  			Expect(chain.Setup(containerID, bridgeName, ip, network)).To(Succeed())
    77  
    78  			Expect(fakeRunner).To(HaveExecutedSerially(specs...))
    79  		})
    80  
    81  		DescribeTable("iptables failures",
    82  			func(specIndex int, errorString string) {
    83  				fakeRunner.WhenRunning(specs[specIndex], func(*exec.Cmd) error {
    84  					return errors.New("iptables failed")
    85  				})
    86  
    87  				Expect(chain.Setup(containerID, bridgeName, ip, network)).To(MatchError(errorString))
    88  			},
    89  			Entry("create nat instance chain", 0, "iptables_manager: nat: iptables failed"),
    90  			Entry("bind nat instance chain to nat prerouting chain", 1, "iptables_manager: nat: iptables failed"),
    91  			Entry("enable NAT for traffic coming from containers", 2, "iptables_manager: nat: iptables failed"),
    92  		)
    93  	})
    94  
    95  	Describe("ContainerTeardown", func() {
    96  		var specs []fake_command_runner.CommandSpec
    97  
    98  		Describe("nat chain", func() {
    99  			BeforeEach(func() {
   100  				expectedFilterInstanceChain := testCfg.InstancePrefix + containerID
   101  				specs = []fake_command_runner.CommandSpec{
   102  					fake_command_runner.CommandSpec{
   103  						Path: "sh",
   104  						Args: []string{"-c", fmt.Sprintf(
   105  							`iptables --wait --table nat -S %s 2> /dev/null | grep "\-j %s\b" | sed -e "s/-A/-D/" | xargs --no-run-if-empty --max-lines=1 iptables --wait --table nat`,
   106  							testCfg.PreroutingChain, expectedFilterInstanceChain,
   107  						)},
   108  					},
   109  					fake_command_runner.CommandSpec{
   110  						Path: "sh",
   111  						Args: []string{"-c", fmt.Sprintf(
   112  							`iptables --wait --table nat -F %s 2> /dev/null || true`,
   113  							expectedFilterInstanceChain,
   114  						)},
   115  					},
   116  					fake_command_runner.CommandSpec{
   117  						Path: "sh",
   118  						Args: []string{"-c", fmt.Sprintf(
   119  							`iptables --wait --table nat -X %s 2> /dev/null || true`,
   120  							expectedFilterInstanceChain,
   121  						)},
   122  					},
   123  				}
   124  			})
   125  
   126  			It("should tear down the chain", func() {
   127  				Expect(chain.Teardown(containerID)).To(Succeed())
   128  
   129  				Expect(fakeRunner).To(HaveExecutedSerially(specs...))
   130  			})
   131  
   132  			DescribeTable("iptables failures",
   133  				func(specIndex int, errorString string) {
   134  					fakeRunner.WhenRunning(specs[specIndex], func(*exec.Cmd) error {
   135  						return errors.New("iptables failed")
   136  					})
   137  
   138  					Expect(chain.Teardown(containerID)).To(MatchError(errorString))
   139  				},
   140  				Entry("prune prerouting chain", 0, "iptables_manager: nat: iptables failed"),
   141  				Entry("flush instance chain", 1, "iptables_manager: nat: iptables failed"),
   142  				Entry("delete instance chain", 2, "iptables_manager: nat: iptables failed"),
   143  			)
   144  		})
   145  	})
   146  })