Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add specsFile to clabverter #151

Merged
merged 23 commits into from
Jun 15, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,6 @@ cover.out

# goreleaser dist dir for testing builds and such locally
.dist/

# build files
cmd/clabverter/build/
3 changes: 3 additions & 0 deletions clabverter/assets/topology-clab.yaml.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
definition:
containerlab: |-
{{- .ClabConfig }}
3 changes: 0 additions & 3 deletions clabverter/assets/topology.yaml.template
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,3 @@ spec:
naming: {{ .Naming }}
{{- end }}
connectivity: vxlan
definition:
containerlab: |-
{{- .ClabConfig }}
111 changes: 101 additions & 10 deletions clabverter/clabverter.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,20 @@
clabernetesutil "github.com/srl-labs/clabernetes/util"
clabernetesutilcontainerlab "github.com/srl-labs/clabernetes/util/containerlab"
clabernetesutilkubernetes "github.com/srl-labs/clabernetes/util/kubernetes"
yamlConfig "go.uber.org/config"
"gopkg.in/yaml.v3"
)

const (
specIndentSpaces = 4
specDefinitionIndentSpaces = 8
specDefinitionIndentSpaces = 10
maxBytesForConfigMap = 950_000
)

// MustNewClabverter returns an instance of Clabverter or panics.
func MustNewClabverter(
topologyFile,
specsFile,
outputDirectory,
destinationNamespace,
naming,
Expand Down Expand Up @@ -90,6 +93,7 @@
return &Clabverter{
logger: clabverterLogger,
topologyFile: topologyFile,
specsFile: specsFile,
githubToken: githubToken,
outputDirectory: outputDirectory,
stdout: stdout,
Expand All @@ -113,6 +117,7 @@
logger claberneteslogging.Instance

topologyFile string
specsFile string
outputDirectory string
stdout bool

Expand All @@ -126,6 +131,7 @@
topologyPath string
topologyPathParent string
isRemotePath bool
valuesPath string
githubGroup string
githubRepo string
githubToken string
Expand All @@ -135,6 +141,8 @@
rawClabConfig string
clabConfig *clabernetesutilcontainerlab.Config

rawSpecValues string

// mapping of nodeName -> startup-config info for the templating process; this is its own thing
// because configurations may be huge and configmaps have a 1M char limit, so while keeping them
// by themselves may not "solve" for ginormous configs, it can certainly give us a little extra
Expand Down Expand Up @@ -362,6 +370,38 @@

c.logger.Debug("loading and validating containerlab topology file complete!")

if c.specsFile != "" {
c.valuesPath, err = filepath.Abs(c.specsFile)
if err != nil {
c.logger.Criticalf("failed determining absolute path of values file, error: %s", err)

return err
}

c.logger.Debugf(
"determined fully qualified spec values file path as: %s", c.valuesPath,
)

c.logger.Debug("attempting to load spec values....")

rawSpecValuesBytes, err := os.ReadFile(c.valuesPath)

if err != nil {
c.logger.Criticalf(
"failed reading spec values file at '%s' from disk, error: %s",
c.valuesPath, err,
)

return err
}

// specs file content is non-indented, need to make it match spec indent
c.rawSpecValues = "spec:\n" + clabernetesutil.Indent(
string(rawSpecValuesBytes),
specIndentSpaces,
)
}

return nil
}

Expand Down Expand Up @@ -453,13 +493,8 @@
err = t.Execute(
&rendered,
containerlabTemplateVars{
Name: c.clabConfig.Name,
Namespace: c.destinationNamespace,
// pad w/ a newline so the template can look prettier :)
ClabConfig: "\n" + clabernetesutil.Indent(
c.rawClabConfig,
specDefinitionIndentSpaces,
),
Name: c.clabConfig.Name,
Namespace: c.destinationNamespace,
Files: files,
FilesFromURL: c.extraFilesFromURL,
InsecureRegistries: c.insecureRegistries,
Expand All @@ -470,19 +505,75 @@
},
)
if err != nil {
c.logger.Criticalf("failed executing configmap template: %s", err)
c.logger.Criticalf("failed executing topology template: %s", err)

return err
}

fileName := fmt.Sprintf("%s/%s.yaml", c.outputDirectory, c.clabConfig.Name)

// merge yamls
// spec values override rendered values

Check failure on line 516 in clabverter/clabverter.go

View workflow job for this annotation

GitHub Actions / lint / lint

var-naming: don't use underscores in Go names; var rendered_yaml should be renderedYaml (revive)
rendered_yaml := yamlConfig.Source(strings.NewReader(rendered.String()))

Check failure on line 517 in clabverter/clabverter.go

View workflow job for this annotation

GitHub Actions / lint / lint

var-naming: don't use underscores in Go names; var spec_yaml should be specYaml (revive)
spec_yaml := yamlConfig.Source(strings.NewReader(c.rawSpecValues))

Check failure on line 519 in clabverter/clabverter.go

View workflow job for this annotation

GitHub Actions / lint / lint

var-naming: don't use underscores in Go names; var merged_yaml should be mergedYaml (revive)
merged_yaml, err := yamlConfig.NewYAML(rendered_yaml, spec_yaml)
if err != nil {
c.logger.Criticalf("failed merging topology spec values: %s", err)

return err
}

var target interface{}
err = merged_yaml.Get(yamlConfig.Root).Populate(&target)

Check failure on line 528 in clabverter/clabverter.go

View workflow job for this annotation

GitHub Actions / lint / lint

only one cuddle assignment allowed before if statement (wsl)
if err != nil {
c.logger.Criticalf("failed extracting spec values: %s", err)

return err
}

Check failure on line 534 in clabverter/clabverter.go

View workflow job for this annotation

GitHub Actions / lint / lint

var-naming: don't use underscores in Go names; var rendered_bytes should be renderedBytes (revive)
rendered_bytes, err := yaml.Marshal(target)
if err != nil {
c.logger.Criticalf("error marshalling topology YAML: %s", err)

return err
}

// marshalling removes the yaml start document chars, adding them back
rendered_bytes = append([]byte("---\n"), rendered_bytes...)

// marshalling uglifies multilne clab topo, appending separate template render to keep it pretty

Check failure on line 545 in clabverter/clabverter.go

View workflow job for this annotation

GitHub Actions / lint / lint

var-naming: don't use underscores in Go names; var t_clab should be tClab (revive)
t_clab, err := template.ParseFS(Assets, "assets/topology-clab.yaml.template")
if err != nil {
c.logger.Criticalf("failed loading containerlab definition manifest from assets: %s", err)

return err
}

Check failure on line 552 in clabverter/clabverter.go

View workflow job for this annotation

GitHub Actions / lint / lint

var-naming: don't use underscores in Go names; var rendered_clab should be renderedClab (revive)
var rendered_clab bytes.Buffer

err = t_clab.Execute(
&rendered_clab,
containerlabDefinitionTemplateVars{
// pad w/ a newline so the template can look prettier :)
ClabConfig: "\n" + clabernetesutil.Indent(
c.rawClabConfig,
specDefinitionIndentSpaces,
),
},
)
if err != nil {
c.logger.Criticalf("failed executing configmap template: %s", err)

return err
}

c.renderedFiles = append(
c.renderedFiles,
renderedContent{
friendlyName: "clabernetes manifest",
fileName: fileName,
content: rendered.Bytes(),
content: append(rendered_bytes, rendered_clab.Bytes()...),
},
)

Expand Down
4 changes: 4 additions & 0 deletions clabverter/clabverter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func TestClabvert(t *testing.T) {
cases := []struct {
name string
topologyFile string
specsFile string
destinationNamespace string
insecureRegistries string
imagePullSecrets string
Expand All @@ -32,6 +33,7 @@ func TestClabvert(t *testing.T) {
{
name: "simple",
topologyFile: "test-fixtures/clabversiontest/clab.yaml",
specsFile: "",
destinationNamespace: "notclabernetes",
insecureRegistries: "1.2.3.4",
imagePullSecrets: "",
Expand All @@ -41,6 +43,7 @@ func TestClabvert(t *testing.T) {
{
name: "simple-no-explicit-namespace",
topologyFile: "test-fixtures/clabversiontest/clab.yaml",
specsFile: "test-fixtures/clabversiontest/specs.yaml",
insecureRegistries: "1.2.3.4",
imagePullSecrets: "regcred",
disableExpose: true,
Expand Down Expand Up @@ -87,6 +90,7 @@ func TestClabvert(t *testing.T) {

clabverter := clabernetesclabverter.MustNewClabverter(
testCase.topologyFile,
testCase.specsFile,
actualDir,
testCase.destinationNamespace,
testCase.naming,
Expand Down
7 changes: 7 additions & 0 deletions clabverter/test-fixtures/clabversiontest/specs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
statusProbes:
enabled: true
excludedNodes:
- baguette
Copy link
Contributor

Choose a reason for hiding this comment

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

🥖 😁

probeConfiguration:
tcpProbeConfiguration:
port: 22
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,14 @@ spec:
- regcred
naming: non-prefixed
statusProbes:
enabled: false
excludedNodes: null
enabled: true
excludedNodes:
- baguette
nodeProbeConfigurations: null
probeConfiguration:
startupSeconds: 0
tcpProbeConfiguration:
port: 22
status:
conditions: null
configs: null
Expand Down
5 changes: 4 additions & 1 deletion clabverter/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ type topologyFileFromURLTemplateVars struct {
type containerlabTemplateVars struct {
Name string
Namespace string
ClabConfig string
Files map[string][]topologyConfigMapTemplateVars
FilesFromURL map[string][]topologyFileFromURLTemplateVars
InsecureRegistries []string
Expand All @@ -38,6 +37,10 @@ type containerlabTemplateVars struct {
ContainerlabVersion string
}

type containerlabDefinitionTemplateVars struct {
ClabConfig string
}

type renderedContent struct {
friendlyName string
fileName string
Expand Down
8 changes: 8 additions & 0 deletions cmd/clabverter/cli/entrypoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

const (
topologyFile = "topologyFile"
specsFile = "specsFile"
Copy link
Member

@hellt hellt Jun 7, 2024

Choose a reason for hiding this comment

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

I am rooting for shorter arg names, but for this feature I fail to find one.
Maybe though it should be --topoSpecFile (or --topoSpec) to be precise what it is about.

outputDirectory = "outputDirectory"
destinationNamespace = "destinationNamespace"
insecureRegistries = "insecureRegistries"
Expand Down Expand Up @@ -37,6 +38,12 @@ If not set, clabverter will look for a file named '*.clab.y*ml'`,
Required: false,
Value: "",
},
&cli.StringFlag{
Name: specsFile,
Usage: `set the values file to parse that will be included in the topology manifest spec.`,
Required: false,
Value: "",
},
&cli.StringFlag{
Name: outputDirectory,
Usage: "set the output directory for the converted manifest(s)",
Expand Down Expand Up @@ -102,6 +109,7 @@ If not set, clabverter will look for a file named '*.clab.y*ml'`,
Action: func(c *cli.Context) error {
err := clabernetesclabverter.MustNewClabverter(
c.String(topologyFile),
c.String(specsFile),
c.String(outputDirectory),
c.String(destinationNamespace),
c.String(naming),
Expand Down
1 change: 1 addition & 0 deletions e2e/clabverter/clabverter_basic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ func TestClabverterBasic(t *testing.T) {

c := clabernetesclabverter.MustNewClabverter(
"test-fixtures/basic_clab.yaml",
"",
"test-fixtures",
namespace,
"prefixed",
Expand Down
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -89,16 +89,19 @@ require (
go.opentelemetry.io/otel/sdk v1.19.0 // indirect
go.opentelemetry.io/otel/trace v1.19.0 // indirect
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
go.uber.org/config v1.4.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.26.0 // indirect
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
golang.org/x/lint v0.0.0-20190930215403-16217165b5de // indirect
golang.org/x/net v0.24.0 // indirect
golang.org/x/oauth2 v0.13.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/term v0.20.0 // indirect
golang.org/x/text v0.15.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.20.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917 // indirect
Expand Down
Loading
Loading