Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions nodes/ceos/ceos.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,6 @@ management api http-commands
vrf {{ .Env.CLAB_MGMT_VRF }}
no shutdown
{{end}}
{{ .PartialCfg }}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI remark, not tested in the lab:
Full configs still get Go template rendering, but no longer pass through SubstituteEnvsAndTemplate, so ${VAR} expansion regresses. Partial configs are inserted as .PartialCfg, so a partial file containing {{ .ShortName }} would be emitted literally instead of rendered.

Please add a test case for env expansion.

!
end
61 changes: 57 additions & 4 deletions nodes/ceos/ceos.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package ceos

import (
"bytes"
"context"
_ "embed"
"encoding/json"
Expand All @@ -16,6 +17,7 @@ import (
"path/filepath"
"regexp"
"strings"
"text/template"

"github.com/charmbracelet/log"
clabconstants "github.com/srl-labs/containerlab/constants"
Expand Down Expand Up @@ -61,8 +63,7 @@ var (
)

// Register registers the node in the NodeRegistry.
func Register(r *clabnodes.NodeRegistry) {
generateNodeAttributes := clabnodes.NewGenerateNodeAttributes(generateable, generateIfFormat)
func Register(r *clabnodes.NodeRegistry) { generateNodeAttributes := clabnodes.NewGenerateNodeAttributes(generateable, generateIfFormat)
platformAttrs := &clabnodes.PlatformAttrs{
ScrapliPlatformName: scrapliPlatformName,
NapalmPlatformName: NapalmPlatformName,
Expand All @@ -81,6 +82,21 @@ func Register(r *clabnodes.NodeRegistry) {

type ceos struct {
clabnodes.DefaultNode
bootCfg string
partialStartupCfg string
}

type CeosTemplateData struct {
ShortName string
Env map[string]string
MgmtIntf string
MgmtIPv4Address string
MgmtIPv4PrefixLength int
MgmtIPv4Gateway string
MgmtIPv6Address string
MgmtIPv6PrefixLength int
MgmtIPv6Gateway string
PartialCfg string
}

// intfMap represents interface mapping config file.
Expand Down Expand Up @@ -209,16 +225,24 @@ func (n *ceos) createCEOSFiles(ctx context.Context) error {
return err
}

// default to embedded boilerplate config
n.bootCfg = cfgTemplate

// use startup config file provided by a user
if nodeCfg.StartupConfig != "" {
c, err := os.ReadFile(nodeCfg.StartupConfig)
if err != nil {
return err
}
cfgTemplate = string(c)

if clabutils.IsPartialConfigFile(nodeCfg.StartupConfig) {
n.partialStartupCfg = string(c)
} else {
n.bootCfg = string(c)
}
}

err = n.GenerateConfig(nodeCfg.ResStartupConfig, cfgTemplate)
err = n.genBootConfig()
if err != nil {
return err
}
Expand Down Expand Up @@ -272,6 +296,35 @@ func (n *ceos) createCEOSFiles(ctx context.Context) error {
return err
}

func (n *ceos) genBootConfig() error {
nodeCfg := n.Config()

tplData := CeosTemplateData{
ShortName: n.Cfg.ShortName,
Env: nodeCfg.Env,
MgmtIntf: nodeCfg.MgmtIntf,
MgmtIPv4Address: nodeCfg.MgmtIPv4Address,
MgmtIPv4PrefixLength: nodeCfg.MgmtIPv4PrefixLength,
MgmtIPv4Gateway: nodeCfg.MgmtIPv4Gateway,
MgmtIPv6Address: nodeCfg.MgmtIPv6Address,
MgmtIPv6PrefixLength: nodeCfg.MgmtIPv6PrefixLength,
MgmtIPv6Gateway: nodeCfg.MgmtIPv6Gateway,
PartialCfg: n.partialStartupCfg,
}

t, err := template.New("ceos-config").Funcs(clabutils.CreateFuncs()).Parse(n.bootCfg)
if err != nil {
return fmt.Errorf("failed to parse cfg template for node %q: %w", n.Cfg.ShortName, err)
}

buf := new(bytes.Buffer)
if err := t.Execute(buf, tplData); err != nil {
return fmt.Errorf("failed to execute cfg template for node %q: %w", n.Cfg.ShortName, err)
}

return clabutils.CreateFile(nodeCfg.ResStartupConfig, buf.String())
}

// Func that Places the Certificates in the right place and format.
func (n *ceos) createCEOSCertificates() error {
if *n.Cfg.Certificate.Issue {
Expand Down
Loading