Skip to content

Commit

Permalink
Merge pull request #861 from VincentS/Calico_NAT_Outgoing_Flag
Browse files Browse the repository at this point in the history
Added NAT_Outgoing parameter to Calico Node
  • Loading branch information
robbrockbank authored Jun 21, 2017
2 parents 1078a94 + 77c3308 commit 4f65624
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 47 deletions.
45 changes: 35 additions & 10 deletions calico_node/startup/startup.go
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,29 @@ func validateIP(ipn *net.IPNet) {
warning("Unable to confirm IPv%d address %s is assigned to this host", ip.Version(), ip)
}

// evaluateENVBool evaluates a passed environment variable
// Returns True if the envVar is defined and set to true.
// Returns False if the envVar is defined and set to false.
// Returns defaultValue in the envVar is not defined.
// An log entry will always be written
func evaluateENVBool(envVar string, defaultValue bool) bool {
envValue, isSet := os.LookupEnv(envVar)

if isSet {

switch strings.ToLower(envValue) {

case "false", "0", "no", "n", "f":
log.Infof("%s is %t through environment variable", envVar, false)
return false
}
log.Infof("%s is %t through environment variable", envVar, true)
return true
}
log.Infof("%s is %t (defaulted) through environment variable", envVar, defaultValue)
return defaultValue
}

