Certz-1.1 and Certz-1.2#5653
Conversation
Pull Request Functional Test Report for #5653 / 0f75cb5Virtual Devices
Hardware Devices
|
Summary of ChangesHello, 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 comprehensive test coverage for Certz 1.1 and 1.2 functionality. It includes a new test suite that validates client certificate loading and authentication across various CA configurations, alongside minor infrastructure improvements to the test setup utilities to ensure more robust script execution and error reporting. Highlights
Using Gemini Code AssistThe 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
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 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
|
There was a problem hiding this comment.
Code Review
This pull request introduces a new client certificates test (client_certificates_test.go) for GNSI certz rotation, updates the CA generation script to support custom directories, and improves error handling in setup_service.go by using t.Fatalf instead of t.Errorf for capability check failures. The review feedback focuses on Go best practices, recommending the removal of package-level global variables in favor of local declarations within the test function, and simplifying flag usage by dereferencing them directly instead of using redundant helper functions.
| var ( | ||
| serverAddr string | ||
| creds DUTCredentialer //an interface for getting credentials from a DUT binding | ||
| testProfile string = "newprofile" //sslProfileId name | ||
| prevClientCertFile string = "" | ||
| prevClientKeyFile string = "" | ||
| prevTrustBundleFile string = "" | ||
| expectedResult bool = true | ||
| certsList = flag.String("certsList", "01,02,10,1000", "Number of Certificate Sets to generate for this test. Comma separated string") | ||
| certsTimeout = flag.Duration("certsTimeout", 10*time.Minute, "Time duration for cert generation and cleanup. Increase if more certs are to be generated") | ||
| certsString = func() string { | ||
| return *certsList | ||
| } | ||
| certsTimeOutVar = func() time.Duration { | ||
| return *certsTimeout | ||
| } | ||
| ) |
There was a problem hiding this comment.
Declaring test-specific variables (such as serverAddr, creds, testProfile, prevClientCertFile, prevClientKeyFile, prevTrustBundleFile, and expectedResult) as package-level global variables is an anti-pattern in Go. It pollutes the global namespace and can lead to shared state issues or race conditions if tests are run concurrently or multiple times in the same process. These variables should be declared locally within the TestClientCert function. Additionally, the helper functions certsString and certsTimeOutVar are redundant; the flag pointers certsList and certsTimeout can be dereferenced directly.
var (
certsList = flag.String("certsList", "01,02,10,1000", "Number of Certificate Sets to generate for this test. Comma separated string")
certsTimeout = flag.Duration("certsTimeout", 10*time.Minute, "Time duration for cert generation and cleanup. Increase if more certs are to be generated")
)References
- Follow Go Code Review Comments and Effective Go for writing readable, idiomatic Go code. Avoid package-level global variables for test-specific state to prevent shared state issues and namespace pollution. (link)
| func TestClientCert(t *testing.T) { | ||
|
|
||
| dut := ondatra.DUT(t, "dut") | ||
| serverAddr = dut.Name() //returns the device name. | ||
| if err := binding.DUTAs(dut.RawAPIs().BindingDUT(), &creds); err != nil { | ||
| t.Fatalf("%sSTATUS:Failed to get DUT credentials using binding.DUTAs: %v. The binding for %s must implement the DUTCredentialer interface.", time.Now().String(), err, dut.Name()) | ||
| } | ||
| username := creds.RPCUsername() | ||
| password := creds.RPCPassword() | ||
| t.Logf("Validation of all services that are using gRPC before certz rotation.") | ||
| gnmiClient, gnsiC := setup_service.PreInitCheck(context.Background(), t, dut) | ||
| //Generate testdata certificates | ||
| t.Logf("%sSTATUS:Generation of test data certificates.", time.Now().String()) | ||
| command := fmt.Sprintf("./mk_cas.sh %v", certsString()) | ||
| if err := setup_service.TestdataMakeCleanup(t, dirPath, certsTimeOutVar(), command); err != nil { | ||
| t.Fatalf("%sSTATUS:Generation of testdata certificates failed!: %v", time.Now().String(), err) | ||
| } | ||
| //Create a certz client | ||
| ctx := context.Background() | ||
| certzClient := gnsiC.Certz() | ||
| t.Logf("%sSTATUS:Precheck:checking baseline ssl profile list.", time.Now().String()) | ||
| //Get ssl profile list. | ||
| if getResp := setup_service.GetSslProfilelist(ctx, t, certzClient, &certzpb.GetProfileListRequest{}); slices.Contains(getResp.SslProfileIds, testProfile) { | ||
| t.Fatalf("%sSTATUS:profileID %s already exists.", time.Now().String(), testProfile) | ||
| } | ||
| //Add a new ssl profileID | ||
| t.Logf("%sSTATUS:Adding new empty ssl profile ID %s.", time.Now().String(), testProfile) | ||
| if addProfileResponse, err := certzClient.AddProfile(ctx, &certzpb.AddProfileRequest{SslProfileId: testProfile}); err != nil { | ||
| t.Fatalf("%sSTATUS:Add profile request failed with %v!", time.Now().String(), err) | ||
| } else { | ||
| t.Logf("%sSTATUS:Received the AddProfileResponse %v.", time.Now().String(), addProfileResponse) | ||
| } | ||
| //Get ssl profile list after new ssl profile addition. | ||
| if getResp := setup_service.GetSslProfilelist(ctx, t, certzClient, &certzpb.GetProfileListRequest{}); !slices.Contains(getResp.SslProfileIds, testProfile) { | ||
| t.Fatalf("%sSTATUS:newly added profileID is not seen.", time.Now().String()) | ||
| } else { | ||
| t.Logf("%sSTATUS: new profileID %s is seen in ssl profile list.", time.Now().String(), testProfile) | ||
| } |
There was a problem hiding this comment.
Refactor TestClientCert to declare test-specific variables locally and dereference the flags directly instead of using the redundant package-level helper functions. This improves maintainability, encapsulation, and adheres to Go best practices.
func TestClientCert(t *testing.T) {
dut := ondatra.DUT(t, "dut")
serverAddr := dut.Name() //returns the device name.
var creds DUTCredentialer
if err := binding.DUTAs(dut.RawAPIs().BindingDUT(), &creds); err != nil {
t.Fatalf("Failed to get DUT credentials using binding.DUTAs: %v. The binding for %s must implement the DUTCredentialer interface.", err, dut.Name())
}
username := creds.RPCUsername()
password := creds.RPCPassword()
t.Logf("Validation of all services that are using gRPC before certz rotation.")
gnmiClient, gnsiC := setup_service.PreInitCheck(context.Background(), t, dut)
//Generate testdata certificates
t.Logf("Generation of test data certificates.")
command := fmt.Sprintf("./mk_cas.sh %v", *certsList)
if err := setup_service.TestdataMakeCleanup(t, dirPath, *certsTimeout, command); err != nil {
t.Fatalf("Generation of testdata certificates failed!: %v", err)
}
//Create a certz client
ctx := context.Background()
certzClient := gnsiC.Certz()
t.Logf("Precheck:checking baseline ssl profile list.")
//Get ssl profile list.
testProfile := "newprofile"
if getResp := setup_service.GetSslProfilelist(ctx, t, certzClient, &certzpb.GetProfileListRequest{}); slices.Contains(getResp.SslProfileIds, testProfile) {
t.Fatalf("profileID %s already exists.", testProfile)
}
//Add a new ssl profileID
t.Logf("Adding new empty ssl profile ID %s.", testProfile)
if addProfileResponse, err := certzClient.AddProfile(ctx, &certzpb.AddProfileRequest{SslProfileId: testProfile}); err != nil {
t.Fatalf("Add profile request failed with %v!", err)
} else {
t.Logf("Received the AddProfileResponse %v.", addProfileResponse)
}
//Get ssl profile list after new ssl profile addition.
if getResp := setup_service.GetSslProfilelist(ctx, t, certzClient, &certzpb.GetProfileListRequest{}); !slices.Contains(getResp.SslProfileIds, testProfile) {
t.Fatalf("newly added profileID is not seen.")
} else {
t.Logf("new profileID %s is seen in ssl profile list.", testProfile)
}
var prevClientCertFile string
var prevClientKeyFile string
var prevTrustBundleFile string
expectedResult := true| t.Logf("%s:STATUS:Cleanup of test data.", time.Now().String()) | ||
| //Cleanup of test data. | ||
| if err := setup_service.TestdataMakeCleanup(t, dirPath, certsTimeOutVar(), "./cleanup.sh"); err != nil { | ||
| t.Errorf("%s:STATUS:Cleanup of testdata certificates failed!: %v", time.Now().String(), err) | ||
| } | ||
| t.Logf("%s:STATUS:Test completed!", time.Now().String()) |
There was a problem hiding this comment.
Clean up the test data cleanup block to use the dereferenced *certsTimeout flag directly and remove the redundant time.Now().String() and STATUS: prefixes from the logs.
| t.Logf("%s:STATUS:Cleanup of test data.", time.Now().String()) | |
| //Cleanup of test data. | |
| if err := setup_service.TestdataMakeCleanup(t, dirPath, certsTimeOutVar(), "./cleanup.sh"); err != nil { | |
| t.Errorf("%s:STATUS:Cleanup of testdata certificates failed!: %v", time.Now().String(), err) | |
| } | |
| t.Logf("%s:STATUS:Test completed!", time.Now().String()) | |
| t.Logf("Cleanup of test data.") | |
| //Cleanup of test data. | |
| if err := setup_service.TestdataMakeCleanup(t, dirPath, *certsTimeout, "./cleanup.sh"); err != nil { | |
| t.Errorf("Cleanup of testdata certificates failed!: %v", err) | |
| } | |
| t.Logf("Test completed!") |
Pushing test code for Certz1.1 and 1.2.
This code was previous merged via PR # 3684, however reverted by PR 5114 due to some issues. Raising a new pull request now with changes.