Skip to content

Commit 212868a

Browse files
[NX-OS] Separate feature activation from configuration (#155)
NX-OS versions prior to 10.6(3) have an issue where YANG configuration is not persisted when feature activation is mixed with dependent configuration in the same gNMI request. The configuration shows up in YANG queries but not in the running config. This implements a workaround by separating feature activation from dependent configuration into separate gNMI transactions for affected versions. Relates to #148
1 parent 1cb8659 commit 212868a

4 files changed

Lines changed: 113 additions & 54 deletions

File tree

internal/provider/cisco/gnmiext/v2/client.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,9 @@ type Capabilities struct {
5757
}
5858

5959
type Client interface {
60-
GetState(ctx context.Context, conf ...Configurable) error
60+
Capabilities() *Capabilities
6161
GetConfig(ctx context.Context, conf ...Configurable) error
62+
GetState(ctx context.Context, conf ...Configurable) error
6263
Patch(ctx context.Context, conf ...Configurable) error
6364
Update(ctx context.Context, conf ...Configurable) error
6465
Delete(ctx context.Context, conf ...Configurable) error
@@ -73,9 +74,7 @@ type client struct {
7374
logger logr.Logger
7475
}
7576

76-
var (
77-
_ Client = &client{}
78-
)
77+
var _ Client = &client{}
7978

8079
// New creates a new Client by negotiating capabilities with the gNMI server by
8180
// carrying out a Capabilities RPC.
@@ -128,6 +127,11 @@ func WithLogger(logger logr.Logger) Option {
128127
// ErrNil indicates that the value for a xpath is not defined.
129128
var ErrNil = errors.New("gnmiext: nil")
130129

130+
// Capabilities returns the capabilities supported by the gNMI server.
131+
func (c *client) Capabilities() *Capabilities {
132+
return c.capabilities
133+
}
134+
131135
// GetConfig retrieves config and unmarshals it into the provided targets.
132136
// If some of the values for the given xpaths are not defined, [ErrNil] is returned.
133137
func (c *client) GetConfig(ctx context.Context, conf ...Configurable) error {

internal/provider/cisco/iosxr/provider_test.go

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -91,55 +91,69 @@ func Test_Payload(t *testing.T) {
9191
// MockClient provides a mock implementation of gnmiext.Client for testing.
9292
type MockClient struct {
9393
// Function fields for mocking different methods
94-
GetConfigFunc func(ctx context.Context, conf ...gnmiext.Configurable) error
95-
PatchFunc func(ctx context.Context, conf ...gnmiext.Configurable) error
96-
UpdateFunc func(ctx context.Context, conf ...gnmiext.Configurable) error
97-
DeleteFunc func(ctx context.Context, conf ...gnmiext.Configurable) error
98-
GetStateFunc func(ctx context.Context, conf ...gnmiext.Configurable) error
94+
CapabilitiesFunc func() *gnmiext.Capabilities
95+
GetConfigFunc func(ctx context.Context, conf ...gnmiext.Configurable) error
96+
PatchFunc func(ctx context.Context, conf ...gnmiext.Configurable) error
97+
UpdateFunc func(ctx context.Context, conf ...gnmiext.Configurable) error
98+
DeleteFunc func(ctx context.Context, conf ...gnmiext.Configurable) error
99+
GetStateFunc func(ctx context.Context, conf ...gnmiext.Configurable) error
99100
}
100101

102+
var _ gnmiext.Client = (*MockClient)(nil)
103+
101104
// Implement the methods that Provider uses
105+
func (m *MockClient) Capabilities() *gnmiext.Capabilities {
106+
if m.CapabilitiesFunc != nil {
107+
return m.CapabilitiesFunc()
108+
}
109+
return nil
110+
}
111+
102112
func (m *MockClient) GetConfig(ctx context.Context, conf ...gnmiext.Configurable) error {
103113
if m.GetConfigFunc != nil {
104114
return m.GetConfigFunc(ctx, conf...)
105115
}
106116
return nil
107117
}
108118

109-
func (m *MockClient) Patch(ctx context.Context, conf ...gnmiext.Configurable) error {
119+
func (m *MockClient) GetState(ctx context.Context, conf ...gnmiext.Configurable) error {
120+
if m.GetStateFunc != nil {
121+
return m.GetStateFunc(ctx, conf...)
122+
}
110123
return nil
111124
}
112125

113-
func (m *MockClient) Update(ctx context.Context, conf ...gnmiext.Configurable) error {
126+
func (m *MockClient) Patch(ctx context.Context, conf ...gnmiext.Configurable) error {
127+
if m.PatchFunc != nil {
128+
return m.PatchFunc(ctx, conf...)
129+
}
114130
return nil
115131
}
116132

117-
func (m *MockClient) Delete(ctx context.Context, conf ...gnmiext.Configurable) error {
133+
func (m *MockClient) Update(ctx context.Context, conf ...gnmiext.Configurable) error {
134+
if m.UpdateFunc != nil {
135+
return m.UpdateFunc(ctx, conf...)
136+
}
118137
return nil
119138
}
120139

121-
func (m *MockClient) GetState(ctx context.Context, conf ...gnmiext.Configurable) error {
122-
if m.GetStateFunc != nil {
123-
return m.GetStateFunc(ctx, conf...)
140+
func (m *MockClient) Delete(ctx context.Context, conf ...gnmiext.Configurable) error {
141+
if m.DeleteFunc != nil {
142+
return m.DeleteFunc(ctx, conf...)
124143
}
125144
return nil
126145
}
127146

128147
func Test_EnsureInterface(t *testing.T) {
129148
m := &MockClient{}
130-
131-
p := &Provider{
132-
client: m,
133-
conn: nil,
134-
}
149+
p := &Provider{client: m}
135150

136151
ctx := context.Background()
137152

138-
var name = "TwentyFiveGigE0/0/0/14"
153+
name := "TwentyFiveGigE0/0/0/14"
139154
var prefix netip.Prefix
140155

141156
prefix, err := netip.ParsePrefix("192.168.1.0/24")
142-
143157
if err != nil {
144158
t.Fatalf("Failed to parse prefix: %v", err)
145159
}
@@ -186,7 +200,7 @@ func Test_GetState(t *testing.T) {
186200

187201
ctx := context.Background()
188202

189-
var name = "TwentyFiveGigE0/0/0/14"
203+
name := "TwentyFiveGigE0/0/0/14"
190204

191205
req := &provider.InterfaceRequest{
192206
Interface: &v1alpha1.Interface{

0 commit comments

Comments
 (0)