From 0077e9f6c7a95fef246a7a1db5b6c161693a50cd Mon Sep 17 00:00:00 2001 From: Tobias Weber <23548161+toweber@users.noreply.github.com> Date: Fri, 20 Dec 2024 21:56:13 +0100 Subject: [PATCH] adding no_proxy env variable by default to each clab node (#2351) * adding no_proxy env variable by default to each clab node * formatting * Add mgmt subnet range to no_proxy var * Add mgmt subnet to no_proxy if not empty * make format * move to a func and add a test * fix contain condition * doc entry --------- Co-authored-by: toweber <> Co-authored-by: Roman Dodin --- clab/config.go | 76 ++++++++++++++++++++++++++++-- docs/manual/nodes.md | 12 +++++ tests/01-smoke/01-basic-flow.robot | 18 ++++++- 3 files changed, 100 insertions(+), 6 deletions(-) diff --git a/clab/config.go b/clab/config.go index 04e62160f..6116b320c 100644 --- a/clab/config.go +++ b/clab/config.go @@ -211,14 +211,11 @@ func (c *CLab) createNodeCfg(nodeName string, nodeDef *types.NodeDefinition, idx return nil, err } - // Load content of the EnvVarFiles - envFileContent, err := utils.LoadEnvVarFiles(c.TopoPaths.TopologyFileDir(), - c.Config.Topology.GetNodeEnvFiles(nodeName)) + // load environment variables + err = addEnvVarsToNodeCfg(c, nodeCfg) if err != nil { return nil, err } - // Merge EnvVarFiles content and the existing env variable - nodeCfg.Env = utils.MergeStringMaps(envFileContent, nodeCfg.Env) log.Debugf("node config: %+v", nodeCfg) @@ -581,3 +578,72 @@ func labelsToEnvVars(n *types.NodeConfig) { n.Env["CLAB_LABEL_"+utils.ToEnvKey(k)] = v } } + +// addEnvVarsToNodeCfg adds env vars that come from different sources to node config struct +func addEnvVarsToNodeCfg(c *CLab, nodeCfg *types.NodeConfig) error { + // Load content of the EnvVarFiles + envFileContent, err := utils.LoadEnvVarFiles(c.TopoPaths.TopologyFileDir(), + c.Config.Topology.GetNodeEnvFiles(nodeCfg.ShortName)) + if err != nil { + return err + } + // Merge EnvVarFiles content and the existing env variable + nodeCfg.Env = utils.MergeStringMaps(envFileContent, nodeCfg.Env) + + // Default set of no_proxy entries + noProxyDefaults := []string{"localhost", "127.0.0.1", "::1", "*.local"} + + // check if either of the no_proxy variables exists + noProxyLower, existsLower := nodeCfg.Env["no_proxy"] + noProxyUpper, existsUpper := nodeCfg.Env["NO_PROXY"] + noProxy := "" + if existsLower { + noProxy = noProxyLower + for _, defaultValue := range noProxyDefaults { + if !strings.Contains(noProxy, defaultValue) { + noProxy = noProxy + "," + defaultValue + } + } + } else if existsUpper { + noProxy = noProxyUpper + for _, defaultValue := range noProxyDefaults { + if !strings.Contains(noProxy, defaultValue) { + noProxy = noProxy + "," + defaultValue + } + } + } else { + noProxy = strings.Join(noProxyDefaults, ",") + } + + // add all clab nodes to the no_proxy variable, if they have a static IP assigned, add this as well + var noProxyList []string + for key := range c.Config.Topology.Nodes { + noProxyList = append(noProxyList, key) + ipv4address := c.Config.Topology.Nodes[key].GetMgmtIPv4() + if ipv4address != "" { + noProxyList = append(noProxyList, ipv4address) + } + ipv6address := c.Config.Topology.Nodes[key].GetMgmtIPv6() + if ipv6address != "" { + noProxyList = append(noProxyList, ipv6address) + } + } + + // add mgmt subnet range for the sake of completeness - some OS support it, others don't + if c.Config.Mgmt.IPv4Subnet != "" { + noProxyList = append(noProxyList, c.Config.Mgmt.IPv4Subnet) + } + if c.Config.Mgmt.IPv6Subnet != "" { + noProxyList = append(noProxyList, c.Config.Mgmt.IPv6Subnet) + } + + // sort for better readability + sort.Strings(noProxyList) + + noProxy = noProxy + "," + strings.Join(noProxyList, ",") + + nodeCfg.Env["no_proxy"] = noProxy + nodeCfg.Env["NO_PROXY"] = noProxy + + return nil +} diff --git a/docs/manual/nodes.md b/docs/manual/nodes.md index d1923c6fc..d85f425bc 100644 --- a/docs/manual/nodes.md +++ b/docs/manual/nodes.md @@ -345,6 +345,18 @@ topology: You can also specify a magic ENV VAR - `__IMPORT_ENVS: true` - which will import all environment variables defined in your shell to the relevant topology level. +/// admonition | `NO_PROXY` variable + type: subtle-note +If you use an http(s) proxy on your host, you typically set the `NO_PROXY` environment variable in your containers to ensure that when containers talk to one another, they don't send traffic through the proxy, as that would lead to broken communication. And setting those env vars is tedious. + +Containerlab automates this process by automatically setting `NO_PROXY`/`no_proxy` environment variables in the containerlab nodes with the values of: + +1. localhost,127.0.0.1,::1,*.local +2. management network range for v4 and v6 (e.g. `172.20.20.0/24`) +3. IPv4/IPv6 management addresses of the nodes of the lab +4. node names as stated in your topology file +/// + ### env-files To add environment variables defined in a file use the `env-files` property that can be defined at `defaults`, `kind` and `node` levels. diff --git a/tests/01-smoke/01-basic-flow.robot b/tests/01-smoke/01-basic-flow.robot index eeccc2254..61ac8c263 100644 --- a/tests/01-smoke/01-basic-flow.robot +++ b/tests/01-smoke/01-basic-flow.robot @@ -18,6 +18,7 @@ ${n2-ipv4} 172.20.20.100/24 ${n2-ipv6} 3fff:172:20:20::100/64 ${table-delimit} │ + *** Test Cases *** Verify number of Hosts entries before deploy ${rc} ${output} = Run And Return Rc And Output @@ -98,6 +99,21 @@ Ensure CLAB_INTFS env var is set # the result is printed today. Should Contain ${output.stderr} stdout:\\n3 +Ensure default no_proxy env var is set + [Documentation] + ... This test ensures that the NO_PROXY env var is populated by clab automatically + ... with the relevant addresses and names + ${output} = Process.Run Process + ... sudo -E ${CLAB_BIN} --runtime ${runtime} exec -t ${CURDIR}/${lab-file} --label clab-node-name\=l1 --cmd 'ash -c "echo $NO_PROXY"' + ... shell=True + Log ${output.stdout} + Log ${output.stderr} + Should Be Equal As Integers ${output.rc} 0 + + Should Contain + ... ${output.stderr} + ... localhost,127.0.0.1,::1,*.local,172.20.20.0/24,172.20.20.100,172.20.20.99,3fff:172:20:20::/64,3fff:172:20:20::100,3fff:172:20:20::99,l1,l2,l3 + Inspect ${lab-name} lab using its name ${rc} ${output} = Run And Return Rc And Output ... sudo -E ${CLAB_BIN} --runtime ${runtime} inspect --name ${lab-name} @@ -190,7 +206,7 @@ Ensure "inspect all" outputs IP addresses ... sudo -E ${CLAB_BIN} --runtime ${runtime} inspect --all Log ${output} Should Be Equal As Integers ${rc} 0 - + # get a 4th line from the bottom of the inspect cmd. # this relates to the l2 node ipv4 ${line} = String.Get Line ${output} -6