Skip to content

Commit

Permalink
Merge branch 'master' into scrapli-netconf
Browse files Browse the repository at this point in the history
  • Loading branch information
hellt committed Jun 28, 2021
2 parents 106c5bc + 930d9ad commit 5fdc24a
Show file tree
Hide file tree
Showing 33 changed files with 361 additions and 278 deletions.
81 changes: 56 additions & 25 deletions .github/workflows/cicd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,43 +48,18 @@ jobs:
- uses: actions/setup-go@v2
with:
go-version: ${{ env.GOVER }}
# create fake default config of srl for tests to validate path
- run: sudo mkdir -p /etc/containerlab/templates/srl && sudo touch /etc/containerlab/templates/srl/srlconfig.tpl
- run: go test -cover ./...

staticcheck:
runs-on: ubuntu-20.04
needs: file-changes
if: needs.file-changes.outputs.code == 'true' || startsWith(github.ref, 'refs/tags/v')
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
with:
go-version: ${{ env.GOVER }}
- name: Staticcheck
run: |
go install honnef.co/go/tools/cmd/staticcheck@latest
staticcheck ./...
docs-test:
runs-on: ubuntu-20.04
needs: file-changes
if: needs.file-changes.outputs.docs == 'true' || startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/docs-publish'
steps:
- uses: actions/checkout@v2
- run: docker run -v $(pwd):/docs --entrypoint mkdocs squidfunk/mkdocs-material:$MKDOCS_MATERIAL_VER build --clean --strict
- name: htmltest
run: |
curl https://htmltest.wjdp.uk | bash
./bin/htmltest -c docs/htmltest.yml
smoke-tests:
runs-on: ubuntu-20.04
strategy:
matrix:
runtime: ["docker", "containerd"]
needs:
- staticcheck
- unit-test
steps:
- name: Checkout
Expand Down Expand Up @@ -114,12 +89,68 @@ jobs:
name: 01-smoke-log
path: ./tests/out/*.html

ceos-basic-tests:
runs-on: ubuntu-20.04
strategy:
matrix:
runtime: ["docker", "containerd"]
needs:
- unit-test
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: ${{ env.GOVER }}
- name: Build containerlab
run: go build && sudo mv ./containerlab /usr/bin/containerlab
- uses: actions/setup-python@v2
with:
python-version: "3.8"
- name: Install robotframework
run: |
python -m pip install --upgrade pip
pip install -r tests/requirements.txt
- name: Login to GitHub Container Registry
uses: docker/login-action@v1
with:
registry: ghcr.io
username: hellt
password: ${{ secrets.GHCR_READ_PKG_PAT }}
- name: Pull ceos image
run: docker pull ghcr.io/srl-labs/ceos:4.25.0F && docker tag ghcr.io/srl-labs/ceos:4.25.0F ceos:4.25.0F
- name: Run ceos tests
run: |
bash ./tests/rf-run.sh ${{ matrix.runtime }} ./tests/03-basic-ceos
# upload test reports as a zip file
- uses: actions/upload-artifact@v2
if: always()
with:
name: 03-basic-ceos-log
path: ./tests/out/*.html

docs-test:
runs-on: ubuntu-20.04
needs: file-changes
if: needs.file-changes.outputs.docs == 'true' || startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/docs-publish'
steps:
- uses: actions/checkout@v2
- run: docker run -v $(pwd):/docs --entrypoint mkdocs squidfunk/mkdocs-material:$MKDOCS_MATERIAL_VER build --clean --strict
- name: htmltest
run: |
curl https://htmltest.wjdp.uk | bash
./bin/htmltest -c docs/htmltest.yml
build-and-release:
runs-on: ubuntu-20.04
if: startsWith(github.ref, 'refs/tags/v')
needs:
- docs-test
- smoke-tests
- ceos-basic-tests
steps:
- name: Checkout
uses: actions/checkout@v2
Expand Down
3 changes: 0 additions & 3 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ archives:
- replacements:
linux: Linux
files:
- templates/**/*
- lab-examples/**/*
checksum:
name_template: checksums.txt
Expand Down Expand Up @@ -54,8 +53,6 @@ nfpms:
contents:
- src: ./lab-examples
dst: /etc/containerlab/lab-examples
- src: ./templates
dst: /etc/containerlab/templates
# - src: ./tools
# dst: /etc/containerlab/tools
- src: /usr/bin/containerlab
Expand Down
3 changes: 3 additions & 0 deletions clab/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ func (c *CLab) NewNode(nodeName string, nodeDef *types.NodeDefinition, idx int)
if err != nil {
return err
}

// Init
nodeInitializer, ok := nodes.Nodes[nodeCfg.Kind]
if !ok {
Expand All @@ -124,6 +125,7 @@ func (c *CLab) NewNode(nodeName string, nodeDef *types.NodeDefinition, idx int)
log.Errorf("failed to initialize node %q: %v", nodeCfg.ShortName, err)
return fmt.Errorf("failed to initialize node %q: %v", nodeCfg.ShortName, err)
}

n.Config().Labels = utils.MergeStringMaps(n.Config().Labels, map[string]string{
"containerlab": c.Config.Name,
"clab-node-name": n.Config().ShortName,
Expand All @@ -134,6 +136,7 @@ func (c *CLab) NewNode(nodeName string, nodeDef *types.NodeDefinition, idx int)
"clab-topo-file": c.TopoFile.path,
})
c.Nodes[nodeName] = n

