Skip to content

Commit

Permalink
adding no_proxy env variable by default to each clab node (#2351)
Browse files Browse the repository at this point in the history
* 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 <dodin.roman@gmail.com>
  • Loading branch information
toweber and hellt authored Dec 20, 2024
1 parent 9fe5485 commit 0077e9f
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 6 deletions.
76 changes: 71 additions & 5 deletions clab/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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
}
12 changes: 12 additions & 0 deletions docs/manual/nodes.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
18 changes: 17 additions & 1 deletion tests/01-smoke/01-basic-flow.robot
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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}
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 0077e9f

Please sign in to comment.