diff --git a/topo/node/arista/arista.go b/topo/node/arista/arista.go index e9c1c2a7..d43ca6eb 100644 --- a/topo/node/arista/arista.go +++ b/topo/node/arista/arista.go @@ -22,6 +22,7 @@ import ( "path/filepath" "regexp" "strings" + "time" cpb "github.com/openconfig/kne/proto/ceos" tpb "github.com/openconfig/kne/proto/topo" @@ -301,6 +302,32 @@ func (n *Node) ConfigPush(ctx context.Context, r io.Reader) error { return resp.Failed } +func (n *Node) ResetCfg(ctx context.Context) error { + log.Infof("%s resetting config", n.Name()) + + err := n.SpawnCLIConn() + if err != nil { + return err + } + + defer n.cliConn.Close() + + // this takes a long time sometimes, so we crank timeouts up + resp, err := n.cliConn.SendCommand( + "configure replace startup-config", + scrapliopts.WithTimeoutOps(300*time.Second), + ) + if err != nil { + return err + } + + if resp.Failed == nil { + log.Infof("%s - finshed resetting config", n.Name()) + } + + return resp.Failed +} + func defaults(pb *tpb.Node) *tpb.Node { if pb == nil { pb = &tpb.Node{ diff --git a/topo/node/arista/arista_test.go b/topo/node/arista/arista_test.go index 3e47747d..315081f8 100644 --- a/topo/node/arista/arista_test.go +++ b/topo/node/arista/arista_test.go @@ -17,6 +17,7 @@ import ( "context" "fmt" "testing" + "time" ceos "github.com/aristanetworks/arista-ceoslab-operator/v2/api/v1alpha1" ceosclient "github.com/aristanetworks/arista-ceoslab-operator/v2/api/v1alpha1/dynamic" @@ -26,6 +27,9 @@ import ( ceospb "github.com/openconfig/kne/proto/ceos" topopb "github.com/openconfig/kne/proto/topo" "github.com/openconfig/kne/topo/node" + scrapliopts "github.com/scrapli/scrapligo/driver/options" + scraplitransport "github.com/scrapli/scrapligo/transport" + scrapliutil "github.com/scrapli/scrapligo/util" "google.golang.org/protobuf/encoding/prototext" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/anypb" @@ -434,3 +438,85 @@ func TestCRD(t *testing.T) { }) } } + +func TestResetCfg(t *testing.T) { + ki := fake.NewSimpleClientset(&corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod1", + }, + }) + + reaction := func(action ktest.Action) (handled bool, ret watch.Interface, err error) { + f := &fakeWatch{ + e: []watch.Event{{ + Object: &corev1.Pod{ + Status: corev1.PodStatus{ + Phase: corev1.PodRunning, + }, + }, + }}, + } + return true, f, nil + } + ki.PrependWatchReactor("*", reaction) + + ni := &node.Impl{ + KubeClient: ki, + Namespace: "test", + Proto: &topopb.Node{ + Name: "pod1", + Vendor: topopb.Vendor_ARISTA, + Config: &topopb.Config{}, + }, + } + + tests := []struct { + desc string + wantErr bool + ni *node.Impl + testFile string + }{ + { + // successfully configure certificate + desc: "success", + wantErr: false, + ni: ni, + testFile: "testdata/reset_config_success", + }, + { + // device returns "% Invalid input" -- we expect to fail + desc: "failure", + wantErr: true, + ni: ni, + testFile: "testdata/reset_config_failure", + }, + } + + for _, tt := range tests { + t.Run(tt.desc, func(t *testing.T) { + nImpl, err := New(tt.ni) + + if err != nil { + t.Fatalf("failed creating kne arista node") + } + + n, _ := nImpl.(*Node) + + n.testOpts = []scrapliutil.Option{ + scrapliopts.WithTransportType(scraplitransport.FileTransport), + scrapliopts.WithFileTransportFile(tt.testFile), + scrapliopts.WithTimeoutOps(2 * time.Second), + scrapliopts.WithTransportReadSize(1), + scrapliopts.WithReadDelay(0), + scrapliopts.WithDefaultLogger(), + } + + ctx := context.Background() + + err = n.ResetCfg(ctx) + if err != nil && !tt.wantErr { + t.Fatalf("resetting config failed, error: %+v\n", err) + } + }) + } +} diff --git a/topo/node/arista/testdata/reset_config_success b/topo/node/arista/testdata/reset_config_success index d08b3baa..ca215cbd 100644 --- a/topo/node/arista/testdata/reset_config_success +++ b/topo/node/arista/testdata/reset_config_success @@ -7,7 +7,7 @@ spine1# spine1#terminal length 0 Pagination disabled. spine1# -spine1#configure replace clean-config +spine1#configure replace startup-config Aug 21 18:37:16 localhost Launcher: %LAUNCHER-6-PROCESS_STOP: Configuring process 'CapiApp' to stop in role 'ActiveSupervisor' Aug 21 18:37:16 localhost Stp: %SPANTREE-6-STABLE_CHANGE: Stp state is now not stable Aug 21 18:37:16 localhost Stp: %SPANTREE-6-INTERFACE_ADD: Interface Ethernet11 has been added to instance MST0