testing (3/4): Add gNMI integration tests with envtest - #409
Conversation
78654a7 to
d200e98
Compare
envtest mode for faster in-process e2e testing
82d714b to
829e761
Compare
d200e98 to
823e208
Compare
823e208 to
f735c68
Compare
be16d2f to
e20ae93
Compare
51d400f to
ace1a56
Compare
8b82070 to
e0403cc
Compare
ace1a56 to
bce5bb0
Compare
bce5bb0 to
2cf82d6
Compare
envtest mode for faster in-process e2e testingenvtest
dd3f643 to
5b100a6
Compare
f81d9b2 to
47fda5a
Compare
268ae9b to
625b160
Compare
a6bf5d6 to
b92a3b7
Compare
78a7329 to
88ddff7
Compare
b93b249 to
8aff030
Compare
8aff030 to
6cf3d85
Compare
| - name: Install ginkgo | ||
| run: go install github.com/onsi/ginkgo/v2/ginkgo@latest |
There was a problem hiding this comment.
| - name: Install ginkgo | |
| run: go install github.com/onsi/ginkgo/v2/ginkgo@latest |
The Makefile target for test-gnmi should already take care of installing ginkgo, if even required.
There was a problem hiding this comment.
Fixed. But I think we still need gingko to run the tests in parallel. With ginkgo we don't have to worry about the gNMI server state being shared across the tests as each process runs one server and the tests run sequentially there. We could refactor (again) the tests to have a gNMI server per test, or extend the server to support multiple States, but this seems too much for now.
| func registerControllers(ctx context.Context, mgr ctrl.Manager, recorder *events.FakeRecorder, providerFn provider.ProviderFunc, locker *resourcelock.ResourceLocker) { | ||
| var err error | ||
|
|
||
| err = (&core.PrefixSetReconciler{ |
There was a problem hiding this comment.
I feel like this list might have gotten outdated, e.g. there is no EthernetSegmentReconciler registered here.
There was a problem hiding this comment.
That is true, but there is also no test for that. Doesn't seem necessary to register a controller that is not used.
| conditions, err := ExtractConditions(r) | ||
| g.Expect(err).NotTo(HaveOccurred()) | ||
|
|
||
| conditionToCheck := string(v1alpha1.ReadyCondition) |
There was a problem hiding this comment.
The problem I see is that we check for the wrong condition and the eventually might return early therefore. The logic is that we only check for "Configured" when that is found on the object. However, we don't wait for the object to report any condition before we decide that.
So generally, if a resource has no conditions, it hasn't been reconciled yet. But if it contains any conditions, then it would also contain the "Configured" condition, as we then initialize that to "Unknown".
Merging this branch will not change overall coverage
Coverage by fileChanged files (no unit tests)
Please note that the "Total", "Covered", and "Missed" counts above refer to code statements instead of lines of code. The value in brackets refers to the test coverage of that file in the old version of the code. Changed unit test files
|
This commit introduces envtest-based integration tests for gNMI functionality
using the OpenConfig provider. The tests verify the end-to-end workflow from
Kubernetes resources to provider gNMI payloads without requiring a full cluster
deployment.
The test architecture uses a per-process gNMI test server to enable parallel
test execution with Ginkgo's --procs flag. Each Ginkgo process creates its own
suite-level server in BeforeSuite, shares it across all tests within that
process, and cleans it up in AfterSuite. Tests within each process run serially,
ensuring proper isolation through per-test namespaces and state clearing between
tests.
Testdata files support optional state/preload sections to set initial
gNMI server state before reconciliation. This is for example required to
successfully reconcile devices: the controller requires the last boot
time. Added one additional section ("delete") that represents the state
of the device after the kubernetes resource has been cleaned up. This is
usually the same as the preload section. Updated test cases
accordingly.
At the beginning of the test we set device.Status.Phase to Running
directly. This unblocks the the Device controller and avoids us having
to add more of the device data into the preload section, e.g., that
related to GetDeviceInfo, ListPorts.
As there is only one gNMI test server per process, all tests share the same device.
This means that test cases must clean up all resources they create, otherwise the
server will be polluted by the left over resources.
As Envtest runs without kube-controller-manager, there is no garbage collector
to cascade deletions, meaning each test needs to explicitly clean up resources it creates,
and it must do so in the correct order to prevent finalizer deadlocks. For example, a
Device cannot be deleted while it still has dependent resources with finalizers.
Additionally, not all custom resources in network-operator have controllers.
Resources like Interface, BGP, and OSPF have reconcilers that add finalizers and
set status conditions. Other resources (typically config-only types) are stored
in the API but have no controller — no finalizer, no conditions.
Thus, the test framework must handle: wait for conditions on controller-managed
resources, prevent blocking indefinitely on config-only ones, and clean up
resources in the correct order without relying on cascading deletion.
The waitForResource helper probes for a finalizer with a short timeout.
Controllers add finalizers early in reconciliation (within ~1 second), so if
none appears after 3 seconds, the resource is assumed to be config-only and the
helper returns immediately. For controller-managed resources, it waits for the
Ready or Configured condition.
The cleanupAllResources helper lists all network-operator resources in the
namespace, then partitions them by checking each resource's finalizers field.
Controller-managed resources (those with finalizers) are deleted first, waiting
for finalizer removal while Device still exists. Config-only resources (no
finalizers) are deleted afterward without waiting. Finally, the Device is
deleted. This approach avoids hardcoded list of resource types.
Signed-off-by: Pujol <enric.pujol@sap.com>
…lacks VLAN support) The OpenConfig provider does not yet support VLAN interface configuration, causing the interface_routed_vlan test to fail. Skip this test by renaming the fixture file to .skip extension until VLAN support is implemented. Signed-off-by: Pujol <enric.pujol@sap.com>
Signed-off-by: Pujol <enric.pujol@sap.com>
This PR introduces envtest-based gNMI integration tests for the OpenConfig provider, enabling faster validation of the Kubernetes resources to gNMI sequence without requiring a full cluster deployment.
The test architecture uses a per-process gNMI server design that enables parallel test execution with Ginkgo's --procs flag. Each process creates its own suite-level server in BeforeSuite and shares it across tests running serially within that process.