From 970f055ff8059ce90dc51e4dc6251becd263241d Mon Sep 17 00:00:00 2001 From: steiler Date: Thu, 11 Apr 2024 08:21:52 +0200 Subject: [PATCH 1/8] inspect: fixes all, by name and topology file --- cmd/inspect.go | 48 +++++++++++++++++++++--------------------------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/cmd/inspect.go b/cmd/inspect.go index 37607a6c5..78fcbade6 100644 --- a/cmd/inspect.go +++ b/cmd/inspect.go @@ -73,43 +73,37 @@ func inspectFn(_ *cobra.Command, _ []string) error { ) } - if name != "" { - opts = append(opts, clab.WithLabName(name)) - } - c, err := clab.NewContainerLab(opts...) if err != nil { return fmt.Errorf("could not parse the topology file: %v", err) } var containers []runtime.GenericContainer + var glabels []*types.GenericFilter // if the topo file is available, use it if topo != "" { - containers, err = c.ListContainers(ctx, nil) - if err != nil { - return fmt.Errorf("failed to list containers: %s", err) - } + name = c.Config.Name + } + + // or when just the name is given + if name != "" { + // if name is set, filter for name + glabels = []*types.GenericFilter{{ + FilterType: "label", Match: name, + Field: labels.Containerlab, Operator: "=", + }} } else { - var glabels []*types.GenericFilter - // or when just the name is given - if name != "" { - // if name is set, filter for name - glabels = []*types.GenericFilter{{ - FilterType: "label", Match: name, - Field: labels.Containerlab, Operator: "=", - }} - } else { - // this is the --all case - glabels = []*types.GenericFilter{{ - FilterType: "label", - Field: labels.Containerlab, Operator: "exists", - }} - } - containers, err = c.ListContainers(ctx, glabels) - if err != nil { - return fmt.Errorf("failed to list containers: %s", err) - } + // this is the --all case + glabels = []*types.GenericFilter{{ + FilterType: "label", + Field: labels.Containerlab, Operator: "exists", + }} + } + + containers, err = c.ListContainers(ctx, glabels) + if err != nil { + return fmt.Errorf("failed to list containers: %s", err) } if len(containers) == 0 { From 5eef9d3596a45e4ac1915992e8285a063f2492b0 Mon Sep 17 00:00:00 2001 From: steiler Date: Thu, 11 Apr 2024 09:44:17 +0200 Subject: [PATCH 2/8] use topology file if provided not just the label --- clab/clab.go | 4 ++-- clab/hostsfile.go | 2 +- cmd/inspect.go | 41 ++++++++++++++++++++++------------------- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/clab/clab.go b/clab/clab.go index a1485253e..c9cd03f51 100644 --- a/clab/clab.go +++ b/clab/clab.go @@ -828,7 +828,7 @@ func (c *CLab) ListContainers(ctx context.Context, filter []*types.GenericFilter } // ListNodesContainers lists all containers based on the nodes stored in clab instance. -func (c *CLab) listNodesContainers(ctx context.Context) ([]runtime.GenericContainer, error) { +func (c *CLab) ListNodesContainers(ctx context.Context) ([]runtime.GenericContainer, error) { var containers []runtime.GenericContainer for _, n := range c.Nodes { @@ -1088,7 +1088,7 @@ func (c *CLab) Deploy(ctx context.Context, options *DeployOptions) ([]runtime.Ge } } - containers, err := c.listNodesContainers(ctx) + containers, err := c.ListNodesContainers(ctx) if err != nil { return nil, err } diff --git a/clab/hostsfile.go b/clab/hostsfile.go index 156f36a7f..640b75cff 100644 --- a/clab/hostsfile.go +++ b/clab/hostsfile.go @@ -37,7 +37,7 @@ func (c *CLab) appendHostsFileEntries(ctx context.Context) error { return err } - containers, err := c.listNodesContainers(ctx) + containers, err := c.ListNodesContainers(ctx) if err != nil { return err } diff --git a/cmd/inspect.go b/cmd/inspect.go index 78fcbade6..11044c71b 100644 --- a/cmd/inspect.go +++ b/cmd/inspect.go @@ -83,27 +83,30 @@ func inspectFn(_ *cobra.Command, _ []string) error { // if the topo file is available, use it if topo != "" { - name = c.Config.Name - } - - // or when just the name is given - if name != "" { - // if name is set, filter for name - glabels = []*types.GenericFilter{{ - FilterType: "label", Match: name, - Field: labels.Containerlab, Operator: "=", - }} + containers, err = c.ListNodesContainers(ctx) + if err != nil { + return fmt.Errorf("failed to list containers: %s", err) + } } else { - // this is the --all case - glabels = []*types.GenericFilter{{ - FilterType: "label", - Field: labels.Containerlab, Operator: "exists", - }} - } + // or when just the name is given + if name != "" { + // if name is set, filter for name + glabels = []*types.GenericFilter{{ + FilterType: "label", Match: name, + Field: labels.Containerlab, Operator: "=", + }} + } else { + // this is the --all case + glabels = []*types.GenericFilter{{ + FilterType: "label", + Field: labels.Containerlab, Operator: "exists", + }} + } - containers, err = c.ListContainers(ctx, glabels) - if err != nil { - return fmt.Errorf("failed to list containers: %s", err) + containers, err = c.ListContainers(ctx, glabels) + if err != nil { + return fmt.Errorf("failed to list containers: %s", err) + } } if len(containers) == 0 { From 995e60aec8081c312a17f923a1aa2d4ae95f177c Mon Sep 17 00:00:00 2001 From: Roman Dodin Date: Thu, 11 Apr 2024 12:07:21 +0300 Subject: [PATCH 3/8] added integration tests for basic inspect command --- .gitignore | 2 + 3-clab-gen-scale.clab.yml | 256 +++++++++++++++++++++++ docs/manual/dev/index.md | 3 + docs/manual/dev/test.md | 71 +++++++ mkdocs.yml | 3 + tests/01-smoke/.02-destroy-all.robot.bak | 79 +++++++ tests/01-smoke/01-basic-flow.robot | 7 +- tests/01-smoke/02-destroy-all.robot | 43 +++- 8 files changed, 460 insertions(+), 4 deletions(-) create mode 100644 3-clab-gen-scale.clab.yml create mode 100644 docs/manual/dev/index.md create mode 100644 docs/manual/dev/test.md create mode 100644 tests/01-smoke/.02-destroy-all.robot.bak diff --git a/.gitignore b/.gitignore index 8d73054fb..b4f2394f8 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,5 @@ tests/out # ignore backup clab topo files **/.*clab.y*ml.bak **/*.y*ml.bak + +.python-version diff --git a/3-clab-gen-scale.clab.yml b/3-clab-gen-scale.clab.yml new file mode 100644 index 000000000..aa63956e6 --- /dev/null +++ b/3-clab-gen-scale.clab.yml @@ -0,0 +1,256 @@ +name: 3-clab-gen-scale +prefix: null +mgmt: {} +settings: null +topology: + kinds: + linux: + image: alpine:3 + nodes: + node1-1: + kind: linux + group: tier-1 + node1-2: + kind: linux + group: tier-1 + node1-3: + kind: linux + group: tier-1 + node1-4: + kind: linux + group: tier-1 + node1-5: + kind: linux + group: tier-1 + node2-1: + kind: linux + group: tier-2 + node2-2: + kind: linux + group: tier-2 + node2-3: + kind: linux + group: tier-2 + node2-4: + kind: linux + group: tier-2 + node2-5: + kind: linux + group: tier-2 + node3-1: + kind: linux + group: tier-3 + node3-2: + kind: linux + group: tier-3 + node3-3: + kind: linux + group: tier-3 + node3-4: + kind: linux + group: tier-3 + node3-5: + kind: linux + group: tier-3 + links: + - endpoints: + - node1-1:eth1 + - node2-1:eth1 + deploymentstate: 0 + - endpoints: + - node1-1:eth2 + - node2-2:eth1 + deploymentstate: 0 + - endpoints: + - node1-1:eth3 + - node2-3:eth1 + deploymentstate: 0 + - endpoints: + - node1-1:eth4 + - node2-4:eth1 + deploymentstate: 0 + - endpoints: + - node1-1:eth5 + - node2-5:eth1 + deploymentstate: 0 + - endpoints: + - node1-2:eth1 + - node2-1:eth2 + deploymentstate: 0 + - endpoints: + - node1-2:eth2 + - node2-2:eth2 + deploymentstate: 0 + - endpoints: + - node1-2:eth3 + - node2-3:eth2 + deploymentstate: 0 + - endpoints: + - node1-2:eth4 + - node2-4:eth2 + deploymentstate: 0 + - endpoints: + - node1-2:eth5 + - node2-5:eth2 + deploymentstate: 0 + - endpoints: + - node1-3:eth1 + - node2-1:eth3 + deploymentstate: 0 + - endpoints: + - node1-3:eth2 + - node2-2:eth3 + deploymentstate: 0 + - endpoints: + - node1-3:eth3 + - node2-3:eth3 + deploymentstate: 0 + - endpoints: + - node1-3:eth4 + - node2-4:eth3 + deploymentstate: 0 + - endpoints: + - node1-3:eth5 + - node2-5:eth3 + deploymentstate: 0 + - endpoints: + - node1-4:eth1 + - node2-1:eth4 + deploymentstate: 0 + - endpoints: + - node1-4:eth2 + - node2-2:eth4 + deploymentstate: 0 + - endpoints: + - node1-4:eth3 + - node2-3:eth4 + deploymentstate: 0 + - endpoints: + - node1-4:eth4 + - node2-4:eth4 + deploymentstate: 0 + - endpoints: + - node1-4:eth5 + - node2-5:eth4 + deploymentstate: 0 + - endpoints: + - node1-5:eth1 + - node2-1:eth5 + deploymentstate: 0 + - endpoints: + - node1-5:eth2 + - node2-2:eth5 + deploymentstate: 0 + - endpoints: + - node1-5:eth3 + - node2-3:eth5 + deploymentstate: 0 + - endpoints: + - node1-5:eth4 + - node2-4:eth5 + deploymentstate: 0 + - endpoints: + - node1-5:eth5 + - node2-5:eth5 + deploymentstate: 0 + - endpoints: + - node2-1:eth6 + - node3-1:eth1 + deploymentstate: 0 + - endpoints: + - node2-1:eth7 + - node3-2:eth1 + deploymentstate: 0 + - endpoints: + - node2-1:eth8 + - node3-3:eth1 + deploymentstate: 0 + - endpoints: + - node2-1:eth9 + - node3-4:eth1 + deploymentstate: 0 + - endpoints: + - node2-1:eth10 + - node3-5:eth1 + deploymentstate: 0 + - endpoints: + - node2-2:eth6 + - node3-1:eth2 + deploymentstate: 0 + - endpoints: + - node2-2:eth7 + - node3-2:eth2 + deploymentstate: 0 + - endpoints: + - node2-2:eth8 + - node3-3:eth2 + deploymentstate: 0 + - endpoints: + - node2-2:eth9 + - node3-4:eth2 + deploymentstate: 0 + - endpoints: + - node2-2:eth10 + - node3-5:eth2 + deploymentstate: 0 + - endpoints: + - node2-3:eth6 + - node3-1:eth3 + deploymentstate: 0 + - endpoints: + - node2-3:eth7 + - node3-2:eth3 + deploymentstate: 0 + - endpoints: + - node2-3:eth8 + - node3-3:eth3 + deploymentstate: 0 + - endpoints: + - node2-3:eth9 + - node3-4:eth3 + deploymentstate: 0 + - endpoints: + - node2-3:eth10 + - node3-5:eth3 + deploymentstate: 0 + - endpoints: + - node2-4:eth6 + - node3-1:eth4 + deploymentstate: 0 + - endpoints: + - node2-4:eth7 + - node3-2:eth4 + deploymentstate: 0 + - endpoints: + - node2-4:eth8 + - node3-3:eth4 + deploymentstate: 0 + - endpoints: + - node2-4:eth9 + - node3-4:eth4 + deploymentstate: 0 + - endpoints: + - node2-4:eth10 + - node3-5:eth4 + deploymentstate: 0 + - endpoints: + - node2-5:eth6 + - node3-1:eth5 + deploymentstate: 0 + - endpoints: + - node2-5:eth7 + - node3-2:eth5 + deploymentstate: 0 + - endpoints: + - node2-5:eth8 + - node3-3:eth5 + deploymentstate: 0 + - endpoints: + - node2-5:eth9 + - node3-4:eth5 + deploymentstate: 0 + - endpoints: + - node2-5:eth10 + - node3-5:eth5 + deploymentstate: 0 +debug: false diff --git a/docs/manual/dev/index.md b/docs/manual/dev/index.md new file mode 100644 index 000000000..d43e9e27c --- /dev/null +++ b/docs/manual/dev/index.md @@ -0,0 +1,3 @@ +# Developers Guide + +This is a start of the developers documentation. Stay tuned for more content! diff --git a/docs/manual/dev/test.md b/docs/manual/dev/test.md new file mode 100644 index 000000000..b26ea1bc2 --- /dev/null +++ b/docs/manual/dev/test.md @@ -0,0 +1,71 @@ +# Testing Containerlab + +Containerlab's test program largely consists of: + +- Go-based unit tests +- RobotFramework-based integration tests + +## Integration Tests + +The integration tests are written in RobotFramework and are located in the [`tests`][tests-dir] directory. The tests are run using the [`rf-run`][rf-run] command that wraps `robot` command. The tests are run in a Docker container, so you don't need to install RobotFramework on your local machine. + +### Local execution + +To execute the integration tests locally you have to install the python environment with the required dependencies. If you're using `pyenv` you can use the following commands: + +1. Create a venv and activate it + + ```bash + pyenv virtualenv 3.11 clab-rf + pyenv shell clab-rf + ``` + +2. Install the dependencies + + ```bash + pip install -r tests/requirements.txt + ``` + +Usually you would run the tests using the locally built containerlab binary that contains the unreleased changes. The typical workflow then starts with building the containerlab binary: + +```bash +make build +``` + +The newly built binary is located in the `bin` directory. In order to let the test runner script know where to find the binary, you have to set the `CLAB_BIN` environment variable before calling the `rf-run` script: + +```bash +CLAB_BIN=$(pwd)/bin/containerlab ./tests/rf-run.sh +``` + +/// note +The test runner script requires you to specify the runtime as its first argument. The runtime can be either `docker` or `podman`. Containerlab primarily uses Docker as the default runtime, hence the number of tests written for docker outnumber the podman tests. +/// + +#### Selecting the test suite + +Containerlab's integration tests are grouped by a topic, and each topic is mapped to a directory under the [`tests`][tests-dir] directory and RobotFramework allows for a flexible selection of tests/test suites to run. For example, to run all the smoke test cases, you can use the following command: + +```bash +CLAB_BIN=$(pwd)/bin/containerlab ./tests/rf-run.sh docker tests/01-smoke +``` + +since [`01-smoke`][01-smoke-dir] is a directory containing all the smoke test suites. + +Consequently, in order to run a specific test suite you just need to provide a path to it. E.g. running the `01-basic-flow.robot` test suite from the `01-smoke` directory: + +```bash +CLAB_BIN=$(pwd)/bin/containerlab ./tests/rf-run.sh docker tests/01-smoke/01-basic-flow.robot +``` + +/// note +Selecting a specific test case in a test suite is not supported, since test suites are written in a way that test cases depend on previous ones. +/// + +#### Inspecting the test results + +RobotFramework generates a detailed report in HTML and XML formats that can be found in the `tests/out` directory. The exact paths to the reports are printed to the console after the test run. + +[tests-dir]: https://github.com/srl-labs/containerlab/tree/main/tests +[rf-run]: https://github.com/srl-labs/containerlab/blob/main/tests/rf-run.sh +[01-smoke-dir]: https://github.com/srl-labs/containerlab/tree/main/tests/01-smoke diff --git a/mkdocs.yml b/mkdocs.yml index b3419b213..beffba417 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -61,6 +61,9 @@ nav: - Certificate management: manual/cert.md - Inventory: manual/inventory.md - Image management: manual/images.md + - Developers guide: + - manual/dev/index.md + - Testing: manual/dev/test.md - Command reference: - deploy: cmd/deploy.md - destroy: cmd/destroy.md diff --git a/tests/01-smoke/.02-destroy-all.robot.bak b/tests/01-smoke/.02-destroy-all.robot.bak new file mode 100644 index 000000000..ea900a3e1 --- /dev/null +++ b/tests/01-smoke/.02-destroy-all.robot.bak @@ -0,0 +1,79 @@ +*** Comments *** +This suite tests: +- the destroy --all operation +- the host mode networking for l3 node +- the ipv4-range can be set for a network + + +*** Settings *** +Library OperatingSystem +Library Process +Resource ../common.robot + +Suite Teardown Run sudo -E ${CLAB_BIN} --runtime ${runtime} destroy --all --cleanup + + +*** Variables *** +${runtime} docker +${lab1-file} 01-linux-nodes.clab.yml +${lab-name} 2-linux-nodes +${lab2-file} 01-linux-single-node.clab.yml +${lab2-name} single-node + + +*** Test Cases *** +Deploy first lab + ${result} = Run Process + ... sudo -E ${CLAB_BIN} --runtime ${runtime} deploy -t ${CURDIR}/${lab1-file} + ... shell=True + Log ${result.stdout} + Log ${result.stderr} + Should Be Equal As Integers ${result.rc} 0 + Should Exist %{PWD}/clab-2-linux-nodes + +Deploy second lab + ${result} = Run Process + ... sudo -E ${CLAB_BIN} --runtime ${runtime} deploy -t ${CURDIR}/${lab2-file} + ... cwd=/tmp # using a different cwd to check lab resolution via container labels + ... shell=True + Log ${result.stdout} + Log ${result.stderr} + Should Be Equal As Integers ${result.rc} 0 + Should Exist /tmp/clab-single-node + +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} + Log ${output} + Should Be Equal As Integers ${rc} 0 + +Verify host mode networking for node l3 + # l3 node is launched with host mode networking + # since it is the nginx container, by launching it in the host mode + # we should be able to curl localhost:80 + ${rc} ${output} = Run And Return Rc And Output + ... curl localhost:80 + Log ${output} + Should Be Equal As Integers ${rc} 0 + Should Contain ${output} Thank you for using nginx + +Verify ipv4-range is set correctly + Skip If '${runtime}' != 'docker' + ${rc} ${output} = Run And Return Rc And Output + ... sudo -E ${CLAB_BIN} --runtime ${runtime} inspect -t ${CURDIR}/01-linux-single-node.clab.yml + Log ${output} + Should Contain ${output} 172.20.30.9/24 + +Destroy all labs + ${rc} ${output} = Run And Return Rc And Output + ... sudo -E ${CLAB_BIN} --runtime ${runtime} destroy --all --cleanup + Log ${output} + Should Be Equal As Integers ${rc} 0 + +Check all labs have been removed + ${rc} ${output} = Run And Return Rc And Output + ... sudo -E ${CLAB_BIN} --runtime ${runtime} inspect --all + Log ${output} + Should Contain ${output} no containers found + Should Not Exist /tmp/single-node + Should Not Exist %{PWD}/clab-2-linux-nodes diff --git a/tests/01-smoke/01-basic-flow.robot b/tests/01-smoke/01-basic-flow.robot index 8a8317cce..98ac505f1 100644 --- a/tests/01-smoke/01-basic-flow.robot +++ b/tests/01-smoke/01-basic-flow.robot @@ -98,7 +98,7 @@ Ensure CLAB_INTFS env var is set # the result is printed today. Should Contain ${output.stderr} stdout:\\n3 -Inspect ${lab-name} lab +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} Log ${output} @@ -271,7 +271,10 @@ Verify iptables allow rule is set ${ipt} = Run ... sudo iptables -vnL DOCKER-USER Log ${ipt} - Should Contain ${ipt} ACCEPT all -- * ${MgmtBr} + # debian 12 uses `0` for protocol, while previous versions use `all` + Should Contain Any ${ipt} + ... ACCEPT all -- * ${MgmtBr} + ... ACCEPT 0 -- * ${MgmtBr} ... ignore_case=True ... collapse_spaces=True diff --git a/tests/01-smoke/02-destroy-all.robot b/tests/01-smoke/02-destroy-all.robot index 14cecda33..2ca6a2c1d 100644 --- a/tests/01-smoke/02-destroy-all.robot +++ b/tests/01-smoke/02-destroy-all.robot @@ -15,21 +15,28 @@ Suite Teardown Run sudo -E ${CLAB_BIN} --runtime ${runtime} destroy --al *** Variables *** ${runtime} docker +${lab1-file} 01-linux-nodes.clab.yml +${lab1-name} 2-linux-nodes +${lab2-file} 01-linux-single-node.clab.yml +${lab2-name} single-node +# ${orig_dir} ${EMPTY} *** Test Cases *** Deploy first lab ${result} = Run Process - ... sudo -E ${CLAB_BIN} --runtime ${runtime} deploy -t ${CURDIR}/01-linux-nodes.clab.yml + ... sudo -E ${CLAB_BIN} --runtime ${runtime} deploy -t ${CURDIR}/${lab1-file} ... shell=True Log ${result.stdout} Log ${result.stderr} Should Be Equal As Integers ${result.rc} 0 Should Exist %{PWD}/clab-2-linux-nodes + Set Suite Variable ${orig_dir} ${CURDIR} + Deploy second lab ${result} = Run Process - ... sudo -E ${CLAB_BIN} --runtime ${runtime} deploy -t ${CURDIR}/01-linux-single-node.clab.yml + ... sudo -E ${CLAB_BIN} --runtime ${runtime} deploy -t ${CURDIR}/${lab2-file} ... cwd=/tmp # using a different cwd to check lab resolution via container labels ... shell=True Log ${result.stdout} @@ -37,6 +44,38 @@ Deploy second lab Should Be Equal As Integers ${result.rc} 0 Should Exist /tmp/clab-single-node +Inspect ${lab2-name} lab using its name + ${rc} ${output} = Run And Return Rc And Output + ... sudo -E ${CLAB_BIN} --runtime ${runtime} inspect --name ${lab2-name} + Log ${output} + Should Be Equal As Integers ${rc} 0 + + ${num_nodes} = Run bash -c "echo '${output}' | grep ${lab2-name} | wc -l" + # lab2 only has 1 nodes and therefore inspect output should contain only 1 node + Should Be Equal As Integers ${num_nodes} 1 + +Inspect ${lab2-name} lab using topology file reference + ${result} = Run Process + ... sudo -E ${CLAB_BIN} --runtime ${runtime} inspect -t ${orig_dir}/${lab2-file} + ... shell=True + Log ${result.stdout} + Log ${result.stderr} + Should Be Equal As Integers ${result.rc} 0 + + ${num_nodes} = Run bash -c "echo '${result.stdout}' | grep ${lab2-name} | wc -l" + # lab2 only has 1 nodes and therefore inspect output should contain only 1 node + Should Be Equal As Integers ${num_nodes} 1 + +Inspect all + ${rc} ${output} = Run And Return Rc And Output + ... sudo -E ${CLAB_BIN} --runtime ${runtime} inspect --all + Log ${output} + Should Be Equal As Integers ${rc} 0 + + ${num_nodes} = Run bash -c "echo '${output}' | grep clab- | wc -l" + # 3 nodes in lab1 and 1 node in lab2 + Should Be Equal As Integers ${num_nodes} 4 + Verify host mode networking for node l3 # l3 node is launched with host mode networking # since it is the nginx container, by launching it in the host mode From 3f89ac8aa0a6e3c7c7439a841a2a65b8884bd5ae Mon Sep 17 00:00:00 2001 From: Roman Dodin Date: Thu, 11 Apr 2024 12:16:38 +0300 Subject: [PATCH 4/8] wrongly added topo --- 3-clab-gen-scale.clab.yml | 256 -------------------------------------- 1 file changed, 256 deletions(-) delete mode 100644 3-clab-gen-scale.clab.yml diff --git a/3-clab-gen-scale.clab.yml b/3-clab-gen-scale.clab.yml deleted file mode 100644 index aa63956e6..000000000 --- a/3-clab-gen-scale.clab.yml +++ /dev/null @@ -1,256 +0,0 @@ -name: 3-clab-gen-scale -prefix: null -mgmt: {} -settings: null -topology: - kinds: - linux: - image: alpine:3 - nodes: - node1-1: - kind: linux - group: tier-1 - node1-2: - kind: linux - group: tier-1 - node1-3: - kind: linux - group: tier-1 - node1-4: - kind: linux - group: tier-1 - node1-5: - kind: linux - group: tier-1 - node2-1: - kind: linux - group: tier-2 - node2-2: - kind: linux - group: tier-2 - node2-3: - kind: linux - group: tier-2 - node2-4: - kind: linux - group: tier-2 - node2-5: - kind: linux - group: tier-2 - node3-1: - kind: linux - group: tier-3 - node3-2: - kind: linux - group: tier-3 - node3-3: - kind: linux - group: tier-3 - node3-4: - kind: linux - group: tier-3 - node3-5: - kind: linux - group: tier-3 - links: - - endpoints: - - node1-1:eth1 - - node2-1:eth1 - deploymentstate: 0 - - endpoints: - - node1-1:eth2 - - node2-2:eth1 - deploymentstate: 0 - - endpoints: - - node1-1:eth3 - - node2-3:eth1 - deploymentstate: 0 - - endpoints: - - node1-1:eth4 - - node2-4:eth1 - deploymentstate: 0 - - endpoints: - - node1-1:eth5 - - node2-5:eth1 - deploymentstate: 0 - - endpoints: - - node1-2:eth1 - - node2-1:eth2 - deploymentstate: 0 - - endpoints: - - node1-2:eth2 - - node2-2:eth2 - deploymentstate: 0 - - endpoints: - - node1-2:eth3 - - node2-3:eth2 - deploymentstate: 0 - - endpoints: - - node1-2:eth4 - - node2-4:eth2 - deploymentstate: 0 - - endpoints: - - node1-2:eth5 - - node2-5:eth2 - deploymentstate: 0 - - endpoints: - - node1-3:eth1 - - node2-1:eth3 - deploymentstate: 0 - - endpoints: - - node1-3:eth2 - - node2-2:eth3 - deploymentstate: 0 - - endpoints: - - node1-3:eth3 - - node2-3:eth3 - deploymentstate: 0 - - endpoints: - - node1-3:eth4 - - node2-4:eth3 - deploymentstate: 0 - - endpoints: - - node1-3:eth5 - - node2-5:eth3 - deploymentstate: 0 - - endpoints: - - node1-4:eth1 - - node2-1:eth4 - deploymentstate: 0 - - endpoints: - - node1-4:eth2 - - node2-2:eth4 - deploymentstate: 0 - - endpoints: - - node1-4:eth3 - - node2-3:eth4 - deploymentstate: 0 - - endpoints: - - node1-4:eth4 - - node2-4:eth4 - deploymentstate: 0 - - endpoints: - - node1-4:eth5 - - node2-5:eth4 - deploymentstate: 0 - - endpoints: - - node1-5:eth1 - - node2-1:eth5 - deploymentstate: 0 - - endpoints: - - node1-5:eth2 - - node2-2:eth5 - deploymentstate: 0 - - endpoints: - - node1-5:eth3 - - node2-3:eth5 - deploymentstate: 0 - - endpoints: - - node1-5:eth4 - - node2-4:eth5 - deploymentstate: 0 - - endpoints: - - node1-5:eth5 - - node2-5:eth5 - deploymentstate: 0 - - endpoints: - - node2-1:eth6 - - node3-1:eth1 - deploymentstate: 0 - - endpoints: - - node2-1:eth7 - - node3-2:eth1 - deploymentstate: 0 - - endpoints: - - node2-1:eth8 - - node3-3:eth1 - deploymentstate: 0 - - endpoints: - - node2-1:eth9 - - node3-4:eth1 - deploymentstate: 0 - - endpoints: - - node2-1:eth10 - - node3-5:eth1 - deploymentstate: 0 - - endpoints: - - node2-2:eth6 - - node3-1:eth2 - deploymentstate: 0 - - endpoints: - - node2-2:eth7 - - node3-2:eth2 - deploymentstate: 0 - - endpoints: - - node2-2:eth8 - - node3-3:eth2 - deploymentstate: 0 - - endpoints: - - node2-2:eth9 - - node3-4:eth2 - deploymentstate: 0 - - endpoints: - - node2-2:eth10 - - node3-5:eth2 - deploymentstate: 0 - - endpoints: - - node2-3:eth6 - - node3-1:eth3 - deploymentstate: 0 - - endpoints: - - node2-3:eth7 - - node3-2:eth3 - deploymentstate: 0 - - endpoints: - - node2-3:eth8 - - node3-3:eth3 - deploymentstate: 0 - - endpoints: - - node2-3:eth9 - - node3-4:eth3 - deploymentstate: 0 - - endpoints: - - node2-3:eth10 - - node3-5:eth3 - deploymentstate: 0 - - endpoints: - - node2-4:eth6 - - node3-1:eth4 - deploymentstate: 0 - - endpoints: - - node2-4:eth7 - - node3-2:eth4 - deploymentstate: 0 - - endpoints: - - node2-4:eth8 - - node3-3:eth4 - deploymentstate: 0 - - endpoints: - - node2-4:eth9 - - node3-4:eth4 - deploymentstate: 0 - - endpoints: - - node2-4:eth10 - - node3-5:eth4 - deploymentstate: 0 - - endpoints: - - node2-5:eth6 - - node3-1:eth5 - deploymentstate: 0 - - endpoints: - - node2-5:eth7 - - node3-2:eth5 - deploymentstate: 0 - - endpoints: - - node2-5:eth8 - - node3-3:eth5 - deploymentstate: 0 - - endpoints: - - node2-5:eth9 - - node3-4:eth5 - deploymentstate: 0 - - endpoints: - - node2-5:eth10 - - node3-5:eth5 - deploymentstate: 0 -debug: false From e673bdc19ee98e4266c172470e9533261f4d50f8 Mon Sep 17 00:00:00 2001 From: Roman Dodin Date: Thu, 11 Apr 2024 12:17:35 +0300 Subject: [PATCH 5/8] more accidentally not ignored stuff --- tests/01-smoke/.02-destroy-all.robot.bak | 79 ------------------------ 1 file changed, 79 deletions(-) delete mode 100644 tests/01-smoke/.02-destroy-all.robot.bak diff --git a/tests/01-smoke/.02-destroy-all.robot.bak b/tests/01-smoke/.02-destroy-all.robot.bak deleted file mode 100644 index ea900a3e1..000000000 --- a/tests/01-smoke/.02-destroy-all.robot.bak +++ /dev/null @@ -1,79 +0,0 @@ -*** Comments *** -This suite tests: -- the destroy --all operation -- the host mode networking for l3 node -- the ipv4-range can be set for a network - - -*** Settings *** -Library OperatingSystem -Library Process -Resource ../common.robot - -Suite Teardown Run sudo -E ${CLAB_BIN} --runtime ${runtime} destroy --all --cleanup - - -*** Variables *** -${runtime} docker -${lab1-file} 01-linux-nodes.clab.yml -${lab-name} 2-linux-nodes -${lab2-file} 01-linux-single-node.clab.yml -${lab2-name} single-node - - -*** Test Cases *** -Deploy first lab - ${result} = Run Process - ... sudo -E ${CLAB_BIN} --runtime ${runtime} deploy -t ${CURDIR}/${lab1-file} - ... shell=True - Log ${result.stdout} - Log ${result.stderr} - Should Be Equal As Integers ${result.rc} 0 - Should Exist %{PWD}/clab-2-linux-nodes - -Deploy second lab - ${result} = Run Process - ... sudo -E ${CLAB_BIN} --runtime ${runtime} deploy -t ${CURDIR}/${lab2-file} - ... cwd=/tmp # using a different cwd to check lab resolution via container labels - ... shell=True - Log ${result.stdout} - Log ${result.stderr} - Should Be Equal As Integers ${result.rc} 0 - Should Exist /tmp/clab-single-node - -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} - Log ${output} - Should Be Equal As Integers ${rc} 0 - -Verify host mode networking for node l3 - # l3 node is launched with host mode networking - # since it is the nginx container, by launching it in the host mode - # we should be able to curl localhost:80 - ${rc} ${output} = Run And Return Rc And Output - ... curl localhost:80 - Log ${output} - Should Be Equal As Integers ${rc} 0 - Should Contain ${output} Thank you for using nginx - -Verify ipv4-range is set correctly - Skip If '${runtime}' != 'docker' - ${rc} ${output} = Run And Return Rc And Output - ... sudo -E ${CLAB_BIN} --runtime ${runtime} inspect -t ${CURDIR}/01-linux-single-node.clab.yml - Log ${output} - Should Contain ${output} 172.20.30.9/24 - -Destroy all labs - ${rc} ${output} = Run And Return Rc And Output - ... sudo -E ${CLAB_BIN} --runtime ${runtime} destroy --all --cleanup - Log ${output} - Should Be Equal As Integers ${rc} 0 - -Check all labs have been removed - ${rc} ${output} = Run And Return Rc And Output - ... sudo -E ${CLAB_BIN} --runtime ${runtime} inspect --all - Log ${output} - Should Contain ${output} no containers found - Should Not Exist /tmp/single-node - Should Not Exist %{PWD}/clab-2-linux-nodes From 0c01db3b2153ba69fcbc13ae4d1e94533d1bd028 Mon Sep 17 00:00:00 2001 From: Roman Dodin Date: Thu, 11 Apr 2024 14:35:36 +0300 Subject: [PATCH 6/8] added a test for the inspect command with ext containers --- tests/06-ext-container/01-ext-container.robot | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/06-ext-container/01-ext-container.robot b/tests/06-ext-container/01-ext-container.robot index c3cef56cc..28c438252 100644 --- a/tests/06-ext-container/01-ext-container.robot +++ b/tests/06-ext-container/01-ext-container.robot @@ -41,6 +41,18 @@ Verify ip and thereby exec on ext1 Should Be Equal As Integers ${rc} 0 Should Contain ${output} 192.168.0.1/24 +Inspect the lab using topology file reference + ${result} = Run Process + ... sudo -E ${CLAB_BIN} --runtime ${runtime} inspect -t ${CURDIR}/${lab-file-name} + ... shell=True + Log ${result.stdout} + Log ${result.stderr} + Should Be Equal As Integers ${result.rc} 0 + + ${num_nodes} = Run bash -c "echo '${result.stdout}' | wc -l" + # the inspect command should return only two external nodes (+4 lines for the header and footer) + Should Be Equal As Integers ${num_nodes} 6 + Verify links in node ext2 ${rc} ${output} = Run And Return Rc And Output ... sudo -E ${CLAB_BIN} --runtime ${runtime} exec --label clab-node-name\=ext2 --cmd "ip link show dev eth1" From 7b89deb1a0370ad8dc242373eb186aa74b2e55d7 Mon Sep 17 00:00:00 2001 From: Roman Dodin Date: Thu, 11 Apr 2024 14:38:03 +0300 Subject: [PATCH 7/8] remove grepping for the lab node to make sure the tables doesn't have extra lines --- tests/01-smoke/02-destroy-all.robot | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/01-smoke/02-destroy-all.robot b/tests/01-smoke/02-destroy-all.robot index 2ca6a2c1d..0f639a643 100644 --- a/tests/01-smoke/02-destroy-all.robot +++ b/tests/01-smoke/02-destroy-all.robot @@ -50,9 +50,9 @@ Inspect ${lab2-name} lab using its name Log ${output} Should Be Equal As Integers ${rc} 0 - ${num_nodes} = Run bash -c "echo '${output}' | grep ${lab2-name} | wc -l" - # lab2 only has 1 nodes and therefore inspect output should contain only 1 node - Should Be Equal As Integers ${num_nodes} 1 + ${num_lines} = Run bash -c "echo '${output}' | wc -l" + # lab2 only has 1 nodes and therefore inspect output should contain only 1 node (+4 lines for the table header and footer) + Should Be Equal As Integers ${num_lines} 5 Inspect ${lab2-name} lab using topology file reference ${result} = Run Process @@ -62,9 +62,9 @@ Inspect ${lab2-name} lab using topology file reference Log ${result.stderr} Should Be Equal As Integers ${result.rc} 0 - ${num_nodes} = Run bash -c "echo '${result.stdout}' | grep ${lab2-name} | wc -l" + ${num_lines} = Run bash -c "echo '${result.stdout}' | wc -l" # lab2 only has 1 nodes and therefore inspect output should contain only 1 node - Should Be Equal As Integers ${num_nodes} 1 + Should Be Equal As Integers ${num_lines} 5 Inspect all ${rc} ${output} = Run And Return Rc And Output @@ -72,9 +72,9 @@ Inspect all Log ${output} Should Be Equal As Integers ${rc} 0 - ${num_nodes} = Run bash -c "echo '${output}' | grep clab- | wc -l" - # 3 nodes in lab1 and 1 node in lab2 - Should Be Equal As Integers ${num_nodes} 4 + ${num_lines} = Run bash -c "echo '${output}' | wc -l" + # 3 nodes in lab1 and 1 node in lab2 (+4 lines for the header and footer) + Should Be Equal As Integers ${num_lines} 8 Verify host mode networking for node l3 # l3 node is launched with host mode networking From 523834d0e7218f6b11fafe65b84d545163937fcf Mon Sep 17 00:00:00 2001 From: Roman Dodin Date: Thu, 11 Apr 2024 14:40:55 +0300 Subject: [PATCH 8/8] address linter complaints --- clab/clab.go | 4 +++- clab/hostsfile.go | 9 +++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/clab/clab.go b/clab/clab.go index c9cd03f51..74012e8a5 100644 --- a/clab/clab.go +++ b/clab/clab.go @@ -546,6 +546,7 @@ func (c *CLab) createWaitForDependency() error { return nil } +// skipcq: GO-R1005 func (c *CLab) scheduleNodes(ctx context.Context, maxWorkers int, skipPostDeploy bool) (*sync.WaitGroup, *exec.ExecCollection) { concurrentChan := make(chan *depMgr.DependencyNode) @@ -882,7 +883,7 @@ func (c *CLab) getLinkNodes() map[string]links.Node { // GetSpecialLinkNodes returns a map of special nodes that are used to resolve links. // Special nodes are host and mgmt-bridge nodes that are not typically present in the topology file // but are required to resolve links. -func (c *CLab) getSpecialLinkNodes() map[string]links.Node { +func (*CLab) getSpecialLinkNodes() map[string]links.Node { // add the virtual host and mgmt-bridge nodes to the resolve nodes specialNodes := map[string]links.Node{ "host": links.GetHostLinkNode(), @@ -957,6 +958,7 @@ func (c *CLab) extractDNSServers(filesys fs.FS) error { } // Deploy the given topology. +// skipcq: GO-R1005 func (c *CLab) Deploy(ctx context.Context, options *DeployOptions) ([]runtime.GenericContainer, error) { var err error diff --git a/clab/hostsfile.go b/clab/hostsfile.go index 640b75cff..9dc04c23a 100644 --- a/clab/hostsfile.go +++ b/clab/hostsfile.go @@ -53,11 +53,13 @@ func (c *CLab) appendHostsFileEntries(ctx context.Context) error { return err } - defer f.Close() + defer f.Close() // skipcq: GO-S2307 + _, err = f.Write(data) if err != nil { return err } + return nil } @@ -84,6 +86,7 @@ func generateHostsEntries(containers []runtime.GenericContainer, labname string) entries.Write(v6entries.Bytes()) fmt.Fprintf(&entries, clabHostEntryPostfix, labname) entries.WriteByte('\n') + return entries.Bytes() } @@ -91,11 +94,13 @@ func (c *CLab) DeleteEntriesFromHostsFile() error { if c.Config.Name == "" { return errors.New("missing containerlab name") } + f, err := os.OpenFile(clabHostsFilename, os.O_RDWR, 0644) // skipcq: GSC-G302 if err != nil { return err } - defer f.Close() + defer f.Close() // skipcq: GO-S2307 + reader := bufio.NewReader(f) skiplines := false output := bytes.Buffer{}