Skip to content

test(operator): use apiequality.Semantic.DeepEqual when tests compare Kubernetes API types #18186

Open

Description

@dongjiang1989

Problem

A few operator test call sites compare Kubernetes API types with reflect.DeepEqual. reflect.DeepEqual reports spurious inequality for API types:

  • metav1.Time values representing the same instant can differ in the internal time.Time location pointer (e.g. after a JSON round-trip through the apiserver vs. constructed in memory), so DeepEqual says "not equal" for semantically equal statuses.
  • nil-vs-empty slices/maps are distinguished even though the apiserver treats them as equivalent.

Upstream Istio swept the same class of call sites in istio/istio#61872, replacing reflect.DeepEqual with apiequality.Semantic.DeepEqual where Kubernetes API types are compared, and deliberately keeping reflect.DeepEqual where it is the correct tool (plain strings, JSON-decoded any values, types with unregistered unexported fields, where Semantic.DeepEqual would panic).

Current state in dynamo

Production code is already clean: deploy/operator uses apiequality.Semantic.DeepEqual in ~99 non-test call sites (e.g. resourceRequirementsEqual, podSpecIsZero, podTemplateIsZero), with comments explaining why semantic equality matches the apiserver's own comparison.

The remaining risk is confined to tests, e.g.:

  • internal/controller/dynamographdeploymentrun_v1beta2_controller_test.go compares DynamoGraphDeploymentRunStatus (contains StartTime *metav1.Time and Conditions []metav1.Condition) with reflect.DeepEqual. Today both sides are read from the same fake client, so representations match and the tests do not flake — but the assertion breaks spuriously as soon as one side goes through a JSON round-trip (e.g. envtest or a recorded fixture).
  • internal/controller_common/resource_test.go compares []metav1.OwnerReference with reflect.DeepEqual.

Proposed scope

  • Switch test comparisons of Kubernetes API types that contain (or may later contain) metav1.Time — Run status, owner references — to apiequality.Semantic.DeepEqual.
  • Leave reflect.DeepEqual where it is correct: plain string/[]string comparisons, JSON/YAML-decoded map[string]any values, []reconcile.Request, and zero-value checks on own types.

Tests-only change, no production behavior impact.

Activity

  1. added
    operatorCODEOWNER area -> @ai-dynamo/dynamo-operator-codeowners
    on Nov 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    operatorCODEOWNER area -> @ai-dynamo/dynamo-operator-codeowners

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions