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

Decouple cmd package from the clab application part2 #1944

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
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
6 changes: 3 additions & 3 deletions clab/authz_keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const (
func (c *CLab) createAuthzKeysFile() error {
b := new(bytes.Buffer)

for _, k := range c.SSHPubKeys {
for _, k := range c.sSHPubKeys {
x := strings.TrimSpace(string(ssh.MarshalAuthorizedKey(k)))
addKeyToBuffer(b, x)
}
Expand Down Expand Up @@ -70,9 +70,9 @@ func RetrieveSSHPubKeysFromFiles() ([]ssh.PublicKey, error) {
return keys, nil
}

// RetrieveSSHPubKeys retrieves the PubKeys from the different sources
// retrieveSSHPubKeys retrieves the PubKeys from the different sources
// SSHAgent as well as all home dir based /.ssh/*.pub files.
func (c *CLab) RetrieveSSHPubKeys() ([]ssh.PublicKey, error) {
func (c *CLab) retrieveSSHPubKeys() ([]ssh.PublicKey, error) {
keys := make([]ssh.PublicKey, 0)

var errs error
Expand Down
12 changes: 6 additions & 6 deletions clab/cert.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,25 @@ import (
"github.com/srl-labs/containerlab/cert"
)

// LoadOrGenerateCA loads the CA certificate from the storage, or generates a new one if it does not exist.
func (c *CLab) LoadOrGenerateCA(caCertInput *cert.CACSRInput) error {
// loadOrGenerateCA loads the CA certificate from the storage, or generates a new one if it does not exist.
func (c *CLab) loadOrGenerateCA(caCertInput *cert.CACSRInput) error {
// try loading the CA cert, and if it fails, generate a new one
caCertificate, err := c.Cert.LoadCaCert()
caCertificate, err := c.cert.LoadCaCert()
if err != nil {
// if loading certs failed, try to generate new RootCA
caCertificate, err = c.Cert.GenerateCACert(caCertInput)
caCertificate, err = c.cert.GenerateCACert(caCertInput)
if err != nil {
return fmt.Errorf("failed generating new Root CA %v", err)
}
// store the root CA
err = c.Cert.StoreCaCert(caCertificate)
err = c.cert.StoreCaCert(caCertificate)
if err != nil {
return nil
}
}

// set CA cert that was either loaded or generated
err = c.Cert.SetCACert(caCertificate)
err = c.cert.SetCACert(caCertificate)
if err != nil {
return nil
}
Expand Down
70 changes: 17 additions & 53 deletions clab/clab.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
depMgr "github.com/srl-labs/containerlab/clab/dependency_manager"
"github.com/srl-labs/containerlab/clab/exec"
errs "github.com/srl-labs/containerlab/errors"
_ "github.com/srl-labs/containerlab/kinds/all"
"github.com/srl-labs/containerlab/links"
"github.com/srl-labs/containerlab/nodes"
"github.com/srl-labs/containerlab/runtime"
Expand All @@ -39,15 +40,13 @@ type CLab struct {
TopoPaths *types.TopoPaths
Nodes map[string]nodes.Node `json:"nodes,omitempty"`
Links map[int]links.Link `json:"links,omitempty"`
Endpoints []links.Endpoint
endpoints []links.Endpoint
Runtimes map[string]runtime.ContainerRuntime `json:"runtimes,omitempty"`
// reg is a registry of node kinds
Reg *nodes.NodeRegistry
Cert *cert.Cert
cert *cert.Cert
// List of SSH public keys extracted from the ~/.ssh/authorized_keys file
// and ~/.ssh/*.pub files.
// The keys are used to enable key-based SSH access for the nodes.
SSHPubKeys []ssh.PublicKey
sSHPubKeys []ssh.PublicKey

dependencyManager depMgr.DependencyManager
m *sync.RWMutex
Expand Down Expand Up @@ -176,49 +175,18 @@ func WithKeepMgmtNet() ClabOption {

func WithTopoPath(path, varsFile string) ClabOption {
return func(c *CLab) error {
file, err := c.ProcessTopoPath(path)
file, err := ProcessTopoPath(path, c.TopoPaths.ClabTmpDir())
if err != nil {
return err
}
if err := c.LoadTopologyFromFile(file, varsFile); err != nil {
if err := c.loadTopologyFromFile(file, varsFile); err != nil {
return fmt.Errorf("failed to read topology file: %v", err)
}

return c.initMgmtNetwork()
}
}

// ProcessTopoPath takes a topology path, which might be the path to a directory or a file
// or stdin or a URL and returns the topology file name if found.
func (c *CLab) ProcessTopoPath(path string) (string, error) {
var file string
var err error

switch {
case path == "-" || path == "stdin":
file, err = readFromStdin(c.TopoPaths.ClabTmpDir())
if err != nil {
return "", err
}
// if the path is not a local file and a URL, download the file and store it in the tmp dir
case !utils.FileOrDirExists(path) && utils.IsHttpURL(path, true):
file, err = downloadTopoFile(path, c.TopoPaths.ClabTmpDir())
if err != nil {
return "", err
}

case path == "":
return "", fmt.Errorf("provide a path to the clab topology file")

default:
file, err = FindTopoFileByPath(path)
if err != nil {
return "", err
}
}
return file, nil
}

// FindTopoFileByPath takes a topology path, which might be the path to a directory
// and returns the topology file name if found.
func FindTopoFileByPath(path string) (string, error) {
Expand Down Expand Up @@ -337,13 +305,9 @@ func NewContainerLab(opts ...ClabOption) (*CLab, error) {
Nodes: make(map[string]nodes.Node),
Links: make(map[int]links.Link),
Runtimes: make(map[string]runtime.ContainerRuntime),
Cert: &cert.Cert{},
cert: &cert.Cert{},
}

// init a new NodeRegistry
c.Reg = nodes.NewNodeRegistry()
c.RegisterNodes()

for _, opt := range opts {
err := opt(c)
if err != nil {
Expand Down Expand Up @@ -574,10 +538,10 @@ func (c *CLab) scheduleNodes(ctx context.Context, maxWorkers int, skipPostDeploy
err := node.PreDeploy(
ctx,
&nodes.PreDeployParams{
Cert: c.Cert,
Cert: c.cert,
TopologyName: c.Config.Name,
TopoPaths: c.TopoPaths,
SSHPubKeys: c.SSHPubKeys,
SSHPubKeys: c.sSHPubKeys,
},
)
if err != nil {
Expand Down Expand Up @@ -911,7 +875,7 @@ func (c *CLab) ResolveLinks() error {
continue
}

c.Endpoints = append(c.Endpoints, l.GetEndpoints()...)
c.endpoints = append(c.endpoints, l.GetEndpoints()...)
c.Links[i] = l
}

Expand Down Expand Up @@ -1020,7 +984,7 @@ func (c *CLab) Deploy(ctx context.Context, options *DeployOptions) ([]runtime.Ge
return nil, err
}

c.SSHPubKeys, err = c.RetrieveSSHPubKeys()
c.sSHPubKeys, err = c.retrieveSSHPubKeys()
if err != nil {
log.Warn(err)
}
Expand Down Expand Up @@ -1077,7 +1041,7 @@ func (c *CLab) Deploy(ctx context.Context, options *DeployOptions) ([]runtime.Ge
return nil, err
}

if err := c.GenerateExports(ctx, topoDataF, options.exportTemplate); err != nil {
if err := c.generateExports(ctx, topoDataF, options.exportTemplate); err != nil {
return nil, err
}

Expand Down Expand Up @@ -1111,8 +1075,8 @@ func (c *CLab) Deploy(ctx context.Context, options *DeployOptions) ([]runtime.Ge
// certificateAuthoritySetup sets up the certificate authority parameters.
func (c *CLab) certificateAuthoritySetup() error {
// init the Cert storage and CA
c.Cert.CertStorage = cert.NewLocalDirCertStorage(c.TopoPaths)
c.Cert.CA = cert.NewCA()
c.cert.CertStorage = cert.NewLocalDirCertStorage(c.TopoPaths)
c.cert.CA = cert.NewCA()

s := c.Config.Settings

Expand Down Expand Up @@ -1162,7 +1126,7 @@ func (c *CLab) certificateAuthoritySetup() error {
KeySize: keySize,
}

return c.LoadOrGenerateCA(caCertInput)
return c.loadOrGenerateCA(caCertInput)
}

// Destroy the given topology.
Expand Down Expand Up @@ -1199,13 +1163,13 @@ func (c *CLab) Destroy(ctx context.Context, maxWorkers uint, keepMgmtNet bool) e
c.deleteNodes(ctx, maxWorkers, serialNodes)

log.Info("Removing containerlab host entries from /etc/hosts file")
err = c.DeleteEntriesFromHostsFile()
err = c.deleteEntriesFromHostsFile()
if err != nil {
return fmt.Errorf("error while trying to clean up the hosts file: %w", err)
}

log.Info("Removing ssh config for containerlab nodes")
err = c.RemoveSSHConfig(c.TopoPaths)
err = c.removeSSHConfig(c.TopoPaths)
if err != nil {
log.Errorf("failed to remove ssh config file: %v", err)
}
Expand Down
23 changes: 6 additions & 17 deletions clab/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (

"github.com/pmorjan/kmod"
log "github.com/sirupsen/logrus"
"github.com/srl-labs/containerlab/kinds/kind_registry"
"github.com/srl-labs/containerlab/labels"
"github.com/srl-labs/containerlab/links"
"github.com/srl-labs/containerlab/nodes"
Expand Down Expand Up @@ -117,7 +118,7 @@ func (c *CLab) parseTopology() error {
}

for idx, nodeName := range nodeNames {
err = c.NewNode(nodeName, nodeRuntimes[nodeName], c.Config.Topology.Nodes[nodeName], idx)
err = c.newNode(nodeName, nodeRuntimes[nodeName], c.Config.Topology.Nodes[nodeName], idx)
if err != nil {
return err
}
Expand All @@ -126,15 +127,15 @@ func (c *CLab) parseTopology() error {
return nil
}

// NewNode initializes a new node object.
func (c *CLab) NewNode(nodeName, nodeRuntime string, nodeDef *types.NodeDefinition, idx int) error {
// newNode initializes a new node object.
func (c *CLab) newNode(nodeName, nodeRuntime string, nodeDef *types.NodeDefinition, idx int) error {
nodeCfg, err := c.createNodeCfg(nodeName, nodeDef, idx)
if err != nil {
return err
}

// construct node
n, err := c.Reg.NewNodeOfKind(nodeCfg.Kind)
n, err := kind_registry.KindRegistryInstance.NewNodeOfKind(nodeCfg.Kind)
if err != nil {
return fmt.Errorf("error constructing node %q: %v", nodeCfg.ShortName, err)
}
Expand Down Expand Up @@ -375,7 +376,7 @@ func (c *CLab) verifyRootNetNSLinks() error {
func (c *CLab) verifyLinks(ctx context.Context) error {
var err error
verificationErrors := []error{}
for _, e := range c.Endpoints {
for _, e := range c.endpoints {
err = e.Verify(ctx, c.globalRuntime().Config().VerifyLinkParams)
if err != nil {
verificationErrors = append(verificationErrors, err)
Expand Down Expand Up @@ -527,18 +528,6 @@ func (c *CLab) resolveBindPaths(binds []string, nodedir string) error {
return nil
}

// HasKind returns true if kind k is found in the list of nodes.
func (c *CLab) HasKind(k string) bool {
for _, n := range c.Nodes {
if n.Config().Kind == k {
log.Warn("found")
return true
}
}

return false
}

// addDefaultLabels adds default labels to node's config struct.
func (c *CLab) addDefaultLabels(n nodes.Node) {
cfg := n.Config()
Expand Down
3 changes: 2 additions & 1 deletion clab/config/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

log "github.com/sirupsen/logrus"
"github.com/srl-labs/containerlab/clab"
"github.com/srl-labs/containerlab/kinds/kind_registry"
"github.com/srl-labs/containerlab/types"
)

Expand Down Expand Up @@ -64,7 +65,7 @@ func PrepareVars(c *clab.CLab) map[string]*NodeConfig {
vars[vkRole] = nodeCfg.Kind
}

creds := c.Reg.Kind(nodeCfg.Kind).Credentials().Slice()
creds := kind_registry.KindRegistryInstance.Kind(nodeCfg.Kind).Credentials().Slice()

res[name] = &NodeConfig{
TargetNode: nodeCfg,
Expand Down
4 changes: 2 additions & 2 deletions clab/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ import (
"github.com/srl-labs/containerlab/types"
)

// GenerateExports generates various export files and writes it to a lab location.
func (c *CLab) GenerateExports(ctx context.Context, f io.Writer, p string) error {
// generateExports generates various export files and writes it to a lab location.
func (c *CLab) generateExports(ctx context.Context, f io.Writer, p string) error {
err := c.exportTopologyDataWithTemplate(ctx, f, p)
if err != nil {
log.Warningf("Cannot parse export template %s: %v", p, err)
Expand Down
5 changes: 2 additions & 3 deletions clab/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,9 @@ const (
varFileSuffix = "_vars"
)

// LoadTopologyFromFile loads a topology by the topo file path
// parses the topology file into c.Conf structure
// loadTopology parses the topology file into c.Conf structure
// as well as populates the TopoFile structure with the topology file related information.
func (c *CLab) LoadTopologyFromFile(topo, varsFile string) error {
func (c *CLab) loadTopologyFromFile(topo, varsFile string) error {
var err error

c.TopoPaths, err = types.NewTopoPaths(topo)
Expand Down
5 changes: 3 additions & 2 deletions clab/hostsfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func (c *CLab) appendHostsFileEntries(ctx context.Context) error {
}
}
// lets make sure to remove the entries of a non-properly destroyed lab in the hosts file
err := c.DeleteEntriesFromHostsFile()
err := c.deleteEntriesFromHostsFile()
if err != nil {
return err
}
Expand Down Expand Up @@ -87,7 +87,8 @@ func generateHostsEntries(containers []runtime.GenericContainer, labname string)
return entries.Bytes()
}

func (c *CLab) DeleteEntriesFromHostsFile() error {
func (c *CLab) deleteEntriesFromHostsFile() error {

if c.Config.Name == "" {
return errors.New("missing containerlab name")
}
Expand Down
3 changes: 2 additions & 1 deletion clab/inventory.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"sort"
"text/template"

"github.com/srl-labs/containerlab/kinds/kind_registry"
"github.com/srl-labs/containerlab/types"
)

Expand Down Expand Up @@ -74,7 +75,7 @@ func (c *CLab) generateAnsibleInventory(w io.Writer) error {

// add username and password to kind properties
// assumption is that all nodes of the same kind have the same credentials
nodeRegEntry := c.Reg.Kind(n.Config().Kind)
nodeRegEntry := kind_registry.KindRegistryInstance.Kind(n.Config().Kind)
if nodeRegEntry != nil {
kindProps.Username = nodeRegEntry.Credentials().GetUsername()
kindProps.Password = nodeRegEntry.Credentials().GetPassword()
Expand Down
Loading
Loading