diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 000000000..c399a6836 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,57 @@ +--- +workflow: + rules: + - if: '$CI_PIPELINE_SOURCE == "push"' + when: never # Prevent pipeline run for push event + - if: '$CI_PIPELINE_SOURCE == "external_pull_request_event"' + when: never # Prevent pipeline run for PRs from github mirror + - when: always # Run pipeline for all other cases + +stages: + - code-tests + - build + - smoke-tests + - integration-tests + +variables: + CGO_ENABLED: 0 + +go-tests: + stage: code-tests + tags: + - containerlab + script: + # create empty files to make clab happy + - sudo mkdir -p /etc/containerlab/templates/srl && sudo touch /etc/containerlab/templates/srl/srlconfig.tpl + - CGO_ENABLED=1 go test -cover -race ./... + +build-containerlab: + stage: build + tags: + - containerlab + script: + - sudo go build -o /usr/bin/containerlab + +smoke-tests: + stage: smoke-tests + tags: + - containerlab + script: + - source ~/venvs/rf/bin/activate + - bash ./tests/rf-run.sh ./tests/01-smoke + artifacts: + when: always + paths: + - "./tests/out/*.html" + +srl-tests: + stage: integration-tests + tags: + - containerlab + script: + - source ~/venvs/rf/bin/activate + - bash ./tests/rf-run.sh ./tests/02-basic-srl + artifacts: + when: always + paths: + - "./tests/out/*.html" diff --git a/clab/cert.go b/clab/cert.go index 649a7253f..5f59ce0d1 100644 --- a/clab/cert.go +++ b/clab/cert.go @@ -55,6 +55,46 @@ type CaRootInput struct { NamePrefix string } +var rootCACSRTempl string = `{ + "CN": "{{.Prefix}} Root CA", + "key": { + "algo": "rsa", + "size": 2048 + }, + "names": [{ + "C": "BE", + "L": "Antwerp", + "O": "Nokia", + "OU": "Container lab" + }], + "ca": { + "expiry": "262800h" + } +} +` + +var nodeCSRTempl string = `{ + "CN": "{{.Name}}.{{.Prefix}}.io", + "key": { + "algo": "rsa", + "size": 2048 + }, + "names": [{ + "C": "BE", + "L": "Antwerp", + "O": "Nokia", + "OU": "Container lab" + }], + "hosts": [ + "{{.Name}}", + "{{.LongName}}", + "{{.Fqdn}}" + ] +} + + +` + // GenerateRootCa function func (c *CLab) GenerateRootCa(csrRootJsonTpl *template.Template, input CaRootInput) (*Certificates, error) { log.Info("Creating root CA") @@ -227,9 +267,9 @@ func (c *CLab) CreateRootCA() error { return nil } - tpl, err := template.ParseFiles(rootCaCsrTemplate) + tpl, err := template.New("ca-csr").Parse(rootCACSRTempl) if err != nil { - return fmt.Errorf("failed to parse rootCACsrTemplate: %v", err) + return fmt.Errorf("failed to parse Root CA CSR Template: %v", err) } rootCerts, err := c.GenerateRootCa(tpl, CaRootInput{ Prefix: c.Config.Name, diff --git a/clab/clab.go b/clab/clab.go index 88c695b45..315ce228c 100644 --- a/clab/clab.go +++ b/clab/clab.go @@ -15,13 +15,6 @@ import ( log "github.com/sirupsen/logrus" ) -const ( - rootCaCsrTemplate = "/etc/containerlab/templates/ca/csr-root-ca.json" - certCsrTemplate = "/etc/containerlab/templates/ca/csr.json" -) - -// var debug bool - type CLab struct { Config *Config TopoFile *TopoFile @@ -200,9 +193,9 @@ func (c *CLab) CreateNodes(ctx context.Context, workers uint) { // if not available on disk, create cert in next step if err != nil { // create CERT - certTpl, err = template.ParseFiles(certCsrTemplate) + certTpl, err = template.New("node-cert").Parse(nodeCSRTempl) if err != nil { - log.Errorf("failed to parse certCsrTemplate: %v", err) + log.Errorf("failed to parse Node CSR Template: %v", err) } certInput := CertInput{ Name: node.ShortName, diff --git a/cmd/destroy.go b/cmd/destroy.go index 0a2af2b0a..d3b7a97bc 100644 --- a/cmd/destroy.go +++ b/cmd/destroy.go @@ -171,6 +171,15 @@ func destroyLab(ctx context.Context, c *clab.CLab) (err error) { if err != nil { return fmt.Errorf("could not list containers: %v", err) } + if len(containers) == 0 { + return nil + } + + // get lab directory used by this lab to remove it later if cleanup is used + var labDir string + if cleanup { + labDir = filepath.Dir(containers[0].Labels["clab-node-lab-dir"]) + } log.Infof("Destroying container lab: %s", c.Config.Name) wg := new(sync.WaitGroup) @@ -192,7 +201,7 @@ func destroyLab(ctx context.Context, c *clab.CLab) (err error) { // remove the lab directories if cleanup { - err = os.RemoveAll(c.Dir.Lab) + err = os.RemoveAll(labDir) if err != nil { log.Errorf("error deleting lab directory: %v", err) } diff --git a/tests/01-smoke/01-basic-flow.robot b/tests/01-smoke/01-basic-flow.robot index c6b71b461..95feead76 100644 --- a/tests/01-smoke/01-basic-flow.robot +++ b/tests/01-smoke/01-basic-flow.robot @@ -1,5 +1,6 @@ *** Settings *** Library OperatingSystem +Suite Teardown Run sudo containerlab destroy -t ${CURDIR}/01-linux-nodes.clab.yml --cleanup *** Variables *** ${lab-name} 2-linux-nodes diff --git a/tests/01-smoke/02-destroy-all.robot b/tests/01-smoke/02-destroy-all.robot index 6f1fe4f75..7c764b858 100644 --- a/tests/01-smoke/02-destroy-all.robot +++ b/tests/01-smoke/02-destroy-all.robot @@ -1,5 +1,6 @@ *** Settings *** Library OperatingSystem +Suite Teardown Run sudo containerlab destroy --all --cleanup *** Test Cases *** Deploy first lab @@ -16,7 +17,7 @@ Deploy second lab Destroy all labs ${rc} ${output} = Run And Return Rc And Output - ... sudo containerlab destroy --all + ... sudo containerlab destroy --all --cleanup Log ${output} Should Be Equal As Integers ${rc} 0 diff --git a/tests/02-basic-srl/01-two-srls.robot b/tests/02-basic-srl/01-two-srls.robot new file mode 100644 index 000000000..9b9d2e3ff --- /dev/null +++ b/tests/02-basic-srl/01-two-srls.robot @@ -0,0 +1,36 @@ +*** Settings *** +Library OperatingSystem +Suite Teardown Run Keyword Cleanup + +*** Variables *** +${lab-name} 02-01-two-srls + +*** Test Cases *** +Deploy ${lab-name} lab + Log ${CURDIR} + ${rc} ${output} = Run And Return Rc And Output + ... sudo containerlab deploy -t ${CURDIR}/02-srl02.clab.yml + Log ${output} + Should Be Equal As Integers ${rc} 0 + +Wait 5 seconds + Sleep 5s + +Verify links in node srl1 + ${rc} ${output} = Run And Return Rc And Output + ... sudo docker exec clab-${lab-name}-srl1 ip link show e1-1 + Log ${output} + Should Be Equal As Integers ${rc} 0 + Should Contain ${output} state UP + +Verify links in node srl2 + ${rc} ${output} = Run And Return Rc And Output + ... sudo docker exec clab-${lab-name}-srl2 ip link show e1-1 + Log ${output} + Should Be Equal As Integers ${rc} 0 + Should Contain ${output} state UP + +*** Keywords *** +Cleanup + Run sudo containerlab destroy -t ${CURDIR}/02-srl02.clab.yml --cleanup + Run rm -rf ${CURDIR}/${lab-name} diff --git a/tests/02-basic-srl/02-srl02.clab.yml b/tests/02-basic-srl/02-srl02.clab.yml new file mode 100644 index 000000000..e849e3ae8 --- /dev/null +++ b/tests/02-basic-srl/02-srl02.clab.yml @@ -0,0 +1,15 @@ +name: 02-01-two-srls + +topology: + kinds: + srl: + image: srlinux:21.3.1-410 + license: /home/gitlab-runner/srl-lic.key + nodes: + srl1: + kind: srl + srl2: + kind: srl + + links: + - endpoints: ["srl1:e1-1", "srl2:e1-1"] diff --git a/tests/requirements.txt b/tests/requirements.txt index 23aaeab27..5e807401b 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,2 +1,2 @@ -robotframework==3.2.2 +robotframework==4.0.1 robotframework-sshlibrary \ No newline at end of file