return nil
}

Expand Down
76 changes: 59 additions & 17 deletions cmd/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,45 @@ package cmd

import (
"context"
"encoding/json"
"errors"
"fmt"
"strings"

"github.com/google/shlex"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/srl-labs/containerlab/clab"
"github.com/srl-labs/containerlab/types"
)

var labels []string
var (
labels []string
execFormat string
execCommand string
)

// execCmd represents the exec command
var execCmd = &cobra.Command{
Use: "exec",
Short: "execute a command on one or multiple containers",
PreRunE: sudoCheck,
Run: func(cmd *cobra.Command, args []string) {
RunE: func(cmd *cobra.Command, args []string) error {
if name == "" && topo == "" {
fmt.Println("provide either lab name (--name) or topology file path (--topo)")
return
return errors.New("provide either lab name (--name) or topology file path (--topo)")

}

if execCommand == "" {
return errors.New("provide command to execute")
}
log.Debugf("raw command: %v", args)
if len(args) == 0 {
fmt.Println("provide command to execute")
return

switch execFormat {
case "json",
"plain":
// expected values, go on
default:
log.Error("format is expected to be either json or plain")
}
opts := []clab.ClabOption{
clab.WithDebug(debug),
Expand All @@ -52,14 +66,18 @@ var execCmd = &cobra.Command{
log.Fatalf("could not list containers: %v", err)
}
if len(containers) == 0 {
log.Println("no containers found")
return
return errors.New("no containers found")
}
cmds := make([]string, 0, len(args))
for _, a := range args {
cmds = append(cmds, strings.Split(a, " ")...)

cmds, err := shlex.Split(execCommand)
if err != nil {
return err
}

jsonResult := make(map[string]map[string]interface{})

for _, cont := range containers {
var doc interface{}
if cont.State != "running" {
continue
}
Expand All @@ -68,17 +86,41 @@ var execCmd = &cobra.Command{
log.Errorf("%s: failed to execute cmd: %v", cont.Names, err)
continue
}
if len(stdout) > 0 {
log.Infof("%s: stdout:\n%s", cont.Names, string(stdout))
contName := strings.TrimLeft(cont.Names[0], "/")
switch execFormat {
case "json":
jsonResult[contName] = make(map[string]interface{})
err := json.Unmarshal([]byte(stdout), &doc)
if err == nil {
jsonResult[contName]["stdout"] = doc
} else {
jsonResult[contName]["stdout"] = string(stdout)
}
jsonResult[contName]["stderr"] = string(stderr)
case "plain":
if len(stdout) > 0 {
log.Infof("%s: stdout:\n%s", contName, string(stdout))
}
if len(stderr) > 0 {
log.Infof("%s: stderr:\n%s", contName, string(stderr))
}

}
if len(stderr) > 0 {
log.Infof("%s: stderr:\n%s", cont.Names, string(stderr))
}
if execFormat == "json" {
result, err := json.Marshal(jsonResult)
if err != nil {
log.Errorf("Issue converting to json %v", err)
}
fmt.Println(string(result))
}
return err
},
}

func init() {
rootCmd.AddCommand(execCmd)
execCmd.Flags().StringVarP(&execCommand, "cmd", "", "", "command to execute")
execCmd.Flags().StringSliceVarP(&labels, "label", "", []string{}, "labels to filter container subset")
execCmd.Flags().StringVarP(&execFormat, "format", "f", "plain", "output format. One of [json, plain]")
}
File renamed without changes.
28 changes: 18 additions & 10 deletions cmd/graph.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package cmd

import (
"context"
_ "embed"
"encoding/json"
"fmt"
"html/template"
Expand All @@ -19,14 +20,15 @@ import (
"github.com/srl-labs/containerlab/types"
)

const (
defaultTemplatePath = "/etc/containerlab/templates/graph/index.html"
)
var (
srv string
tmpl string
offline bool
dot bool

var srv string
var tmpl string
var offline bool
var dot bool
//go:embed graph-template.html
graphTemplate string
)

type graphTopo struct {
Nodes []containerDetails `json:"nodes,omitempty"`
Expand Down Expand Up @@ -117,9 +119,15 @@ var graphCmd = &cobra.Command{
Name: c.Config.Name,
Data: template.JS(string(b)),
}
tmpl := template.Must(template.ParseFiles(tmpl))
var t *template.Template
if tmpl != "" {
t = template.Must(template.ParseFiles(tmpl))
} else {
t = template.Must(template.New("graph").Parse(graphTemplate))
}

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
_ = tmpl.Execute(w, topoD)
_ = t.Execute(w, topoD)
})

log.Infof("Listening on %s...", srv)
Expand Down Expand Up @@ -173,5 +181,5 @@ func init() {
graphCmd.Flags().StringVarP(&srv, "srv", "s", ":50080", "HTTP server address to view, customize and export your topology")
graphCmd.Flags().BoolVarP(&offline, "offline", "o", false, "use only information from topo file when building graph")
graphCmd.Flags().BoolVarP(&dot, "dot", "", false, "generate dot file instead of launching the web server")
graphCmd.Flags().StringVarP(&tmpl, "template", "", defaultTemplatePath, "Go html template used to generate the graph")
graphCmd.Flags().StringVarP(&tmpl, "template", "", "", "Go html template used to generate the graph")
}
Loading

0 comments on commit 5fdc24a

Please sign in to comment.