diff --git a/deploy/deploy.go b/deploy/deploy.go index a8ce993d..b84e9959 100644 --- a/deploy/deploy.go +++ b/deploy/deploy.go @@ -220,25 +220,25 @@ func (d *Deployment) Deploy(ctx context.Context, kubecfg string) (rerr error) { defer func() { finish(rerr) }() } if err := d.checkDependencies(); err != nil { - return err + return fmt.Errorf("failed to check for dependencies: %w", err) } log.Infof("Deploying cluster...") if err := d.Cluster.Deploy(ctx); err != nil { - return err + return fmt.Errorf("failed to deploy cluster: %w", err) } log.Infof("Cluster deployed") if err := d.Cluster.Healthy(); err != nil { - return err + return fmt.Errorf("failed to check cluster is healthy: %w", err) } log.Infof("Cluster healthy") // Once cluster is up, set kClient rCfg, err := clientcmd.BuildConfigFromFlags("", kubecfg) if err != nil { - return err + return fmt.Errorf("failed to create k8s config: %w", err) } kClient, err := kubernetes.NewForConfig(rCfg) if err != nil { - return err + return fmt.Errorf("failed to create k8s client: %w", err) } log.Infof("Checking kubectl versions.") @@ -252,11 +252,11 @@ func (d *Deployment) Deploy(ctx context.Context, kubecfg string) (rerr error) { } kClientVersion, err := getVersion(kubeYAML.ClientVersion.GitVersion) if err != nil { - return err + return fmt.Errorf("failed to parse k8s client version: %w", err) } kServerVersion, err := getVersion(kubeYAML.ServerVersion.GitVersion) if err != nil { - return err + return fmt.Errorf("failed to parse k8s server version: %w", err) } origMajor := kClientVersion.Major kClientVersion.Major -= 2 @@ -298,35 +298,35 @@ func (d *Deployment) Deploy(ctx context.Context, kubecfg string) (rerr error) { log.Infof("Deploying ingress...") if err := d.Ingress.Deploy(ctx); err != nil { - return err + return fmt.Errorf("failed to deploy ingress: %w", err) } tCtx, cancel := context.WithTimeout(ctx, healthTimeout) defer cancel() if err := d.Ingress.Healthy(tCtx); err != nil { - return err + return fmt.Errorf("failed to check ingress is healthy: %w", err) } log.Infof("Ingress healthy") log.Infof("Deploying CNI...") if err := d.CNI.Deploy(ctx); err != nil { - return err + return fmt.Errorf("failed to deploy CNI: %w", err) } d.CNI.SetKClient(kClient) tCtx, cancel = context.WithTimeout(ctx, healthTimeout) defer cancel() if err := d.CNI.Healthy(tCtx); err != nil { - return err + return fmt.Errorf("failed to check CNI is healthy: %w", err) } log.Infof("CNI healthy") for _, c := range d.Controllers { log.Infof("Deploying controller...") if err := c.Deploy(ctx); err != nil { - return err + return fmt.Errorf("failed to deploy controller: %w", err) } c.SetKClient(kClient) tCtx, cancel = context.WithTimeout(ctx, healthTimeout) defer cancel() if err := c.Healthy(tCtx); err != nil { - return err + return fmt.Errorf("failed to check controller is healthy: %w", err) } } log.Infof("Controllers deployed and healthy") @@ -336,7 +336,7 @@ func (d *Deployment) Deploy(ctx context.Context, kubecfg string) (rerr error) { func (d *Deployment) Delete() error { log.Infof("Deleting cluster...") if err := d.Cluster.Delete(); err != nil { - return err + return fmt.Errorf("failed to delete cluster: %w", err) } log.Infof("Cluster deleted") return nil @@ -344,26 +344,26 @@ func (d *Deployment) Delete() error { func (d *Deployment) Healthy(ctx context.Context) error { if err := d.Cluster.Healthy(); err != nil { - return err + return fmt.Errorf("failed to check cluster is healthy: %w", err) } log.Infof("Cluster healthy") tCtx, cancel := context.WithTimeout(ctx, healthTimeout) defer cancel() if err := d.Ingress.Healthy(tCtx); err != nil { - return err + return fmt.Errorf("failed to check ingress is healthy: %w", err) } log.Infof("Ingress healthy") tCtx, cancel = context.WithTimeout(ctx, healthTimeout) defer cancel() if err := d.CNI.Healthy(tCtx); err != nil { - return err + return fmt.Errorf("failed to check CNI is healthy: %w", err) } log.Infof("CNI healthy") for _, c := range d.Controllers { tCtx, cancel = context.WithTimeout(ctx, healthTimeout) defer cancel() if err := c.Healthy(tCtx); err != nil { - return err + return fmt.Errorf("failed to check controller is healthy: %w", err) } } log.Infof("Controllers healthy") @@ -488,7 +488,7 @@ func (k *KindSpec) checkDependencies() error { if k.Version != "" { wantV, err := getVersion(k.Version) if err != nil { - return err + return fmt.Errorf("failed to parse desired kind version: %w", err) } stdout, err := outCommand("kind", "version") @@ -545,8 +545,9 @@ func (k *KindSpec) create() error { args = append(args, "--config", k.KindConfigFile) } log.Infof("Creating kind cluster with: %v", args) + // TODO if err := logCommand("kind", args...); err != nil { - return fmt.Errorf("failed to create cluster: %w", err) + return err } log.Infof("Deployed kind cluster: %s", k.Name) return nil @@ -554,11 +555,11 @@ func (k *KindSpec) create() error { func (k *KindSpec) Deploy(ctx context.Context) error { if err := k.checkDependencies(); err != nil { - return err + return fmt.Errorf("failed to check for dependencies: %w", err) } if err := k.create(); err != nil { - return err + return fmt.Errorf("failed to create kind cluster: %w", err) } // If the script is found, then run it. Else silently ignore it. @@ -566,7 +567,7 @@ func (k *KindSpec) Deploy(ctx context.Context) error { // be acceptable for the Cisco 8000e container. if _, err := os.Stat(setPIDMaxScript); err == nil { if err := logCommand(setPIDMaxScript); err != nil { - return err + return fmt.Errorf("failed to exec set_pid_max script: %w", err) } } @@ -600,7 +601,7 @@ func (k *KindSpec) Delete() error { args = append(args, "--name", k.Name) } if err := logCommand("kind", args...); err != nil { - return fmt.Errorf("failed to delete cluster using cli: %w", err) + return fmt.Errorf("failed to delete cluster: %w", err) } return nil } @@ -820,13 +821,13 @@ func (m *MetalLBSpec) Deploy(ctx context.Context) error { if m.dClient == nil { m.dClient, err = dclient.NewClientWithOpts(dclient.FromEnv) if err != nil { - return err + return fmt.Errorf("failed to create docker client: %w", err) } } if m.mClient == nil { m.mClient, err = metallbclientv1.NewForConfig(m.rCfg) if err != nil { - return err + return fmt.Errorf("failed to create metallb client: %w", err) } } @@ -851,7 +852,7 @@ func (m *MetalLBSpec) Deploy(ctx context.Context) error { } log.Infof("Deploying MetalLB from: %s", m.Manifest) if err := logCommand("kubectl", "apply", "-f", m.Manifest); err != nil { - return err + return fmt.Errorf("failed to deploy metallb: %w", err) } if _, err := m.kClient.CoreV1().Secrets("metallb-system").Get(ctx, "memberlist", metav1.GetOptions{}); err != nil { log.Infof("Creating metallb secret") @@ -868,13 +869,13 @@ func (m *MetalLBSpec) Deploy(ctx context.Context) error { }, } if _, err := m.kClient.CoreV1().Secrets("metallb-system").Create(ctx, s, metav1.CreateOptions{}); err != nil { - return err + return fmt.Errorf("failed to create metallb secret: %w", err) } } // Wait for metallb to be healthy if err := m.Healthy(ctx); err != nil { - return err + return fmt.Errorf("metallb not healthy: %w", err) } if _, err = m.mClient.IPAddressPool("metallb-system").Get(ctx, "kne-service-pool", metav1.GetOptions{}); err != nil { @@ -882,7 +883,7 @@ func (m *MetalLBSpec) Deploy(ctx context.Context) error { // Get Network information from docker. nr, err := m.dClient.NetworkList(ctx, dtypes.NetworkListOptions{}) if err != nil { - return err + return fmt.Errorf("failed to get docker network list: %w", err) } var network dtypes.NetworkResource for _, v := range nr { @@ -899,7 +900,7 @@ func (m *MetalLBSpec) Deploy(ctx context.Context) error { for _, ipRange := range network.IPAM.Config { _, ipNet, err := net.ParseCIDR(ipRange.Subnet) if err != nil { - return err + return fmt.Errorf("failed to parse cidr: %w", err) } if ipNet.IP.To4() != nil { n = ipNet @@ -932,7 +933,7 @@ func (m *MetalLBSpec) Deploy(ctx context.Context) error { }, } if _, err = m.mClient.L2Advertisement("metallb-system").Create(ctx, l2Advert, metav1.CreateOptions{}); err != nil { - return err + return fmt.Errorf("failed to create metallb L2 advertisement: %w", err) } } return nil @@ -981,7 +982,7 @@ func (m *MeshnetSpec) Deploy(ctx context.Context) error { } log.Infof("Deploying Meshnet from: %s", m.Manifest) if err := logCommand("kubectl", "apply", "-f", m.Manifest); err != nil { - return err + return fmt.Errorf("failed to deploy meshnet: %w", err) } log.Infof("Meshnet Deployed") return nil @@ -998,10 +999,10 @@ func (m *MeshnetSpec) Healthy(ctx context.Context) error { for { select { case <-ctx.Done(): - return fmt.Errorf("context canceled before healthy") + return fmt.Errorf("context canceled before meshnet healthy") case e, ok := <-w.ResultChan(): if !ok { - return fmt.Errorf("watch channel closed before healthy") + return fmt.Errorf("watch channel closed before meshnet healthy") } d, ok := e.Object.(*appsv1.DaemonSet) if !ok { @@ -1055,7 +1056,7 @@ func (c *CEOSLabSpec) Deploy(ctx context.Context) error { } log.Infof("Deploying CEOSLab controller from: %s", c.Operator) if err := logCommand("kubectl", "apply", "-f", c.Operator); err != nil { - return err + return fmt.Errorf("failed to deploy ceoslab operator: %w", err) } log.Infof("CEOSLab controller deployed") return nil @@ -1104,7 +1105,7 @@ func (l *LemmingSpec) Deploy(ctx context.Context) error { } log.Infof("Deploying Lemming controller from: %s", l.Operator) if err := logCommand("kubectl", "apply", "-f", l.Operator); err != nil { - return err + return fmt.Errorf("failed to deploy lemming operator: %w", err) } log.Infof("Lemming controller deployed") return nil @@ -1153,7 +1154,7 @@ func (s *SRLinuxSpec) Deploy(ctx context.Context) error { } log.Infof("Deploying SRLinux controller from: %s", s.Operator) if err := logCommand("kubectl", "apply", "-f", s.Operator); err != nil { - return err + return fmt.Errorf("failed to deploy srlinux operator: %w", err) } log.Infof("SRLinux controller deployed") return nil @@ -1204,7 +1205,7 @@ func (i *IxiaTGSpec) Deploy(ctx context.Context) error { } log.Infof("Deploying IxiaTG controller from: %s", i.Operator) if err := logCommand("kubectl", "apply", "-f", i.Operator); err != nil { - return err + return fmt.Errorf("failed to deploy ixiatg operator: %w", err) } if i.ConfigMap == "" && i.ManifestDir != "" { @@ -1238,7 +1239,7 @@ func (i *IxiaTGSpec) Deploy(ctx context.Context) error { } log.Infof("Deploying IxiaTG config map from: %s", i.ConfigMap) if err := logCommand("kubectl", "apply", "-f", i.ConfigMap); err != nil { - return err + return fmt.Errorf("failed to deploy ixiatg config map: %w", err) } log.Infof("IxiaTG controller deployed") return nil @@ -1252,16 +1253,16 @@ func deploymentHealthy(ctx context.Context, c kubernetes.Interface, name string) log.Infof("Waiting on deployment %q to be healthy", name) w, err := c.AppsV1().Deployments(name).Watch(ctx, metav1.ListOptions{}) if err != nil { - return err + return fmt.Errorf("failed to create watcher for deployment %q", name) } ch := w.ResultChan() for { select { case <-ctx.Done(): - return fmt.Errorf("context canceled before healthy") + return fmt.Errorf("context canceled before %q healthy", name) case e, ok := <-ch: if !ok { - return fmt.Errorf("watch channel closed before healthy") + return fmt.Errorf("watch channel closed before %q healthy", name) } d, ok := e.Object.(*appsv1.Deployment) if !ok { diff --git a/topo/node/node.go b/topo/node/node.go index 7072c493..f9dc7e6d 100644 --- a/topo/node/node.go +++ b/topo/node/node.go @@ -32,6 +32,7 @@ type Interface interface { Name() string GetNamespace() string GetProto() *tpb.Node + String() string } type Implementation interface { @@ -140,6 +141,10 @@ func (n *Impl) GetNamespace() string { return n.Namespace } +func (n *Impl) String() string { + return fmt.Sprintf("%q (vendor: %q, model: %q)", n.Proto.Name, n.Proto.Vendor, n.Proto.Model) +} + func (n *Impl) TopologySpecs(context.Context) ([]*topologyv1.Topology, error) { proto := n.GetProto() diff --git a/topo/topo.go b/topo/topo.go index 11e39a08..36d95209 100644 --- a/topo/topo.go +++ b/topo/topo.go @@ -254,10 +254,10 @@ func (m *Manager) Create(ctx context.Context, timeout time.Duration) (rerr error }() } if err := m.push(ctx); err != nil { - return err + return fmt.Errorf("failed to create topology %q: %w", m.topo.GetName(), err) } if err := m.checkNodeStatus(ctx, timeout); err != nil { - return err + return fmt.Errorf("failed to check status of nodes in topology %q: %w", m.topo.GetName(), err) } log.Infof("Topology %q created", m.topo.GetName()) return nil @@ -279,12 +279,15 @@ func (m *Manager) Delete(ctx context.Context) error { } if err := m.deleteMeshnetTopologies(ctx); err != nil { - return err + return fmt.Errorf("failed to delete meshnet topologies for topology %q: %w", m.topo.GetName(), err) } // Delete namespace prop := metav1.DeletePropagationForeground - return m.kClient.CoreV1().Namespaces().Delete(ctx, m.topo.Name, metav1.DeleteOptions{PropagationPolicy: &prop}) + if err := m.kClient.CoreV1().Namespaces().Delete(ctx, m.topo.Name, metav1.DeleteOptions{PropagationPolicy: &prop}); err != nil { + return fmt.Errorf("failed to delete namespace %q: %w", m.topo.Name, err) + } + return nil } // Show returns the topology information including services and node health. @@ -470,27 +473,27 @@ func (m *Manager) push(ctx context.Context) error { } sNs, err := m.kClient.CoreV1().Namespaces().Create(ctx, ns, metav1.CreateOptions{}) if err != nil { - return err + return fmt.Errorf("failed to create namespace %q: %w", ns, err) } log.Infof("Server Namespace: %+v", sNs) } if err := m.createMeshnetTopologies(ctx); err != nil { - return err + return fmt.Errorf("failed to create meshnet topologies: %w", err) } log.Infof("Creating Node Pods") - for k, n := range m.nodes { + for _, n := range m.nodes { if err := n.Create(ctx); err != nil { - return err + return fmt.Errorf("failed to create node %s: %w", n, err) } - log.Infof("Node %q resource created", k) + log.Infof("Node %s resource created", n) } for _, n := range m.nodes { err := m.GenerateSelfSigned(ctx, n.Name()) switch { default: - return fmt.Errorf("failed to generate cert for node %s: %w", n.Name(), err) + return fmt.Errorf("failed to generate cert for node %s: %w", n, err) case err == nil, status.Code(err) == codes.Unimplemented: } } @@ -549,10 +552,10 @@ func (m *Manager) checkNodeStatus(ctx context.Context, timeout time.Duration) er phase, err := n.Status(ctx) if err != nil || phase == node.StatusFailed { - return fmt.Errorf("Node %q: Status %s Reason %v", name, phase, err) + return fmt.Errorf("Node %s: Status %s Reason %v", n, phase, err) } if phase == node.StatusRunning { - log.Infof("Node %q: Status %s", name, phase) + log.Infof("Node %s: Status %s", n, phase) processed[name] = true } else { foundAll = false diff --git a/topo/topo_test.go b/topo/topo_test.go index 16f1c4cc..4297ede0 100644 --- a/topo/topo_test.go +++ b/topo/topo_test.go @@ -502,7 +502,7 @@ func TestCreate(t *testing.T) { }, }, }, - wantErr: `Node "bad": Status FAILED`, + wantErr: `Node "bad" (vendor: "1002", model: ""): Status FAILED`, }, { desc: "failed to report metrics, create still passes", opts: []Option{WithUsageReporting(true, "", "")},