From 5132320f3a991dedc2c5731216c960e5c38c8a36 Mon Sep 17 00:00:00 2001 From: Roman Dodin Date: Tue, 14 Jan 2025 22:55:40 +0100 Subject: [PATCH] Create labdir next to clab file (#2394) * create labdir next to clab file * fix clabNodeDir bind resolver * fix test labels init * fix paths for 02 test * fix paths * fix paths * fix paths --- .gitignore | 4 ++ clab/config.go | 2 +- clab/config_test.go | 64 +++++------------------- clab/test_data/clab-topo2/node1/somefile | 0 docs/cmd/deploy.md | 2 +- docs/manual/conf-artifacts.md | 18 +++---- tests/01-smoke/02-destroy-all.robot | 8 +-- tests/01-smoke/09-external-ca.robot | 6 +-- tests/01-smoke/10-ca-parameter.robot | 16 +++--- tests/02-basic-srl/01-two-srls.robot | 4 +- tests/03-basic-ceos/01-two-ceos.robot | 6 +-- types/topo_paths.go | 7 +-- 12 files changed, 49 insertions(+), 88 deletions(-) create mode 100644 clab/test_data/clab-topo2/node1/somefile diff --git a/.gitignore b/.gitignore index 4485f6f1c..bc0b2e662 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,7 @@ tests/out .python-version .devcontainer/private-* + + +# readd test labDir files +!clab/test_data/clab-* \ No newline at end of file diff --git a/clab/config.go b/clab/config.go index afd2d09e7..f8c020c38 100644 --- a/clab/config.go +++ b/clab/config.go @@ -239,7 +239,7 @@ func (c *CLab) createNodeCfg(nodeName string, nodeDef *types.NodeDefinition, idx if err != nil { return nil, err } - err = c.resolveBindPaths(binds, nodeCfg.LabDir) + err = c.resolveBindPaths(binds, c.TopoPaths.NodeDir(nodeName)) if err != nil { return nil, err } diff --git a/clab/config_test.go b/clab/config_test.go index 629247287..6ca9b6109 100644 --- a/clab/config_test.go +++ b/clab/config_test.go @@ -24,21 +24,6 @@ import ( "go.uber.org/mock/gomock" ) -func setupTestCase(t *testing.T) func(t *testing.T) { - // setup function - // create node' labdir with a file that is used in topo2 definition for binds resolver to check path existence - f, _ := filepath.Abs("clab-topo2/node1/somefile") - os.MkdirAll("clab-topo2/node1", 0777) // skipcq: GSC-G301 - - if _, err := os.Create(f); err != nil { - t.Error(err) - } - // teardown function - return func(t *testing.T) { - os.RemoveAll("clab-topo2") - } -} - func TestLicenseInit(t *testing.T) { tests := map[string]struct { got string @@ -62,9 +47,6 @@ func TestLicenseInit(t *testing.T) { }, } - teardownTestCase := setupTestCase(t) - defer teardownTestCase(t) - for name, tc := range tests { t.Run(name, func(t *testing.T) { opts := []ClabOption{ @@ -96,7 +78,7 @@ func TestBindsInit(t *testing.T) { want: []string{ "node1.lic:/dst1", "kind.lic:/dst2", - "${PWD}/clab-topo2/node1/somefile:/somefile", + "${PWD}/test_data/clab-topo2/node1/somefile:/somefile", }, }, "kind_and_node_binds": { @@ -113,9 +95,6 @@ func TestBindsInit(t *testing.T) { }, } - teardownTestCase := setupTestCase(t) - defer teardownTestCase(t) - for name, tc := range tests { t.Run(name, func(t *testing.T) { opts := []ClabOption{ @@ -174,9 +153,6 @@ func TestTypeInit(t *testing.T) { }, } - teardownTestCase := setupTestCase(t) - defer teardownTestCase(t) - for name, tc := range tests { t.Run(name, func(t *testing.T) { opts := []ClabOption{ @@ -250,9 +226,6 @@ func TestEnvInit(t *testing.T) { }, } - teardownTestCase := setupTestCase(t) - defer teardownTestCase(t) - for name, tc := range tests { t.Run(name, func(t *testing.T) { for k, v := range tc.envvar { @@ -307,9 +280,6 @@ func TestUserInit(t *testing.T) { }, } - teardownTestCase := setupTestCase(t) - defer teardownTestCase(t) - for name, tc := range tests { t.Run(name, func(t *testing.T) { opts := []ClabOption{ @@ -346,9 +316,6 @@ func TestVerifyLinks(t *testing.T) { }, } - teardownTestCase := setupTestCase(t) - defer teardownTestCase(t) - ctx := context.Background() for name, tc := range tests { @@ -382,6 +349,10 @@ func TestVerifyLinks(t *testing.T) { } func TestLabelsInit(t *testing.T) { + owner := os.Getenv("SUDO_USER") + if owner == "" { + owner = os.Getenv("USER") + } tests := map[string]struct { got string node string @@ -396,9 +367,9 @@ func TestLabelsInit(t *testing.T) { labels.NodeKind: "nokia_srlinux", labels.NodeType: "ixrd2l", labels.NodeGroup: "", - labels.NodeLabDir: "../clab-topo1/node1", + labels.NodeLabDir: "./clab-topo1/node1", labels.TopoFile: "topo1.yml", - labels.Owner: "runner", + labels.Owner: owner, }, }, "custom_node_label": { @@ -410,10 +381,10 @@ func TestLabelsInit(t *testing.T) { labels.NodeKind: "nokia_srlinux", labels.NodeType: "ixrd2l", labels.NodeGroup: "", - labels.NodeLabDir: "../clab-topo1/node2", + labels.NodeLabDir: "./clab-topo1/node2", labels.TopoFile: "topo1.yml", "node-label": "value", - labels.Owner: "runner", + labels.Owner: owner, }, }, "custom_kind_label": { @@ -425,10 +396,10 @@ func TestLabelsInit(t *testing.T) { labels.NodeKind: "nokia_srlinux", labels.NodeType: "ixrd2l", labels.NodeGroup: "", - labels.NodeLabDir: "../clab-topo2/node1", + labels.NodeLabDir: "./clab-topo2/node1", labels.TopoFile: "topo2.yml", "kind-label": "value", - labels.Owner: "runner", + labels.Owner: owner, }, }, "custom_default_label": { @@ -440,17 +411,14 @@ func TestLabelsInit(t *testing.T) { labels.NodeKind: "nokia_srlinux", labels.NodeType: "ixrd2l", labels.NodeGroup: "", - labels.NodeLabDir: "../clab-topo3/node2", + labels.NodeLabDir: "./clab-topo3/node2", labels.TopoFile: "topo3.yml", "default-label": "value", - labels.Owner: "runner", + labels.Owner: owner, }, }, } - teardownTestCase := setupTestCase(t) - defer teardownTestCase(t) - for name, tc := range tests { t.Run(name, func(t *testing.T) { opts := []ClabOption{ @@ -663,9 +631,6 @@ func TestEnvFileInit(t *testing.T) { }, } - teardownTestCase := setupTestCase(t) - defer teardownTestCase(t) - for name, tc := range tests { t.Run(name, func(t *testing.T) { opts := []ClabOption{ @@ -755,9 +720,6 @@ func TestStartupConfigInit(t *testing.T) { }, } - teardownTestCase := setupTestCase(t) - defer teardownTestCase(t) - for name, tc := range tests { t.Run(name, func(t *testing.T) { opts := []ClabOption{ diff --git a/clab/test_data/clab-topo2/node1/somefile b/clab/test_data/clab-topo2/node1/somefile new file mode 100644 index 000000000..e69de29bb diff --git a/docs/cmd/deploy.md b/docs/cmd/deploy.md index 55e4cfadc..34cd92562 100644 --- a/docs/cmd/deploy.md +++ b/docs/cmd/deploy.md @@ -166,7 +166,7 @@ Example command-line usage: `CLAB_VERSION_CHECK=disable containerlab deploy` To change the [lab directory](../manual/conf-artifacts.md#identifying-a-lab-directory) location, set `CLAB_LABDIR_BASE` environment variable accordingly. It denotes the base directory in which the lab directory will be created. -The default behavior is to create the lab directory in the current working dir. +The default behavior is to create the lab directory in the same directory as the topology file (`clab.yml` file). ### Examples diff --git a/docs/manual/conf-artifacts.md b/docs/manual/conf-artifacts.md index 40b986324..bb43440f4 100644 --- a/docs/manual/conf-artifacts.md +++ b/docs/manual/conf-artifacts.md @@ -1,4 +1,6 @@ -When containerlab deploys a lab it creates a Lab Directory in the **current working directory**. This directory is used to keep all the necessary files that are needed to run/configure the nodes. We call these files _configuration artifacts_. +# Lab Directory and Configuration Artifacts + +When containerlab deploys a lab it creates a Lab Directory in the same directory where your topology (`clab.yml`) file is. This directory is used to keep all the necessary files that are needed to run/configure the nodes. We call these files _configuration artifacts_ and/or lab state files. Things like: @@ -7,15 +9,11 @@ Things like: * node-specific files and directories that are required to launch the container * license files if needed -all these artifacts will be available under a Lab Directory. - -!!!note - If you configure a node with [`binds`](nodes.md#binds) mounts and the source of the bind is not within the lab directory already, containerlab will copy over the source files/dirs into the lab directory on users behalf. - -### Identifying a lab directory +All these artifacts will be available under a Lab Directory. -The lab directory name follows the `clab-` template. Thus, if the name of your lab is `srl02` you will find the `clab-srl02` directory created by default in the current working directory. The location can be altered via the [CLAB_LABDIR_BASE](../cmd/deploy.md#clab_labdir_base) envorinment variable. +## Identifying a Lab Directory +The lab directory name follows the `clab-` template. Thus, if the name of your lab is `srl02` you will find the `clab-srl02` directory created by default in the directory where topology file is located. The location can be changed by setting the [`CLAB_LABDIR_BASE`](../cmd/deploy.md#clab_labdir_base) environment variable. ``` ❯ ls -lah clab-srl02 @@ -29,7 +27,7 @@ drwxr-xr-x 3 root root 79 Dec 1 22:11 srl2 The contents of this directory will contain kind-specific files and directories. Containerlab will name directories after the node names and will only created those if they are needed. For instance, by default any node of kind `linux` will not have it's own directory under the Lab Directory. -### Persistence of a lab directory +### Persistence of a Lab Directory When a user first deploy a lab, the Lab Directory gets created if it was not present. Depending on a node's kind, this directory might act as a persistent storage area for a node. A common case is having the configuration file saved when the changes are made to the node via management interfaces. @@ -48,4 +46,4 @@ When a user destroys a lab without providing the [`--cleanup`](../cmd/destroy.md Moreover, when the user will deploy the same lab, containerlab will reuse the configuration artifacts if possible, which will, for example, start the nodes with the config files saved from the previous lab run. -To be able to deploy a lab without reusing existing configuration artifact use the [`--reconfigure`](../cmd/deploy.md#reconfigure) flag with `deploy` command. With that setting, containerlab will first delete the Lab Directory and then will start the deployment process. +To be able to deploy a lab without reusing existing configuration artifact use the [`redeploy`](../cmd/redeploy.md) command with `--cleanup` or add [`--reconfigure`](../cmd/deploy.md#reconfigure) flag to the `deploy` command. With that setting, containerlab will first delete the Lab Directory and then will start the deployment process. diff --git a/tests/01-smoke/02-destroy-all.robot b/tests/01-smoke/02-destroy-all.robot index 6b7eca346..40cef14c1 100644 --- a/tests/01-smoke/02-destroy-all.robot +++ b/tests/01-smoke/02-destroy-all.robot @@ -30,7 +30,7 @@ Deploy first lab Log ${result.stdout} Log ${result.stderr} Should Be Equal As Integers ${result.rc} 0 - Should Exist %{PWD}/clab-2-linux-nodes + Should Exist ${CURDIR}/clab-2-linux-nodes Set Suite Variable ${orig_dir} ${CURDIR} @@ -42,7 +42,7 @@ Deploy second lab Log ${result.stdout} Log ${result.stderr} Should Be Equal As Integers ${result.rc} 0 - Should Exist /tmp/clab-single-node + Should Exist ${CURDIR}/clab-single-node Inspect ${lab2-name} lab using its name ${rc} ${output} = Run And Return Rc And Output @@ -102,7 +102,7 @@ Redeploy second lab Log ${result.stdout} Log ${result.stderr} Should Be Equal As Integers ${result.rc} 0 - Should Exist /tmp/clab-single-node + Should Exist ${CURDIR}/clab-single-node Destroy all labs ${rc} ${output} = Run And Return Rc And Output @@ -116,4 +116,4 @@ Check all labs have been removed Log ${output} Should Contain ${output} no containers found Should Not Exist /tmp/single-node - Should Not Exist %{PWD}/clab-2-linux-nodes + Should Not Exist ${CURDIR}/clab-2-linux-nodes diff --git a/tests/01-smoke/09-external-ca.robot b/tests/01-smoke/09-external-ca.robot index af09d3049..796502f1f 100644 --- a/tests/01-smoke/09-external-ca.robot +++ b/tests/01-smoke/09-external-ca.robot @@ -16,8 +16,8 @@ ${ca-keylength} 2048 ${runtime} docker # Node based certs files -${l1-key} ./clab-${lab-name}/.tls/l1/l1.key -${l1-cert} ./clab-${lab-name}/.tls/l1/l1.pem +${l1-key} ${CURDIR}/clab-${lab-name}/.tls/l1/l1.key +${l1-cert} ${CURDIR}/clab-${lab-name}/.tls/l1/l1.pem *** Test Cases *** @@ -64,7 +64,7 @@ Review Node l1 Certificate Should Contain ${output} Issuer: L = Internet, O = srl-labs, OU = Containerlab, CN = containerlab.dev Should Contain ${output} Public-Key: (2048 bit) -Verfiy node cert with CA Cert +Verify node cert with CA Cert ${rc} ${output} = Run And Return Rc And Output ... openssl verify -CAfile ${ca-cert-file} ${l1-cert} Log ${output} diff --git a/tests/01-smoke/10-ca-parameter.robot b/tests/01-smoke/10-ca-parameter.robot index fede4913c..e29e96d4c 100644 --- a/tests/01-smoke/10-ca-parameter.robot +++ b/tests/01-smoke/10-ca-parameter.robot @@ -17,14 +17,14 @@ ${l2-keysize} 1024 ${ca-validity-duration} 5 hours # cert files -${ca-cert-key} ./clab-${lab-name}/.tls/ca/ca.key -${ca-cert-file} ./clab-${lab-name}/.tls/ca/ca.pem -${l1-key} ./clab-${lab-name}/.tls/l1/l1.key -${l1-cert} ./clab-${lab-name}/.tls/l1/l1.pem -${l2-key} ./clab-${lab-name}/.tls/l2/l2.key -${l2-cert} ./clab-${lab-name}/.tls/l2/l2.pem -${l3-key} ./clab-${lab-name}/.tls/l3/l3.key -${l3-cert} ./clab-${lab-name}/.tls/l3/l3.pem +${ca-cert-key} ${CURDIR}/clab-${lab-name}/.tls/ca/ca.key +${ca-cert-file} ${CURDIR}/clab-${lab-name}/.tls/ca/ca.pem +${l1-key} ${CURDIR}/clab-${lab-name}/.tls/l1/l1.key +${l1-cert} ${CURDIR}/clab-${lab-name}/.tls/l1/l1.pem +${l2-key} ${CURDIR}/clab-${lab-name}/.tls/l2/l2.key +${l2-cert} ${CURDIR}/clab-${lab-name}/.tls/l2/l2.pem +${l3-key} ${CURDIR}/clab-${lab-name}/.tls/l3/l3.key +${l3-cert} ${CURDIR}/clab-${lab-name}/.tls/l3/l3.pem *** Test Cases *** diff --git a/tests/02-basic-srl/01-two-srls.robot b/tests/02-basic-srl/01-two-srls.robot index 1f9b1e768..0e2592413 100644 --- a/tests/02-basic-srl/01-two-srls.robot +++ b/tests/02-basic-srl/01-two-srls.robot @@ -133,14 +133,14 @@ Verify TLS works with JSON-RPC with skipping certificate check Verify TLS works with JSON-RPC and certificate check ${rc} ${output} = Run And Return Rc And Output - ... curl --cacert ./clab-${lab-name}/.tls/ca/ca.pem 'https://admin:NokiaSrl1!@clab-${lab-name}-srl1/jsonrpc' -d '{"jsonrpc":"2.0","id":0,"method":"get","params":{"commands":[{"path":"/system/information/version","datastore":"state"}]}}' + ... curl --cacert ${CURDIR}/clab-${lab-name}/.tls/ca/ca.pem 'https://admin:NokiaSrl1!@clab-${lab-name}-srl1/jsonrpc' -d '{"jsonrpc":"2.0","id":0,"method":"get","params":{"commands":[{"path":"/system/information/version","datastore":"state"}]}}' Log ${output} Should Be Equal As Integers ${rc} 0 Should Not Contain ${output} error Verify TLS works with JSON-RPC, certificate check and IP address as SAN ${rc} ${output} = Run And Return Rc And Output - ... curl --cacert ./clab-${lab-name}/.tls/ca/ca.pem 'https://admin:NokiaSrl1!@172.20.20.200/jsonrpc' -d '{"jsonrpc":"2.0","id":0,"method":"get","params":{"commands":[{"path":"/system/information/version","datastore":"state"}]}}' + ... curl --cacert ${CURDIR}/clab-${lab-name}/.tls/ca/ca.pem 'https://admin:NokiaSrl1!@172.20.20.200/jsonrpc' -d '{"jsonrpc":"2.0","id":0,"method":"get","params":{"commands":[{"path":"/system/information/version","datastore":"state"}]}}' Log ${output} Should Be Equal As Integers ${rc} 0 Should Not Contain ${output} error diff --git a/tests/03-basic-ceos/01-two-ceos.robot b/tests/03-basic-ceos/01-two-ceos.robot index 0e77c3106..97d2f3400 100644 --- a/tests/03-basic-ceos/01-two-ceos.robot +++ b/tests/03-basic-ceos/01-two-ceos.robot @@ -36,18 +36,18 @@ Get nodes mgmt IPs Should Be Equal As Strings ${inspected-n2-mgmt-ip} ${n2-mgmt-ip} Ensure n1 mgmt IPv4 is in the config file - ${f} = OperatingSystem.Get File ${EXECDIR}/clab-${lab-name}/${node1-name}/flash/startup-config + ${f} = OperatingSystem.Get File ${CURDIR}/clab-${lab-name}/${node1-name}/flash/startup-config Log ${f} Log ${n1-mgmt-ip} Should Contain ${f} ${n1-mgmt-ip} Ensure n2 mgmt IPv4 is in the config file - ${f} = OperatingSystem.Get File ${EXECDIR}/clab-${lab-name}/${node2-name}/flash/startup-config + ${f} = OperatingSystem.Get File ${CURDIR}/clab-${lab-name}/${node2-name}/flash/startup-config Log ${f} Should Contain ${f} ${n2-mgmt-ip} Ensure IPv6 default route is in the config file - ${f} = OperatingSystem.Get File ${EXECDIR}/clab-${lab-name}/${node1-name}/flash/startup-config + ${f} = OperatingSystem.Get File ${CURDIR}/clab-${lab-name}/${node1-name}/flash/startup-config Log ${f} Should Contain ${f} ipv6 route diff --git a/types/topo_paths.go b/types/topo_paths.go index b8513797b..7078e5bb7 100644 --- a/types/topo_paths.go +++ b/types/topo_paths.go @@ -80,13 +80,10 @@ func (t *TopoPaths) SetLabDir(p string) (err error) { func (t *TopoPaths) SetLabDirByPrefix(topologyName string) (err error) { t.topoName = topologyName // if "CLAB_LABDIR_BASE" Env Var is set, use that dir as a base - // for the labDir, otherwise use PWD. + // for the labDir, otherwise use dir where topology clab file is. baseDir := os.Getenv("CLAB_LABDIR_BASE") if baseDir == "" { - baseDir, err = os.Getwd() - if err != nil { - return err - } + baseDir = t.TopologyFileDir() } // construct the path t.labDir = path.Join(baseDir, labDirPrefix+topologyName)