-
Notifications
You must be signed in to change notification settings - Fork 58
fix(storage): ensure model-cache init namespace has unbound DNS label in NVMesh path #1303
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
93ba862
581a13f
c4c4ba8
7bcbfd4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -40,6 +40,7 @@ import ( | |
| "github.com/prometheus/client_golang/prometheus" | ||
| "github.com/sirupsen/logrus" | ||
| "github.com/stretchr/testify/assert" | ||
| "github.com/stretchr/testify/mock" | ||
| "github.com/stretchr/testify/require" | ||
| "go.opentelemetry.io/otel" | ||
| "go.opentelemetry.io/otel/propagation" | ||
|
|
@@ -4426,9 +4427,9 @@ func TestGetGPUUsageStats_FallbackToNonSuffixSingleType(t *testing.T) { | |
| Status: corev1.NodeStatus{ | ||
| Conditions: []corev1.NodeCondition{{Type: corev1.NodeReady, Status: corev1.ConditionTrue}}, | ||
| Allocatable: corev1.ResourceList{ | ||
| corev1.ResourceCPU: resource.MustParse("5"), | ||
| corev1.ResourceMemory: resource.MustParse("32Gi"), | ||
| corev1.ResourceEphemeralStorage: resource.MustParse("256Gi"), | ||
| corev1.ResourceCPU: resource.MustParse("5"), | ||
| corev1.ResourceMemory: resource.MustParse("32Gi"), | ||
| corev1.ResourceEphemeralStorage: resource.MustParse("256Gi"), | ||
| corev1.ResourceName(nodefeatures.GPUResourceKey): resource.MustParse("4"), | ||
| }, | ||
| }, | ||
|
|
@@ -5460,3 +5461,56 @@ func TestUpdateSchedulerWorkloadMetrics(t *testing.T) { | |
| assert.Equal(t, float64(1), vals[gaugeKey{"kai-scheduler", "function"}]) | ||
| }) | ||
| } | ||
|
|
||
| func TestEnsureModelCacheNamespaceLabel_PatchesWithCorrectPayload(t *testing.T) { | ||
| namespace := "nvca-modelcache-init" | ||
| expectedPatch := []byte(fmt.Sprintf(`[{"op": "add", "path": "/metadata/labels/%s", "value": %q}]`, | ||
| strings.ReplaceAll(nvcatypes.WorkloadInstanceTypeLabel, "/", "~1"), | ||
| nvcatypes.WorkloadInstanceTypeValueMiniService)) | ||
|
|
||
| nsPatcher := &mockNamespacePatcher{} | ||
| nsPatcher.On("Patch", mock.Anything, namespace, apitypes.JSONPatchType, expectedPatch, metav1.PatchOptions{}). | ||
| Return(&corev1.Namespace{}, nil) | ||
|
|
||
| err := ensureModelCacheNamespaceLabel(context.Background(), nsPatcher, namespace) | ||
| assert.NoError(t, err) | ||
| nsPatcher.AssertExpectations(t) | ||
| } | ||
|
|
||
| func TestEnsureModelCacheNamespaceLabel_PatchError(t *testing.T) { | ||
| nsPatcher := &mockNamespacePatcher{} | ||
| nsPatcher.On("Patch", mock.Anything, mock.Anything, apitypes.JSONPatchType, mock.Anything, metav1.PatchOptions{}). | ||
| Return(nil, fmt.Errorf("patch error")) | ||
|
|
||
| err := ensureModelCacheNamespaceLabel(context.Background(), nsPatcher, "nvca-modelcache-init") | ||
| assert.Error(t, err) | ||
| } | ||
|
|
||
| // TestEnsureModelCacheNamespaceLabel_IdempotentWhenLabelPresent confirms that | ||
| // ensureModelCacheNamespaceLabel always issues the JSON patch "add" operation, | ||
| // even when the label is already set. RFC 6902 §4.1 specifies that "add" on an | ||
| // existing object key replaces its value, so the call is safe and idempotent | ||
| // regardless of whether the namespace was freshly created or already labelled. | ||
| func TestEnsureModelCacheNamespaceLabel_IdempotentWhenLabelPresent(t *testing.T) { | ||
| namespace := "nvca-modelcache-init" | ||
| expectedPatch := []byte(fmt.Sprintf(`[{"op": "add", "path": "/metadata/labels/%s", "value": %q}]`, | ||
| strings.ReplaceAll(nvcatypes.WorkloadInstanceTypeLabel, "/", "~1"), | ||
| nvcatypes.WorkloadInstanceTypeValueMiniService)) | ||
|
|
||
| // Simulate a namespace that already carries the correct label; the API | ||
| // server accepts the patch (replace is a no-op at the state level). | ||
| alreadyLabelled := &corev1.Namespace{} | ||
| alreadyLabelled.Labels = map[string]string{ | ||
| nvcatypes.WorkloadInstanceTypeLabel: nvcatypes.WorkloadInstanceTypeValueMiniService, | ||
| } | ||
|
|
||
| nsPatcher := &mockNamespacePatcher{} | ||
| nsPatcher.On("Patch", mock.Anything, namespace, apitypes.JSONPatchType, expectedPatch, metav1.PatchOptions{}). | ||
| Return(alreadyLabelled, nil) | ||
|
|
||
| err := ensureModelCacheNamespaceLabel(context.Background(), nsPatcher, namespace) | ||
| assert.NoError(t, err) | ||
| // Patch must have been called exactly once — not skipped because the label | ||
| // was already present. | ||
| nsPatcher.AssertNumberOfCalls(t, "Patch", 1) | ||
| } | ||
|
Comment on lines
+5494
to
+5516
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift 🔎 Supported by static analysis🏁 Script executed: #!/bin/bash
set -e
printf '%s\n' '--- scoped conventions ---'
find /tmp/coderabbit-repo-knowledge/nvidia-nvcf-193a0c82 -type f -name '*.md' -maxdepth 3 -print
printf '%s\n' '--- target symbols and test context ---'
rg -n -C 8 'ensureModelCacheNamespaceLabel|TestEnsureModelCacheNamespaceLabel|type mockNamespacePatcher|NamespacePatcher' src/compute-plane-services/nvca/pkg/nvca/backendk8scache.go src/compute-plane-services/nvca/pkg/nvca/backendk8scache_test.go
printf '%s\n' '--- imports and nearby tests ---'
sed -n '1,80p' src/compute-plane-services/nvca/pkg/nvca/backendk8scache_test.go
sed -n '5420,5535p' src/compute-plane-services/nvca/pkg/nvca/backendk8scache_test.goRepository: NVIDIA/nvcf Length of output: 29016 🏁 Script executed: #!/bin/bash
set -e
printf '%s\n' '--- helper and patcher contract ---'
rg -n -C 12 'func ensureModelCacheNamespaceLabel|mockNamespacePatcher|Namespaces\(\).*Patch|JSONPatchType' src/compute-plane-services/nvca
printf '%s\n' '--- relevant package conventions ---'
cat /tmp/coderabbit-repo-knowledge/nvidia-nvcf-193a0c82/conventions/src-compute-plane-services-nvca.md
printf '%s\n' '--- envtest usage in the target subtree ---'
rg -n -C 4 'envtest|KUBEBUILDER_ASSETS|Start\(' src/compute-plane-services/nvca --glob '*.go' --glob 'Makefile*' --glob '*.mk'Repository: NVIDIA/nvcf Length of output: 50368 🏁 Script executed: #!/bin/bash
set -e
printf '%s\n' '--- exact helper definition and mock ---'
rg -n -C 15 --glob '!vendor/**' --glob '*.go' 'func ensureModelCacheNamespaceLabel|type mockNamespacePatcher|func \(.*mockNamespacePatcher.*Patch' src/compute-plane-services/nvca
printf '%s\n' '--- package convention ---'
sed -n '1,240p' /tmp/coderabbit-repo-knowledge/nvidia-nvcf-193a0c82/conventions/src-compute-plane-services-nvca.md
printf '%s\n' '--- envtest references, excluding vendor ---'
rg -n -C 3 --glob '!vendor/**' --glob '*.go' 'envtest|KUBEBUILDER_ASSETS' src/compute-plane-services/nvcaRepository: NVIDIA/nvcf Length of output: 50367 🏁 Script executed: #!/bin/bash
set -e
printf '%s\n' '--- namespace creation and helper call ---'
sed -n '700,748p' src/compute-plane-services/nvca/pkg/nvca/backendk8scache.go
printf '%s\n' '--- exact envtest setup contract ---'
sed -n '1,125p' src/compute-plane-services/nvca/internal/envtest/envtest.go
printf '%s\n' '--- JSON patch implementation and missing-parent behavior ---'
rg -n -C 8 --glob '!vendor/**' --glob '*.go' 'func ensureModelCacheNamespaceLabel|JSONPatchType' src/compute-plane-services/nvca/pkg/nvca
rg -n -C 8 'missing path|MissingPath|jsonpatch|JSONPatch' src/compute-plane-services/nvca/vendor/github.com/evanphx src/compute-plane-services/nvca/vendor/k8s.io/apiserver/pkg/endpoints/handlers 2>/dev/null | head -160Repository: NVIDIA/nvcf Length of output: 33631 🏁 Script executed: #!/bin/bash
set -e
printf '%s\n' '--- namespace constructor ---'
rg -n -C 12 --glob '!vendor/**' 'func NewModelCacheInitNamespace|NewModelCacheInitNamespace' src/compute-plane-services/nvca
printf '%s\n' '--- JSON patch add path handling ---'
rg -n -C 12 'func \(d \*partialDoc\) add|EnsurePathExistsOnAdd|ErrMissing|missing path' src/compute-plane-services/nvca/vendor/github.com/evanphx/json-patch/v5/patch.goRepository: NVIDIA/nvcf Length of output: 40095 🏁 Script executed: #!/bin/bash
set -e
printf '%s\n' '--- Kubernetes patch implementation binding ---'
rg -n -C 6 --glob '!vendor/**' 'github.com/evanphx/json-patch|evanphx|jsonpatch' src/compute-plane-services/nvca/go.mod src/compute-plane-services/nvca/vendor/k8s.io/apiserver/pkg 2>/dev/null | head -120
printf '%s\n' '--- existing namespace-label test patterns ---'
sed -n '350,430p' src/compute-plane-services/nvca/pkg/storage/cachebackend_samba_test.go
printf '%s\n' '--- namespace constructor remainder ---'
sed -n '45,66p' src/compute-plane-services/nvca/pkg/storage/controller_modelcache.goRepository: NVIDIA/nvcf Length of output: 8290 Exercise
🤖 Prompt for AI Agents |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🔎 Supported by static analysis
🏁 Script executed:
Repository: NVIDIA/nvcf
Length of output: 50368
🏁 Script executed:
Repository: NVIDIA/nvcf
Length of output: 50368
🏁 Script executed:
Repository: NVIDIA/nvcf
Length of output: 32801
🌐 Web query:
RFC 6902 JSON Patch add operation parent object must exist path💡 Result:
According to RFC 6902, the JSON Patch "add" operation requires that the parent object or array containing the target location must exist [1][2]. While the target location itself is not required to exist—in which case the "add" operation will create it—it remains an error if the container (the parent object or array) does not exist [1][3]. For example, if you are attempting to add a member to an object: - If you have an existing object {"a": {"foo": 1}} and use path "/a/b", the operation succeeds because the parent object "a" exists [1][4]. - If you have an object {"q": {"bar": 2}} and attempt to add a member at path "/a/b", the operation will fail because the parent object "a" does not exist in the document [1][3]. Similarly, you cannot add an element to an array that does not exist; the array itself must already be present in the document for the "add" operation to succeed at a specific index within that array [3][5].
Citations:
Handle namespaces without an existing
metadata.labelsmap.storage.NewModelCacheInitNamespace()sets labels only on the create path. When creation returnsAlreadyExists,ensureModelCacheNamespaceLabelcallsNamespaces().Patchwith JSON Patchadd; this can fail whenmetadata.labelsis absent, causing startup to return an error. Use a patch that createsmetadata.labelswhile preserving existing labels. Add tests for nil labels and existing labels.🤖 Prompt for AI Agents
Sources: Coding guidelines, Path instructions