From 15887301fa2ecdd80db96bb9d510be11f31b74ac Mon Sep 17 00:00:00 2001 From: Karim Radhouani Date: Fri, 18 Jun 2021 20:08:26 +0800 Subject: [PATCH] cleanup, rework labels init and add basic tests --- clab/ceos.go | 3 - clab/config.go | 77 ++++++++++------------- clab/crpd.go | 28 ++++----- clab/linux.go | 4 -- clab/sonic.go | 4 -- clab/srl.go | 13 +--- clab/vr-csr.go | 3 - clab/vr-ros.go | 3 - clab/vr-sros.go | 11 +--- clab/vr-veos.go | 4 +- clab/vr-vmx.go | 3 - clab/vr-xrv.go | 3 - clab/vr-xrv9k.go | 3 - types/topology.go | 3 + types/topology_test.go | 137 +++++++++++++++++++++++++++++++++++++++++ 15 files changed, 188 insertions(+), 111 deletions(-) create mode 100644 types/topology_test.go diff --git a/clab/ceos.go b/clab/ceos.go index 271df47d6..cff6b526c 100644 --- a/clab/ceos.go +++ b/clab/ceos.go @@ -61,9 +61,7 @@ func initCeosNode(c *CLab, nodeDef *types.NodeDefinition, nodeCfg *types.NodeCon if err != nil { return err } - // nodeCfg.Image = c.imageInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Image = c.Config.Topology.GetNodeImage(nodeCfg.ShortName) - // nodeCfg.Position = c.positionInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Position = c.Config.Topology.GetNodePosition(nodeCfg.ShortName) // initialize specific container information @@ -90,7 +88,6 @@ func initCeosNode(c *CLab, nodeDef *types.NodeDefinition, nodeCfg *types.NodeCon nodeCfg.Cmd = envSb.String() nodeCfg.User = user - // nodeCfg.Group = c.groupInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Group = c.Config.Topology.GetNodeGroup(nodeCfg.ShortName) nodeCfg.NodeType = nodeDef.Type diff --git a/clab/config.go b/clab/config.go index 8e17c3070..01d75923e 100644 --- a/clab/config.go +++ b/clab/config.go @@ -9,8 +9,10 @@ import ( "context" "fmt" "os" + "path" "path/filepath" "runtime" + "sort" "strings" "syscall" @@ -111,12 +113,15 @@ func (c *CLab) ParseTopology() error { c.Links = make(map[int]*types.Link) // initialize the Node information from the topology map - idx := 0 - for nodeName, node := range c.Config.Topology.Nodes { - if err := c.NewNode(nodeName, node, idx); err != nil { + nodeNames := make([]string, 0, len(c.Config.Topology.Nodes)) + for nodeName := range c.Config.Topology.Nodes { + nodeNames = append(nodeNames, nodeName) + } + sort.Strings(nodeNames) + for idx, nodeName := range nodeNames { + if err := c.NewNode(nodeName, c.Config.Topology.Nodes[nodeName], idx); err != nil { return err } - idx++ } for i, l := range c.Config.Topology.Links { // i represents the endpoint integer and l provide the link struct @@ -125,40 +130,20 @@ func (c *CLab) ParseTopology() error { return nil } -// initialize container labels -func (c *CLab) labelsInit(nodeDef *types.NodeDefinition, kind string, node *types.NodeConfig) map[string]string { - defaultLabels := map[string]string{ - "containerlab": c.Config.Name, - "clab-node-name": node.ShortName, - "clab-node-kind": kind, - "clab-node-type": node.NodeType, - "clab-node-group": node.Group, - "clab-node-lab-dir": node.LabDir, - "clab-topo-file": c.TopoFile.path, - } - // merge global labels into kind envs - m := utils.MergeStringMaps(c.Config.Topology.GetDefaults().GetLabels(), c.Config.Topology.GetKind(kind).GetLabels()) - // merge result of previous merge into node envs - m2 := utils.MergeStringMaps(m, nodeDef.GetLabels()) - // merge with default labels - return utils.MergeStringMaps(m2, defaultLabels) -} - // NewNode initializes a new node object func (c *CLab) NewNode(nodeName string, nodeDef *types.NodeDefinition, idx int) error { - // initialize a new node - nodeCfg := new(types.NodeConfig) - nodeCfg.ShortName = nodeName - nodeCfg.LongName = prefix + "-" + c.Config.Name + "-" + nodeName - nodeCfg.Fqdn = nodeName + "." + c.Config.Name + ".io" - nodeCfg.LabDir = c.Dir.Lab + "/" + nodeName - nodeCfg.Index = idx - nodeCfg.Endpoints = []*types.Endpoint{} - - nodeCfg.NetworkMode = strings.ToLower(nodeDef.NetworkMode) - - nodeCfg.MgmtIPv4Address = nodeDef.MgmtIPv4 - nodeCfg.MgmtIPv6Address = nodeDef.MgmtIPv6 + // initialize a new node configuration + nodeCfg := &types.NodeConfig{ + ShortName: nodeName, + LongName: strings.Join([]string{prefix, c.Config.Name, nodeName}, "-"), + Fqdn: strings.Join([]string{nodeName, c.Config.Name, ".io"}, "."), + LabDir: path.Join(c.Dir.Lab, nodeName), + Index: idx, + Endpoints: make([]*types.Endpoint, 0), + NetworkMode: strings.ToLower(nodeDef.GetNetworkMode()), + MgmtIPv4Address: nodeDef.GetMgmtIPv4(), + MgmtIPv6Address: nodeDef.GetMgmtIPv6(), + } // initialize the node with global parameters // Kind initialization is either coming from `topology.nodes` section or from `topology.defaults` @@ -166,7 +151,6 @@ func (c *CLab) NewNode(nodeName string, nodeDef *types.NodeDefinition, idx int) nodeCfg.Kind = strings.ToLower(c.Config.Topology.GetNodeKind(nodeName)) // initialize bind mounts - // binds := c.bindsInit(nodeDef) binds := c.Config.Topology.GetNodeBinds(nodeName) err := resolveBindPaths(binds, nodeCfg.LabDir) if err != nil { @@ -174,20 +158,15 @@ func (c *CLab) NewNode(nodeName string, nodeDef *types.NodeDefinition, idx int) } nodeCfg.Binds = binds - //ps, pb, err := c.portsInit(nodeDef) nodeCfg.PortSet, nodeCfg.PortBindings, err = c.Config.Topology.GetNodePorts(nodeName) if err != nil { return err } // initialize passed env variables which will be merged with kind specific ones - // envs := c.envInit(nodeDef, nodeCfg.Kind) envs := c.Config.Topology.GetNodeEnv(nodeName) - - // user := c.userInit(nodeDef, nodeCfg.Kind) user := c.Config.Topology.GetNodeUser(nodeName) - // nodeCfg.Publish = c.publishInit(nodeDef, nodeCfg.Kind) nodeCfg.Publish = c.Config.Topology.GetNodePublish(nodeName) switch nodeCfg.Kind { case "ceos": @@ -253,9 +232,7 @@ func (c *CLab) NewNode(nodeName string, nodeDef *types.NodeDefinition, idx int) } case "bridge", "ovs-bridge": - // nodeCfg.Group = c.groupInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Group = c.Config.Topology.GetNodeGroup(nodeCfg.ShortName) - // nodeCfg.Position = c.positionInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Position = c.Config.Topology.GetNodePosition(nodeCfg.ShortName) default: @@ -263,8 +240,16 @@ func (c *CLab) NewNode(nodeName string, nodeDef *types.NodeDefinition, idx int) } // init labels after all node kinds are processed - nodeCfg.Labels = c.labelsInit(nodeDef, nodeCfg.Kind, nodeCfg) - // nodeCfg.Labels = c.Config.Topology.GetNodeLabels(nodeName) + nodeCfg.Labels = c.Config.Topology.GetNodeLabels(nodeName) + nodeCfg.Labels = utils.MergeStringMaps(nodeCfg.Labels, map[string]string{ + "containerlab": c.Config.Name, + "clab-node-name": nodeCfg.ShortName, + "clab-node-kind": nodeCfg.Kind, + "clab-node-type": nodeCfg.NodeType, + "clab-node-group": nodeCfg.Group, + "clab-node-lab-dir": nodeCfg.LabDir, + "clab-topo-file": c.TopoFile.path, + }) c.Nodes[nodeName] = nodeCfg return nil } diff --git a/clab/crpd.go b/clab/crpd.go index fb6f788b5..304937d7c 100644 --- a/clab/crpd.go +++ b/clab/crpd.go @@ -16,26 +16,20 @@ import ( func initCrpdNode(c *CLab, nodeDef *types.NodeDefinition, nodeCfg *types.NodeConfig, user string, envs map[string]string) error { var err error - // node.Config, err = c.configInit(nodeCfg, node.Kind) c.Config.Topology.GetNodeConfig(nodeCfg.ShortName) if err != nil { return err } - // nodeCfg.Image = c.imageInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Image = c.Config.Topology.GetNodeImage(nodeCfg.ShortName) - // nodeCfg.Group = c.groupInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Group = c.Config.Topology.GetNodeGroup(nodeCfg.ShortName) - // nodeCfg.Position = c.positionInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Position = c.Config.Topology.GetNodePosition(nodeCfg.ShortName) nodeCfg.User = user // initialize license file - // lp, err := c.licenseInit(nodeDef, nodeCfg) - lp, err := c.Config.Topology.GetNodeLicense(nodeCfg.ShortName) + nodeCfg.License, err = c.Config.Topology.GetNodeLicense(nodeCfg.ShortName) if err != nil { return err } - nodeCfg.License = lp // mount config and log dirs nodeCfg.Binds = append(nodeCfg.Binds, fmt.Sprint(path.Join(nodeCfg.LabDir, "config"), ":/config")) @@ -46,32 +40,32 @@ func initCrpdNode(c *CLab, nodeDef *types.NodeDefinition, nodeCfg *types.NodeCon return err } -func (c *CLab) createCRPDFiles(node *types.NodeConfig) error { +func (c *CLab) createCRPDFiles(nodeCfg *types.NodeConfig) error { // create config and logs directory that will be bind mounted to crpd - utils.CreateDirectory(path.Join(node.LabDir, "config"), 0777) - utils.CreateDirectory(path.Join(node.LabDir, "log"), 0777) + utils.CreateDirectory(path.Join(nodeCfg.LabDir, "config"), 0777) + utils.CreateDirectory(path.Join(nodeCfg.LabDir, "log"), 0777) // copy crpd config from default template or user-provided conf file - cfg := path.Join(node.LabDir, "/config/juniper.conf") + cfg := path.Join(nodeCfg.LabDir, "/config/juniper.conf") - err := node.GenerateConfig(cfg, defaultConfigTemplates[node.Kind]) + err := nodeCfg.GenerateConfig(cfg, defaultConfigTemplates[nodeCfg.Kind]) if err != nil { - log.Errorf("node=%s, failed to generate config: %v", node.ShortName, err) + log.Errorf("node=%s, failed to generate config: %v", nodeCfg.ShortName, err) } // copy crpd sshd conf file to crpd node dir src := "/etc/containerlab/templates/crpd/sshd_config" - dst := node.LabDir + "/config/sshd_config" + dst := nodeCfg.LabDir + "/config/sshd_config" err = copyFile(src, dst) if err != nil { return fmt.Errorf("file copy [src %s -> dst %s] failed %v", src, dst, err) } log.Debugf("CopyFile src %s -> dst %s succeeded\n", src, dst) - if node.License != "" { + if nodeCfg.License != "" { // copy license file to node specific lab directory - src = node.License - dst = path.Join(node.LabDir, "/config/license.conf") + src = nodeCfg.License + dst = path.Join(nodeCfg.LabDir, "/config/license.conf") if err = copyFile(src, dst); err != nil { return fmt.Errorf("file copy [src %s -> dst %s] failed %v", src, dst, err) } diff --git a/clab/linux.go b/clab/linux.go index e17e91ff2..a2f0890aa 100644 --- a/clab/linux.go +++ b/clab/linux.go @@ -18,13 +18,9 @@ func initLinuxNode(c *CLab, nodeDef *types.NodeDefinition, nodeCfg *types.NodeCo if err != nil { return err } - // nodeCfg.Image = c.imageInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Image = c.Config.Topology.GetNodeImage(nodeCfg.ShortName) - // nodeCfg.Group = c.groupInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Group = c.Config.Topology.GetNodeGroup(nodeCfg.ShortName) - // nodeCfg.Position = c.positionInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Position = c.Config.Topology.GetNodePosition(nodeCfg.ShortName) - // nodeCfg.Cmd = c.cmdInit(nodeDef, nodeCfg.Kind) nodeCfg.Cmd = c.Config.Topology.GetNodeCmd(nodeCfg.ShortName) nodeCfg.User = user diff --git a/clab/sonic.go b/clab/sonic.go index 99731afec..e4399bb20 100644 --- a/clab/sonic.go +++ b/clab/sonic.go @@ -9,16 +9,12 @@ import "github.com/srl-labs/containerlab/types" func initSonicNode(c *CLab, nodeDef *types.NodeDefinition, nodeCfg *types.NodeConfig, user string, envs map[string]string) error { var err error - // nodeCfg.Config, err = c.configInit(nodeDef, nodeCfg.Kind) c.Config.Topology.GetNodeConfig(nodeCfg.ShortName) if err != nil { return err } - // nodeCfg.Image = c.imageInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Image = c.Config.Topology.GetNodeImage(nodeCfg.ShortName) - // nodeCfg.Group = c.groupInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Group = c.Config.Topology.GetNodeGroup(nodeCfg.ShortName) - // nodeCfg.Position = c.positionInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Position = c.Config.Topology.GetNodePosition(nodeCfg.ShortName) nodeCfg.User = user diff --git a/clab/srl.go b/clab/srl.go index 5621760c4..50ce38443 100644 --- a/clab/srl.go +++ b/clab/srl.go @@ -63,30 +63,23 @@ func initSRLNode(c *CLab, nodeDef *types.NodeDefinition, nodeCfg *types.NodeConf return err } - // lp, err := c.licenseInit(nodeDef, nodeCfg) - lp, err := c.Config.Topology.GetNodeLicense(nodeCfg.ShortName) + nodeCfg.License, err = c.Config.Topology.GetNodeLicense(nodeCfg.ShortName) if err != nil { return err } - if lp == "" { + if nodeCfg.License == "" { return fmt.Errorf("no license found for node '%s' of kind '%s'", nodeCfg.ShortName, nodeCfg.Kind) } - nodeCfg.License = lp - - // nodeCfg.Image = c.imageInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Image = c.Config.Topology.GetNodeImage(nodeCfg.ShortName) - // nodeCfg.Group = c.groupInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Group = c.Config.Topology.GetNodeGroup(nodeCfg.ShortName) nodeCfg.NodeType = c.Config.Topology.GetNodeType(nodeCfg.ShortName) if nodeCfg.NodeType == "" { nodeCfg.NodeType = srlDefaultType } - // nodeCfg.NodeType = c.typeInit(nodeDef, nodeCfg.Kind) - // nodeCfg.Position = c.positionInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Position = c.Config.Topology.GetNodePosition(nodeCfg.ShortName) if filename, found := srlTypes[nodeCfg.NodeType]; found { - nodeCfg.Topology = baseConfigDir + filename + nodeCfg.Topology = path.Join(baseConfigDir, filename) } else { keys := make([]string, 0, len(srlTypes)) for key := range srlTypes { diff --git a/clab/vr-csr.go b/clab/vr-csr.go index fae299cab..c65706a32 100644 --- a/clab/vr-csr.go +++ b/clab/vr-csr.go @@ -14,11 +14,8 @@ import ( func initVrCSRNode(c *CLab, nodeDef *types.NodeDefinition, nodeCfg *types.NodeConfig, user string, envs map[string]string) error { var err error - // nodeCfg.Image = c.imageInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Image = c.Config.Topology.GetNodeImage(nodeCfg.ShortName) - // nodeCfg.Group = c.groupInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Group = c.Config.Topology.GetNodeGroup(nodeCfg.ShortName) - // nodeCfg.Position = c.positionInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Position = c.Config.Topology.GetNodePosition(nodeCfg.ShortName) nodeCfg.User = user diff --git a/clab/vr-ros.go b/clab/vr-ros.go index dca4455f7..f798cd6d0 100644 --- a/clab/vr-ros.go +++ b/clab/vr-ros.go @@ -14,11 +14,8 @@ import ( func initVrROSNode(c *CLab, nodeDef *types.NodeDefinition, nodeCfg *types.NodeConfig, user string, envs map[string]string) error { var err error - // nodeCfg.Image = c.imageInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Image = c.Config.Topology.GetNodeImage(nodeCfg.ShortName) - // nodeCfg.Group = c.groupInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Group = c.Config.Topology.GetNodeGroup(nodeCfg.ShortName) - // nodeCfg.Position = c.positionInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Position = c.Config.Topology.GetNodePosition(nodeCfg.ShortName) nodeCfg.User = user diff --git a/clab/vr-sros.go b/clab/vr-sros.go index b2cf9bfac..4d47085ff 100644 --- a/clab/vr-sros.go +++ b/clab/vr-sros.go @@ -15,33 +15,26 @@ import ( func initSROSNode(c *CLab, nodeDef *types.NodeDefinition, nodeCfg *types.NodeConfig, user string, envs map[string]string) error { var err error - // nodeCfg.Config, err = c.configInit(nodeDef, nodeCfg.Kind) + c.Config.Topology.GetNodeConfig(nodeCfg.ShortName) if err != nil { return err } - // nodeCfg.Image = c.imageInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Image = c.Config.Topology.GetNodeImage(nodeCfg.ShortName) - // nodeCfg.Group = c.groupInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Group = c.Config.Topology.GetNodeGroup(nodeCfg.ShortName) - // nodeCfg.Position = c.positionInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Position = c.Config.Topology.GetNodePosition(nodeCfg.ShortName) nodeCfg.User = user // vr-sros type sets the vrnetlab/sros variant (https://github.com/hellt/vrnetlab/sros) nodeCfg.NodeType = c.Config.Topology.GetNodeType(nodeCfg.ShortName) - //nodeCfg.NodeType = c.typeInit(nodeDef, nodeCfg.Kind) if nodeCfg.NodeType == "" { nodeCfg.NodeType = vrsrosDefaultType } // initialize license file - // lp, err := c.licenseInit(nodeDef, nodeCfg) - lp, err := c.Config.Topology.GetNodeLicense(nodeCfg.ShortName) + nodeCfg.License, err = c.Config.Topology.GetNodeLicense(nodeCfg.ShortName) if err != nil { return err } - nodeCfg.License = lp - // env vars are used to set launch.py arguments in vrnetlab container defEnv := map[string]string{ "CONNECTION_MODE": vrDefConnMode, diff --git a/clab/vr-veos.go b/clab/vr-veos.go index 20a7e9ecd..54f394f1e 100644 --- a/clab/vr-veos.go +++ b/clab/vr-veos.go @@ -13,11 +13,9 @@ import ( func initVrVeosNode(c *CLab, nodeDef *types.NodeDefinition, nodeCfg *types.NodeConfig, user string, envs map[string]string) error { var err error - // nodeCfg.Image = c.imageInitialization(nodeDef, nodeCfg.Kind) + nodeCfg.Image = c.Config.Topology.GetNodeImage(nodeCfg.ShortName) - // nodeCfg.Group = c.groupInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Group = c.Config.Topology.GetNodeGroup(nodeCfg.ShortName) - // nodeCfg.Position = c.positionInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Position = c.Config.Topology.GetNodePosition(nodeCfg.ShortName) nodeCfg.User = user diff --git a/clab/vr-vmx.go b/clab/vr-vmx.go index adaea54ad..3e0f2a75e 100644 --- a/clab/vr-vmx.go +++ b/clab/vr-vmx.go @@ -13,11 +13,8 @@ import ( func initVrVMXNode(c *CLab, nodeDef *types.NodeDefinition, nodeCfg *types.NodeConfig, user string, envs map[string]string) error { var err error - // nodeCfg.Image = c.imageInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Image = c.Config.Topology.GetNodeImage(nodeCfg.ShortName) - // nodeCfg.Group = c.groupInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Group = c.Config.Topology.GetNodeGroup(nodeCfg.ShortName) - // nodeCfg.Position = c.positionInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Position = c.Config.Topology.GetNodePosition(nodeCfg.ShortName) nodeCfg.User = user diff --git a/clab/vr-xrv.go b/clab/vr-xrv.go index 515d32b8f..4b87e4bf6 100644 --- a/clab/vr-xrv.go +++ b/clab/vr-xrv.go @@ -14,11 +14,8 @@ import ( func initVrXRVNode(c *CLab, nodeDef *types.NodeDefinition, nodeCfg *types.NodeConfig, user string, envs map[string]string) error { var err error - // nodeCfg.Image = c.imageInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Image = c.Config.Topology.GetNodeImage(nodeCfg.ShortName) - // nodeCfg.Group = c.groupInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Group = c.Config.Topology.GetNodeGroup(nodeCfg.ShortName) - // nodeCfg.Position = c.positionInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Position = c.Config.Topology.GetNodePosition(nodeCfg.ShortName) nodeCfg.User = user diff --git a/clab/vr-xrv9k.go b/clab/vr-xrv9k.go index d90a69040..ce77802bd 100644 --- a/clab/vr-xrv9k.go +++ b/clab/vr-xrv9k.go @@ -14,11 +14,8 @@ import ( func initVrXRV9kNode(c *CLab, nodeDef *types.NodeDefinition, nodeCfg *types.NodeConfig, user string, envs map[string]string) error { var err error - // nodeCfg.Image = c.imageInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Image = c.Config.Topology.GetNodeImage(nodeCfg.ShortName) - // nodeCfg.Group = c.groupInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Group = c.Config.Topology.GetNodeGroup(nodeCfg.ShortName) - // nodeCfg.Position = c.positionInitialization(nodeDef, nodeCfg.Kind) nodeCfg.Position = c.Config.Topology.GetNodePosition(nodeCfg.ShortName) nodeCfg.User = user diff --git a/types/topology.go b/types/topology.go index 703cbc2a0..8876f248c 100644 --- a/types/topology.go +++ b/types/topology.go @@ -56,6 +56,9 @@ func (t *Topology) GetKinds() map[string]*NodeDefinition { } func (t *Topology) GetNodeKind(name string) string { + if t == nil { + return "" + } if ndef, ok := t.Nodes[name]; ok { if ndef.GetKind() != "" { return ndef.GetKind() diff --git a/types/topology_test.go b/types/topology_test.go new file mode 100644 index 000000000..21047d96b --- /dev/null +++ b/types/topology_test.go @@ -0,0 +1,137 @@ +package types + +import "testing" + +var topologyTestSet = map[string]struct { + input *Topology + want map[string]*NodeDefinition +}{ + "node_only": { + input: &Topology{ + Nodes: map[string]*NodeDefinition{ + "node1": { + Kind: "srl", + }, + }, + }, + want: map[string]*NodeDefinition{ + "node1": { + Kind: "srl", + }, + }, + }, + "node_kind": { + input: &Topology{ + Kinds: map[string]*NodeDefinition{ + "srl": { + Group: "grp1", + Type: "type1", + Config: "config.cfg", + Image: "image:latest", + License: "lic1.key", + Position: "pos1", + Cmd: "runit", + Binds: []string{ + "a:b", + "c:d", + }, + Ports: []string{ + "80:8080", + }, + Env: map[string]string{ + "env1": "v1", + "env2": "v2", + }, + Labels: map[string]string{ + "label1": "v1", + "label2": "v2", + }, + }, + }, + Nodes: map[string]*NodeDefinition{ + "node1": { + Kind: "srl", + Env: map[string]string{ + "env2": "notv2", + }, + Labels: map[string]string{ + "label2": "notv2", + }, + }, + }, + }, + want: map[string]*NodeDefinition{ + "node1": { + Kind: "srl", + Group: "grp1", + Type: "type1", + Config: "config.cfg", + Image: "image:latest", + License: "lic1.key", + Position: "pos1", + Cmd: "runit", + Binds: []string{ + "a:b", + "c:d", + }, + Ports: []string{ + "80:8080", + }, + Env: map[string]string{ + "env1": "v1", + "env2": "notv2", + }, + Labels: map[string]string{ + "label1": "v1", + "label2": "notv2", + }, + }, + }, + }, + "node_kind_default": { + input: &Topology{ + Defaults: &NodeDefinition{ + Kind: "srl", + }, + Kinds: map[string]*NodeDefinition{ + "srl": { + Group: "grp1", + Type: "type1", + Config: "config.cfg", + Image: "image:latest", + License: "lic1.key", + Position: "pos1", + Cmd: "runit", + }, + }, + Nodes: map[string]*NodeDefinition{ + "node1": {}, + }, + }, + want: map[string]*NodeDefinition{ + "node1": { + Kind: "srl", + Group: "grp1", + Type: "type1", + Config: "config.cfg", + Image: "image:latest", + License: "lic1.key", + Position: "pos1", + Cmd: "runit", + }, + }, + }, +} + +func TestGetNodeKind(t *testing.T) { + for name, item := range topologyTestSet { + t.Logf("%q test item", name) + kind := item.input.GetNodeKind("node1") + if item.want["node1"].Kind != kind { + t.Errorf("item %q failed", name) + t.Errorf("item %q exp %q", name, item.want["node1"].Kind) + t.Errorf("item %q got %q", name, kind) + t.Fail() + } + } +}