// autoDetectCIDR auto-detects the IP and Network using the requested
// detection method.
func autoDetectCIDR(method string, version int) *net.IPNet {
Expand Down Expand Up @@ -497,11 +520,14 @@ func configureIPPools(client *client.Client) {
// Ensure there are pools created for each IP version.
if !ipv4Present {
log.Debug("Create default IPv4 IP pool")
createIPPool(client, ipv4Cidr, ipv4IpipModeEnvVar)
outgoingNATEnabled := evaluateENVBool("CALICO_IPV4POOL_NAT_OUTGOING", true)
createIPPool(client, ipv4Cidr, ipv4IpipModeEnvVar, outgoingNATEnabled)
}
if !ipv6Present && ipv6Supported() {
log.Debug("Create default IPv6 IP pool")
createIPPool(client, ipv6Cidr, string(ipip.Undefined))
outgoingNATEnabled := evaluateENVBool("CALICO_IPV6POOL_NAT_OUTGOING", false)

createIPPool(client, ipv6Cidr, string(ipip.Undefined), outgoingNATEnabled)
}
}

Expand All @@ -510,10 +536,9 @@ func configureIPPools(client *client.Client) {
// simplistic check of /proc/sys/net/ipv6 (since platforms that do not have IPv6
// compiled in will not have this entry).
func ipv6Supported() bool {
// First check the Felix parm.
switch strings.ToLower(os.Getenv("FELIX_IPV6SUPPORT")) {
case "false", "0", "no", "n", "f":
log.Info("IPv6 support disabled through environment")
// First check if Felix param is false
IPv6isSupported := evaluateENVBool("FELIX_IPV6SUPPORT", true)
if !IPv6isSupported {
return false
}

Expand All @@ -526,7 +551,7 @@ func ipv6Supported() bool {

// createIPPool creates an IP pool using the specified CIDR. This
// method is a no-op if the pool already exists.
func createIPPool(client *client.Client, cidr *net.IPNet, ipipModeName string) {
func createIPPool(client *client.Client, cidr *net.IPNet, ipipModeName string, isNATOutgoingEnabled bool) {
version := cidr.Version()
ipipMode := ipip.Mode(ipipModeName)

Expand All @@ -540,7 +565,7 @@ func createIPPool(client *client.Client, cidr *net.IPNet, ipipModeName string) {
CIDR: *cidr,
},
Spec: api.IPPoolSpec{
NATOutgoing: true,
NATOutgoing: isNATOutgoingEnabled,
IPIP: &api.IPIPConfiguration{
Enabled: ipipMode != ipip.Undefined,
Mode: ipipMode,
Expand All @@ -563,8 +588,8 @@ func createIPPool(client *client.Client, cidr *net.IPNet, ipipModeName string) {
terminate()
}
} else {
message("Created default IPv%d pool (%s) with NAT outgoing enabled. IPIP mode: %s",
version, cidr, ipipModeName)
message("Created default IPv%d pool (%s) with NAT outgoing %t. IPIP mode: %s",
version, cidr, isNATOutgoingEnabled, ipipModeName)
}
}

Expand Down
45 changes: 35 additions & 10 deletions calico_node/startup/startup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ type EnvItem struct {
}

var _ = Describe("FV tests against a real etcd", func() {
changedEnvVars := []string{"CALICO_IPV4POOL_CIDR", "CALICO_IPV6POOL_CIDR", "NO_DEFAULT_POOLS", "CALICO_IPV4POOL_IPIP"}
changedEnvVars := []string{"CALICO_IPV4POOL_CIDR", "CALICO_IPV6POOL_CIDR", "NO_DEFAULT_POOLS", "CALICO_IPV4POOL_IPIP", "CALICO_IPV6POOL_NAT_OUTGOING", "CALICO_IPV4POOL_NAT_OUTGOING"}

BeforeEach(func() {
for _, envName := range changedEnvVars {
Expand All @@ -83,7 +83,7 @@ var _ = Describe("FV tests against a real etcd", func() {
})

DescribeTable("Test IP pool env variables",
func(envList []EnvItem, expectedIPv4 string, expectedIPv6 string, expectIpv4IpipMode string) {
func(envList []EnvItem, expectedIPv4 string, expectedIPv6 string, expectIpv4IpipMode string, expectedIPV4NATOutgoing bool, expectedIPV6NATOutgoing bool) {
// Create a new client.
cfg, _ := client.LoadClientConfigFromEnvironment()
c := testutils.CreateCleanClient(*cfg)
Expand All @@ -106,6 +106,7 @@ var _ = Describe("FV tests against a real etcd", func() {
// Look through the pool for the expected data.
foundv4Expected := false
foundv6Expected := false

for _, pool := range poolList.Items {
if pool.Metadata.CIDR.String() == expectedIPv4 {
foundv4Expected = true
Expand All @@ -118,6 +119,9 @@ var _ = Describe("FV tests against a real etcd", func() {
if pool.Spec.IPIP != nil {
Expect(pool.Spec.IPIP.Enabled).To(BeFalse())
}

Expect(pool.Spec.NATOutgoing).To(Equal(expectedIPV6NATOutgoing), "Expected IPv6 to be %t but was %t", expectedIPV6NATOutgoing, pool.Spec.NATOutgoing)

} else {
// off is not a real mode value but use it instead of empty string
if expectIpv4IpipMode == "off" {
Expand All @@ -128,6 +132,9 @@ var _ = Describe("FV tests against a real etcd", func() {
Expect(pool.Spec.IPIP.Enabled).To(BeTrue())
Expect(pool.Spec.IPIP.Mode).To(Equal(ipip.Mode(expectIpv4IpipMode)))
}

Expect(pool.Spec.NATOutgoing).To(Equal(expectedIPV4NATOutgoing), "Expected IPv4 to be %t but was %t", expectedIPV4NATOutgoing, pool.Spec.NATOutgoing)

}
}
Expect(foundv4Expected).To(BeTrue(),
Expand All @@ -137,31 +144,49 @@ var _ = Describe("FV tests against a real etcd", func() {
},

Entry("No env variables set", []EnvItem{},
"192.168.0.0/16", "fd80:24e2:f998:72d6::/64", "off"),
"192.168.0.0/16", "fd80:24e2:f998:72d6::/64", "off", true, false),
Entry("IPv4 Pool env var set",
[]EnvItem{{"CALICO_IPV4POOL_CIDR", "172.16.0.0/24"}},
"172.16.0.0/24", "fd80:24e2:f998:72d6::/64", "off"),
"172.16.0.0/24", "fd80:24e2:f998:72d6::/64", "off", true, false),
Entry("IPv6 Pool env var set",
[]EnvItem{{"CALICO_IPV6POOL_CIDR", "fdff:ffff:ffff:ffff:ffff::/80"}},
"192.168.0.0/16", "fdff:ffff:ffff:ffff:ffff::/80", "off"),
"192.168.0.0/16", "fdff:ffff:ffff:ffff:ffff::/80", "off", true, false),
Entry("Both IPv4 and IPv6 Pool env var set",
[]EnvItem{
{"CALICO_IPV4POOL_CIDR", "172.16.0.0/24"},
{"CALICO_IPV6POOL_CIDR", "fdff:ffff:ffff:ffff:ffff::/80"},
},
"172.16.0.0/24", "fdff:ffff:ffff:ffff:ffff::/80", "off"),
"172.16.0.0/24", "fdff:ffff:ffff:ffff:ffff::/80", "off", true, false),
Entry("CALICO_IPV4POOL_IPIP set off", []EnvItem{{"CALICO_IPV4POOL_IPIP", "off"}},
"192.168.0.0/16", "fd80:24e2:f998:72d6::/64", "off"),
"192.168.0.0/16", "fd80:24e2:f998:72d6::/64", "off", true, false),
Entry("CALICO_IPV4POOL_IPIP set always", []EnvItem{{"CALICO_IPV4POOL_IPIP", "always"}},
"192.168.0.0/16", "fd80:24e2:f998:72d6::/64", "always"),
"192.168.0.0/16", "fd80:24e2:f998:72d6::/64", "always", true, false),
Entry("CALICO_IPV4POOL_IPIP set cross-subnet", []EnvItem{{"CALICO_IPV4POOL_IPIP", "cross-subnet"}},
"192.168.0.0/16", "fd80:24e2:f998:72d6::/64", "cross-subnet"),
"192.168.0.0/16", "fd80:24e2:f998:72d6::/64", "cross-subnet", true, false),
Entry("IPv6 Pool and IPIP set",
[]EnvItem{
{"CALICO_IPV6POOL_CIDR", "fdff:ffff:ffff:ffff:ffff::/80"},
{"CALICO_IPV4POOL_IPIP", "always"},
},
"192.168.0.0/16", "fdff:ffff:ffff:ffff:ffff::/80", "always"),
"192.168.0.0/16", "fdff:ffff:ffff:ffff:ffff::/80", "always", true, false),
Entry("IPv6 NATOutgoing Set Enabled",
[]EnvItem{
{"CALICO_IPV6POOL_NAT_OUTGOING", "true"}},
"192.168.0.0/16", "fd80:24e2:f998:72d6::/64", "off", true, true),
Entry("IPv6 NATOutgoing Set Disabled",
[]EnvItem{
{"CALICO_IPV6POOL_NAT_OUTGOING", "false"}},
"192.168.0.0/16", "fd80:24e2:f998:72d6::/64", "off", true, false),
Entry("IPv4 NATOutgoing Set Disabled",
[]EnvItem{
{"CALICO_IPV4POOL_NAT_OUTGOING", "false"}},
"192.168.0.0/16", "fd80:24e2:f998:72d6::/64", "off", false, false),
Entry("IPv6 NAT OUTGOING and IPV4 NAT OUTGOING SET",
[]EnvItem{
{"CALICO_IPV4POOL_NAT_OUTGOING", "false"},
{"CALICO_IPV6POOL_NAT_OUTGOING", "true"},
},
"192.168.0.0/16", "fd80:24e2:f998:72d6::/64", "off", false, true),
)

Describe("Test NO_DEFAULT_POOLS env variable", func() {
Expand Down
59 changes: 32 additions & 27 deletions calico_node/tests/st/calicoctl/test_default_pools.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,33 +49,33 @@ def tearDownClass(cls):
cls.host.cleanup()

@parameterized.expand([
(False, "CALICO_IPV4POOL_CIDR", "10.0.0.0/27", 0, None, "Too small"),
(False, "CALICO_IPV4POOL_CIDR", "10.0.0.0/32", 0, None, "Too small, but legal CIDR"),
(False, "CALICO_IPV4POOL_CIDR", "10.0.0.0/33", 0, None, "Impossible CIDR"),
(False, "CALICO_IPV4POOL_CIDR", "256.0.0.0/24", 0, None, "Invalid IP"),
(True, "CALICO_IPV4POOL_CIDR", "10.0.0.0/24", 2, None, "Typical non-default pool"),
(True, "CALICO_IPV4POOL_CIDR", "10.0.0.0/26", 2, None, "Smallest legal pool"),
(True, "CALICO_IPV6POOL_CIDR", "fd00::/122", 2, None, "Smallest legal pool"),
(False, "CALICO_IPV6POOL_CIDR", "fd00::/123", 0, None, "Too small"),
(False, "CALICO_IPV6POOL_CIDR", "fd00::/128", 0, None, "Too small, but legal CIDR"),
(False, "CALICO_IPV6POOL_CIDR", "fd00::/129", 0, None, "Impossible CIDR"),
(True, "CALICO_IPV4POOL_CIDR", "10.0.0.0/24", 2, "cross-subnet", "Typ. non-def pool, IPIP"),
(True, "CALICO_IPV4POOL_CIDR", "10.0.0.0/24", 2, "always", "Typ. non-default pool, IPIP"),
(True, "CALICO_IPV4POOL_CIDR", "10.0.0.0/24", 2, "off", "Typical pool, explicitly no IPIP"),
(True, "CALICO_IPV6POOL_CIDR", "fd00::/122", 2, "always", "IPv6 - IPIP not permitted"),
(True, "CALICO_IPV6POOL_CIDR", "fd00::/122", 2, "cross-subnet", "IPv6 - IPIP not allowed"),
(True, "CALICO_IPV6POOL_CIDR", "fd00::/122", 2, "off", "IPv6, IPIP explicitly off"),
(False, "CALICO_IPV6POOL_CIDR", "fd00::/122", 0, "junk", "Invalid IPIP value"),
(False, "CALICO_IPV4POOL_CIDR", "10.0.0.0/24", 0, "reboot", "Invalid IPIP value"),
(False, "CALICO_IPV4POOL_CIDR", "0.0.0.0/0", 0, None, "Invalid, link local address"),
(False, "CALICO_IPV6POOL_CIDR", "::/0", 0, None, "Invalid, link local address"),
(True, "CALICO_IPV6POOL_CIDR", "fd80::0:0/120", 2, None, "Valid, but non-canonical form"),
(False, "CALICO_IPV6POOL_CIDR", "1.2.3.4/24", 0, None, "Wrong type"),
(False, "CALICO_IPV4POOL_CIDR", "fd00::/24", 0, None, "Wrong type"),
(True, "CALICO_IPV6POOL_CIDR", "::0:a:b:c:d:e:0/120", 2, None, "Valid, non-canonical form"),
(False, "CALICO_IPV4POOL_CIDR", "1.2/16", 0, None, "Valid, unusual form"),
(False, "CALICO_IPV4POOL_CIDR", "10.0.0.0/27", 0, None, True, "Too small"),
(False, "CALICO_IPV4POOL_CIDR", "10.0.0.0/32", 0, None, True, "Too small, but legal CIDR"),
(False, "CALICO_IPV4POOL_CIDR", "10.0.0.0/33", 0, None, True, "Impossible CIDR"),
(False, "CALICO_IPV4POOL_CIDR", "256.0.0.0/24", 0, None, True, "Invalid IP"),
(True, "CALICO_IPV4POOL_CIDR", "10.0.0.0/24", 2, None, True, "Typical non-default pool"),
(True, "CALICO_IPV4POOL_CIDR", "10.0.0.0/26", 2, None, True, "Smallest legal pool"),
(True, "CALICO_IPV6POOL_CIDR", "fd00::/122", 2, None, False, "Smallest legal pool"),
(False, "CALICO_IPV6POOL_CIDR", "fd00::/123", 0, None, False, "Too small"),
(False, "CALICO_IPV6POOL_CIDR", "fd00::/128", 0, None, False, "Too small, but legal CIDR"),
(False, "CALICO_IPV6POOL_CIDR", "fd00::/129", 0, None, False, "Impossible CIDR"),
(True, "CALICO_IPV4POOL_CIDR", "10.0.0.0/24", 2, "cross-subnet", True,"Typ. non-def pool, IPIP"),
(True, "CALICO_IPV4POOL_CIDR", "10.0.0.0/24", 2, "always", True,"Typ. non-default pool, IPIP"),
(True, "CALICO_IPV4POOL_CIDR", "10.0.0.0/24", 2, "off", True, "Typical pool, explicitly no IPIP"),
(True, "CALICO_IPV6POOL_CIDR", "fd00::/122", 2, "always", False, "IPv6 - IPIP not permitted"),
(True, "CALICO_IPV6POOL_CIDR", "fd00::/122", 2, "cross-subnet", False, "IPv6 - IPIP not allowed"),
(True, "CALICO_IPV6POOL_CIDR", "fd00::/122", 2, "off", False, "IPv6, IPIP explicitly off"),
(False, "CALICO_IPV6POOL_CIDR", "fd00::/122", 0, "junk", False, "Invalid IPIP value"),
(False, "CALICO_IPV4POOL_CIDR", "10.0.0.0/24", 0, "reboot", True, "Invalid IPIP value"),
(False, "CALICO_IPV4POOL_CIDR", "0.0.0.0/0", 0, None, True, "Invalid, link local address"),
(False, "CALICO_IPV6POOL_CIDR", "::/0", 0, None, False, "Invalid, link local address"),
(True, "CALICO_IPV6POOL_CIDR", "fd80::0:0/120", 2, None, False, "Valid, but non-canonical form"),
(False, "CALICO_IPV6POOL_CIDR", "1.2.3.4/24", 0, None, False, "Wrong type"),
(False, "CALICO_IPV4POOL_CIDR", "fd00::/24", 0, None, True, "Wrong type"),
(True, "CALICO_IPV6POOL_CIDR", "::0:a:b:c:d:e:0/120", 2, None, False, "Valid, non-canonical form"),
(False, "CALICO_IPV4POOL_CIDR", "1.2/16", 0, None, True, "Valid, unusual form"),
])
def test_default_pools(self, success_expected, param, value, exp_num_pools, ipip, description):
def test_default_pools(self, success_expected, param, value, exp_num_pools, ipip, nat_outgoing, description):
"""
Test that the various options for default pools work correctly
"""
Expand Down Expand Up @@ -138,7 +138,12 @@ def test_default_pools(self, success_expected, param, value, exp_num_pools, ipip
"Didn't find ipip mode in pool %s" % pool

# Check NAT setting
assert pool['spec']['nat-outgoing'] is True, "Didn't find nat enabled in pool %s" % pool
if 'nat-outgoing' in pool['spec']:
assert pool['spec']['nat-outgoing'] is nat_outgoing, \
"Wrong NAT default in pool %s, expected nat-outgoing to be %s" % (pool, nat_outgoing)
else:
assert nat_outgoing is False, \
"Wrong NAT default in pool %s, expecting nat-outgoing to be disabled" % pool

def test_no_default_pools(self):
"""
Expand Down

0 comments on commit 4f65624

Please sign in to comment.