Skip to content

gnmi-1.19 fixes#5612

Draft
mnp-juniper wants to merge 5 commits into
openconfig:mainfrom
mnp-juniper:gnmi119
Draft

gnmi-1.19 fixes#5612
mnp-juniper wants to merge 5 commits into
openconfig:mainfrom
mnp-juniper:gnmi119

Conversation

@mnp-juniper

Copy link
Copy Markdown
Contributor

Made these changes :
1.Removed wild card issue in gnmi get
2.Added a check for standby CC ready before switchover
3.Created interface and routing policy configs before attemping the get and set

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces stability and reliability improvements to the controller card switchover test suite. By refining how gNMI data is retrieved and ensuring that critical system components are ready and properly configured before operations occur, the changes reduce flakiness in the testing environment.

Highlights

  • gNMI Get Request Refinement: Removed wildcard-based queries in gNMI Get operations, replacing them with direct path lookups to improve reliability and performance.
  • Switchover Readiness Check: Added an explicit readiness check for the standby controller card before initiating a system switchover to ensure stability.
  • Configuration Pre-requisites: Implemented automated creation of interface and routing policy configurations prior to executing Get and Set requests to ensure proper device state.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the controller card switchover test by adding standby controller card readiness checks, configuring routing policies and basic interfaces, and refactoring the verification of configured elements using raw gNMI calls. Feedback focuses on improving the robustness of the raw gNMI JSON parsing by querying the parent /interfaces container instead of the list directly, and using GetOrCreateStatement instead of AppendNewStatement to avoid ignoring errors when defining routing policy statements.

Comment on lines +388 to +426
// 2. Construct the exact path matching: /interfaces/interface
getRequest := &gpb.GetRequest{
Type: gpb.GetRequest_CONFIG,
Encoding: gpb.Encoding_JSON_IETF,
Path: []*gpb.Path{
{
Elem: []*gpb.PathElem{
{Name: "interfaces"},
{Name: "interface"},
},
},
},
}

ctxTimeout, cancel := context.WithTimeout(context.Background(), 20*time.Second)
defer cancel()

// 3. Execute the raw gNMI call
getResponse, err := gnmiClient.Get(ctxTimeout, getRequest)
if err != nil {
t.Fatalf("Raw gNMI Get failed: %v", err)
}

numInterfaces := 0
// 4. Parse the raw JSON using a generic map wrapper
if len(getResponse.GetNotification()) > 0 && len(getResponse.GetNotification()[0].GetUpdate()) > 0 {
jsonVal := getResponse.GetNotification()[0].GetUpdate()[0].GetVal().GetJsonIetfVal()

// Parse into a dynamic list of maps representing the interfaces list array
var rawData []map[string]interface{}
if err := json.Unmarshal(jsonVal, &rawData); err != nil {
t.Fatalf("Failed to parse raw JSON payload: %v", err)
}

// The length of the array is exactly how many interface objects are inside the JSON
numInterfaces = len(rawData)
} else {
t.Fatalf("No interface configuration elements returned from device state database.")
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Querying the list path /interfaces/interface directly via raw gNMI Get and unmarshalling it into a slice of maps ([]map[string]interface{}) is fragile. Depending on the gNMI server implementation, a list query might return multiple updates (one per list key) or a wrapped JSON object instead of a direct JSON array, which will cause json.Unmarshal to fail and crash the test.

To make this robust and vendor-independent, query the parent container /interfaces (which is guaranteed to be returned as a single JSON object) and dynamically extract the interface list, handling potential namespace prefixes.

	// 2. Construct the exact path matching: /interfaces
	getRequest := &gpb.GetRequest{
		Type:     gpb.GetRequest_CONFIG,
		Encoding: gpb.Encoding_JSON_IETF,
		Path: []*gpb.Path{
			{
				Elem: []*gpb.PathElem{
					{Name: "interfaces"},
				},
			},
		},
	}

	ctxTimeout, cancel := context.WithTimeout(context.Background(), 20*time.Second)
	defer cancel()

	// 3. Execute the raw gNMI call
	getResponse, err := gnmiClient.Get(ctxTimeout, getRequest)
	if err != nil {
		t.Fatalf("Raw gNMI Get failed: %v", err)
	}

	numInterfaces := 0
	// 4. Parse the raw JSON using a generic map wrapper
	if len(getResponse.GetNotification()) > 0 && len(getResponse.GetNotification()[0].GetUpdate()) > 0 {
		jsonVal := getResponse.GetNotification()[0].GetUpdate()[0].GetVal().GetJsonIetfVal()

		// Parse into a dynamic map representing the interfaces container
		var rawData map[string]interface{}
		if err := json.Unmarshal(jsonVal, &rawData); err != nil {
			t.Fatalf("Failed to parse raw JSON payload: %v", err)
		}

		// Extract the interface list, handling potential namespace prefixes
		interfacesVal, ok := rawData["interface"]
		if !ok {
			interfacesVal, ok = rawData["openconfig-interfaces:interface"]
		}

		if ok {
			if interfacesList, ok := interfacesVal.([]interface{}); ok {
				numInterfaces = len(interfacesList)
			} else {
				t.Fatalf("Interface list in JSON is not an array")
			}
		} else {
			t.Fatalf("No interface list found in JSON payload")
		}
	} else {
		t.Fatalf("No interface configuration elements returned from device state database.")
	}

d := &oc.Root{}
rp := d.GetOrCreateRoutingPolicy()
pdef := rp.GetOrCreatePolicyDefinition(acceptRoutePolicy)
stmt, _ := pdef.AppendNewStatement("20")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using AppendNewStatement with a hardcoded key and ignoring the returned error with _ is discouraged. Since the statement key is explicitly known ("20"), it is cleaner and more idiomatic to use GetOrCreateStatement which does not return an error.

	stmt := pdef.GetOrCreateStatement("20")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants