Skip to content

Commit

Permalink
Retrieve labdir from container labels during destroy (#1738)
Browse files Browse the repository at this point in the history
* retrieve labdir from container labels

We where always expecting the labdir to be a subdir of the actual pwd.
With this PR we will query the labels and deduce the labdir from the "containerlab" label.

* extend test

* combine listing containers for destroy fn

---------

Co-authored-by: Roman Dodin <[email protected]>
  • Loading branch information
steiler and hellt authored Nov 23, 2023
1 parent d945895 commit 27fad67
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 34 deletions.
2 changes: 1 addition & 1 deletion clab/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ type Config struct {
func (c *CLab) parseTopology() error {
log.Infof("Parsing & checking topology file: %s", c.TopoPaths.TopologyFilenameBase())

err := c.TopoPaths.SetLabDir(c.Config.Name)
err := c.TopoPaths.SetLabDirByPrefix(c.Config.Name)
if err != nil {
return err
}
Expand Down
111 changes: 86 additions & 25 deletions cmd/destroy.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"context"
"fmt"
"os"
"path/filepath"

log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
Expand All @@ -17,6 +18,7 @@ import (
"github.com/srl-labs/containerlab/runtime"
"github.com/srl-labs/containerlab/runtime/ignite"
"github.com/srl-labs/containerlab/types"
"gopkg.in/yaml.v2"
)

var (
Expand Down Expand Up @@ -54,49 +56,41 @@ func destroyFn(_ *cobra.Command, _ []string) error {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

topos := map[string]struct{}{}
// topo will hold the reference to the topology file
// as the key and the respective lab directory as the referenced value
topos := map[string]string{}

switch {
case !all:
topos[topo] = struct{}{}
case all:
// only WithRuntime option is needed to list all containers of a lab
inspectAllOpts := []clab.ClabOption{
clab.WithRuntime(rt,
&runtime.RuntimeConfig{
Debug: debug,
Timeout: timeout,
GracefulShutdown: graceful,
},
),
clab.WithTimeout(timeout),
}

c, err := clab.NewContainerLab(inspectAllOpts...)
cnts, err := listContainers(ctx, topo)
if err != nil {
return err
}
// list all containerlab containers
filter := []*types.GenericFilter{{
FilterType: "label", Match: c.Config.Name,
Field: labels.Containerlab, Operator: "exists",
}}
containers, err := c.ListContainers(ctx, filter)

if len(cnts) == 0 {
log.Info("no containerlab containers found")
return nil
}

topos[topo] = filepath.Dir(cnts[0].Labels[labels.NodeLabDir])

case all:
containers, err := listContainers(ctx, topo)
if err != nil {
return err
}

if len(containers) == 0 {
return fmt.Errorf("no containerlab labs were found")
return fmt.Errorf("no containerlab labs found")
}
// get unique topo files from all labs
for i := range containers {
topos[containers[i].Labels[labels.TopoFile]] = struct{}{}
topos[containers[i].Labels[labels.TopoFile]] = filepath.Dir(containers[i].Labels[labels.NodeLabDir])
}
}

log.Debugf("We got the following topos struct for destroy: %+v", topos)
for topo := range topos {
for topo, labdir := range topos {
opts := []clab.ClabOption{
clab.WithTimeout(timeout),
clab.WithTopoPath(topo, varsFile),
Expand All @@ -121,6 +115,15 @@ func destroyFn(_ *cobra.Command, _ []string) error {
return err
}

if labdir != "" {
// adjust the labdir. Usually we take the PWD. but now on destroy time,
// we might be in a different Dir.
err = nc.TopoPaths.SetLabDir(labdir)
if err != nil {
return err
}
}

err = links.SetMgmtNetUnderlayingBridge(nc.Config.Mgmt.Bridge)
if err != nil {
return err
Expand Down Expand Up @@ -238,3 +241,61 @@ func destroyLab(ctx context.Context, c *clab.CLab) (err error) {

return err
}

// listContainers lists containers belonging to a certain topo if topo file path is specified
// otherwise lists all containerlab containers.
func listContainers(ctx context.Context, topo string) ([]runtime.GenericContainer, error) {
runtimeConfig := &runtime.RuntimeConfig{
Debug: debug,
Timeout: timeout,
GracefulShutdown: graceful,
}

opts := []clab.ClabOption{
clab.WithRuntime(rt, runtimeConfig),
clab.WithTimeout(timeout),
}

c, err := clab.NewContainerLab(opts...)
if err != nil {
return nil, err
}

// filter to list all containerlab containers
// it is overwritten if topo file is provided
filter := []*types.GenericFilter{{
FilterType: "label",
Field: labels.Containerlab,
Operator: "exists",
}}

// when topo file is provided, filter containers by lab name
if topo != "" {
// read topo yaml file to get the lab name
topo, err := os.ReadFile(topo)
if err != nil {
return nil, err
}

config := &clab.Config{}

err = yaml.Unmarshal(topo, config)
if err != nil {
return nil, fmt.Errorf("%w, failed to parse topology file", err)
}

filter = []*types.GenericFilter{{
FilterType: "label",
Field: labels.Containerlab,
Operator: "=",
Match: config.Name,
}}
}

containers, err := c.ListContainers(ctx, filter)
if err != nil {
return nil, err
}

return containers, nil
}
20 changes: 14 additions & 6 deletions tests/01-smoke/02-destroy-all.robot
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ This suite tests:

*** Settings ***
Library OperatingSystem
Library Process
Resource ../common.robot

Suite Teardown Run sudo -E ${CLAB_BIN} --runtime ${runtime} destroy --all --cleanup
Expand All @@ -18,16 +19,21 @@ ${runtime} docker

*** Test Cases ***
Deploy first lab
${rc} ${output} = Run And Return Rc And Output
${result} = Run Process
... sudo -E ${CLAB_BIN} --runtime ${runtime} deploy -t ${CURDIR}/01-linux-nodes.clab.yml
Log ${output}
Should Be Equal As Integers ${rc} 0
... shell=True
Log ${result.stdout}
Should Be Equal As Integers ${result.rc} 0
Should Exist %{PWD}/clab-2-linux-nodes

Deploy second lab
${rc} ${output} = Run And Return Rc And Output
${result} = Run Process
... sudo -E ${CLAB_BIN} --runtime ${runtime} deploy -t ${CURDIR}/01-linux-single-node.clab.yml
Log ${output}
Should Be Equal As Integers ${rc} 0
... cwd=/tmp # using a different cwd to check lab resolution via container labels
... shell=True
Log ${result.stdout}
Should Be Equal As Integers ${result.rc} 0
Should Exist /tmp/clab-single-node

Verify host mode networking for node l3
# l3 node is launched with host mode networking
Expand Down Expand Up @@ -57,3 +63,5 @@ Check all labs have been removed
... 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
12 changes: 10 additions & 2 deletions types/topo_paths.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,16 @@ func (t *TopoPaths) SetTopologyFilePath(topologyFile string) error {
return nil
}

// SetLabDir sets the labDir foldername (no abs path, but the last element) usually the topology name.
func (t *TopoPaths) SetLabDir(topologyName string) (err error) {
func (t *TopoPaths) SetLabDir(p string) (err error) {
if !utils.DirExists(p) {
return fmt.Errorf("folder %s does not exist or is not accessible", p)
}
t.labDir = p
return nil
}

// SetLabDirByPrefix sets the labDir foldername (no abs path, but the last element) usually the topology name.
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.
Expand Down
7 changes: 7 additions & 0 deletions utils/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ func FileOrDirExists(filename string) bool {
return err == nil && f != nil
}

// DirExists returns true if a dir referenced by path exists & accessible.
func DirExists(filename string) bool {
f, err := os.Stat(filename)

return err == nil && f != nil && f.IsDir()
}

// CopyFile copies a file from src to dst. If src and dst files exist, and are
// the same, then return success. Otherwise, copy the file contents from src to dst.
// mode is the desired target file permissions, e.g. "0644".
Expand Down

0 comments on commit 27fad67

Please sign in to comment.