-
Notifications
You must be signed in to change notification settings - Fork 1
feat(backend): Standardize labels across all deployed resources #334
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
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 |
|---|---|---|
|
|
@@ -2,16 +2,24 @@ package common | |
|
|
||
| import ( | ||
| apiv2 "github.com/wandb/operator/api/v2" | ||
| "github.com/wandb/operator/pkg/utils" | ||
| ) | ||
|
|
||
| const ( | ||
| WandbNameLabel = "weightsandbiases.apps.wandb.com/name" | ||
| WandbNamespaceLabel = "weightsandbiases.apps.wandb.com/namespace" | ||
| WandbComponentLabel = "weightsandbiases.apps.wandb.com/component" | ||
|
|
||
| AppNameLabel = "app.kubernetes.io/name" | ||
| AppInstanceLabel = "app.kubernetes.io/instance" | ||
| AppPartOfLabel = "app.kubernetes.io/part-of" | ||
| AppManagedByLabel = "app.kubernetes.io/managed-by" | ||
|
|
||
| PartOfWandb = "wandb" | ||
| ManagedByWandbOperator = "wandb-operator" | ||
| ) | ||
|
|
||
| // HasAllLabelKeys reports whether existing contains every key present in desired, | ||
| // regardless of value. | ||
| // HasAllLabelKeys reports whether existing has every key in desired. | ||
| func HasAllLabelKeys(existing, desired map[string]string) bool { | ||
| for k := range desired { | ||
| if _, ok := existing[k]; !ok { | ||
|
|
@@ -21,12 +29,28 @@ func HasAllLabelKeys(existing, desired map[string]string) bool { | |
| return true | ||
| } | ||
|
|
||
| // BuildWandbLabels returns the standard wandb labels for resources managed | ||
| // on behalf of the given WeightsAndBiases CR. | ||
| // BuildWandbLabels returns ownership labels; componentName is the service id. | ||
| func BuildWandbLabels(wandb *apiv2.WeightsAndBiases, componentName string) map[string]string { | ||
| return map[string]string{ | ||
| WandbNameLabel: wandb.Name, | ||
| WandbNamespaceLabel: wandb.Namespace, | ||
| WandbComponentLabel: componentName, | ||
| } | ||
| } | ||
|
|
||
| // BuildIdentityLabels returns name, part-of, and managed-by (not instance). | ||
| func BuildIdentityLabels(serviceName string) map[string]string { | ||
| return map[string]string{ | ||
| AppNameLabel: serviceName, | ||
| AppPartOfLabel: PartOfWandb, | ||
| AppManagedByLabel: ManagedByWandbOperator, | ||
| } | ||
| } | ||
|
|
||
| // BuildApplicationLabels merges ownership+identity for MetaTemplate only. | ||
| func BuildApplicationLabels(wandb *apiv2.WeightsAndBiases, serviceName string) map[string]string { | ||
| return utils.MergeMapsStringString( | ||
| BuildWandbLabels(wandb, serviceName), | ||
| BuildIdentityLabels(serviceName), | ||
| ) | ||
|
Comment on lines
+41
to
+55
Contributor
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. 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift Set
📍 Affects 5 files
🤖 Prompt for AI Agents |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| package common | ||
|
|
||
| import ( | ||
| . "github.com/onsi/ginkgo/v2" | ||
| . "github.com/onsi/gomega" | ||
| apiv2 "github.com/wandb/operator/api/v2" | ||
| metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
| ) | ||
|
|
||
| var _ = Describe("BuildIdentityLabels", func() { | ||
| It("sets name, part-of, and managed-by without instance", func() { | ||
| Expect(BuildIdentityLabels("api")).To(Equal(map[string]string{ | ||
| AppNameLabel: "api", | ||
| AppPartOfLabel: PartOfWandb, | ||
| AppManagedByLabel: ManagedByWandbOperator, | ||
| })) | ||
| }) | ||
| }) | ||
|
|
||
| var _ = Describe("BuildApplicationLabels", func() { | ||
| It("merges ownership and identity labels", func() { | ||
| wandb := &apiv2.WeightsAndBiases{ | ||
| ObjectMeta: metav1.ObjectMeta{Name: "wandb", Namespace: "wandb-ns"}, | ||
| } | ||
|
|
||
| Expect(BuildApplicationLabels(wandb, "api")).To(Equal(map[string]string{ | ||
| WandbNameLabel: "wandb", | ||
| WandbNamespaceLabel: "wandb-ns", | ||
| WandbComponentLabel: "api", | ||
| AppNameLabel: "api", | ||
| AppPartOfLabel: PartOfWandb, | ||
| AppManagedByLabel: ManagedByWandbOperator, | ||
| })) | ||
| }) | ||
| }) | ||
|
|
||
| var _ = Describe("HasAllLabelKeys", func() { | ||
| It("returns true when every desired key is present", func() { | ||
| Expect(HasAllLabelKeys( | ||
| map[string]string{"a": "1", "b": "2", "c": "3"}, | ||
| map[string]string{"a": "x", "b": "y"}, | ||
| )).To(BeTrue()) | ||
| }) | ||
|
|
||
| It("returns false when a desired key is missing", func() { | ||
| Expect(HasAllLabelKeys( | ||
| map[string]string{"a": "1"}, | ||
| map[string]string{"a": "1", "b": "2"}, | ||
| )).To(BeFalse()) | ||
| }) | ||
| }) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,7 @@ import ( | |
|
|
||
| "github.com/stretchr/testify/require" | ||
| apiv2 "github.com/wandb/operator/api/v2" | ||
| "github.com/wandb/operator/internal/controller/common" | ||
| "github.com/wandb/operator/internal/controller/infra/objectstore" | ||
| "github.com/wandb/operator/pkg/utils" | ||
| "github.com/wandb/operator/pkg/wandb/manifest" | ||
|
|
@@ -63,6 +64,11 @@ func TestToEtcdApplication(t *testing.T) { | |
| requireKafkaPodSecurityContext(t, app.Spec.PodTemplate.Spec.SecurityContext) | ||
| requireKafkaContainerSecurityContext(t, app.Spec.PodTemplate.Spec.Containers[0].SecurityContext) | ||
| require.NotNil(t, app.Spec.ServiceTemplate) | ||
| require.Equal(t, BuildWandbKafkaLabels(wandb), app.Labels) | ||
| require.Equal(t, "wandb-kafka-etcd", app.Spec.MetaTemplate.Labels[common.AppNameLabel]) | ||
| require.Equal(t, common.PartOfWandb, app.Spec.MetaTemplate.Labels[common.AppPartOfLabel]) | ||
| require.Equal(t, common.ManagedByWandbOperator, app.Spec.MetaTemplate.Labels[common.AppManagedByLabel]) | ||
| require.Equal(t, KafkaModuleName, app.Spec.MetaTemplate.Labels[common.WandbComponentLabel]) | ||
|
Comment on lines
+67
to
+71
Contributor
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. 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
fd 'suite_test.go' internal/controller/infra/managed/kafka/bufstream
rg -n -C 3 'RunSpecs|Describe\(|TestToEtcdApplication|TestToBufstreamApplication' \
internal/controller/infra/managed/kafka/bufstreamRepository: wandb/operator Length of output: 2861 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- candidate test file ---'
sed -n '1,220p' internal/controller/infra/managed/kafka/bufstream/spec_test.go
printf '%s\n' '--- nearby suite files ---'
fd 'suite_test.go' internal/controller/infra/managed/kafka internal/controller/infra/managed | sort
printf '%s\n' '--- test framework usage in the package ---'
rg -n 'github.com/onsi/(ginkgo|gomega)|github.com/stretchr/testify|func Test|Describe\(|RunSpecs' \
internal/controller/infra/managed/kafka/bufstream
printf '%s\n' '--- repository test framework usage ---'
rg -n 'github.com/onsi/(ginkgo|gomega)|github.com/stretchr/testify|RunSpecs' \
--glob '*_test.go' | head -120Repository: wandb/operator Length of output: 13547 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- Ginkgo/Gomega dependencies and usage ---'
rg -n 'onsi/(ginkgo|gomega)|ginkgo|gomega' go.mod go.sum internal --glob '*_test.go' --glob 'go.mod' | head -160
printf '%s\n' '--- existing suite patterns ---'
for f in $(fd -t f 'suite_test.go' internal/controller/infra/managed | head -5); do
echo "### $f"
sed -n '1,80p' "$f"
done
printf '%s\n' '--- package test files ---'
git ls-files 'internal/controller/infra/managed/kafka/bufstream/*_test.go'Repository: wandb/operator Length of output: 11739 Use the package Ginkgo/Gomega suite for these assertions. Add 🤖 Prompt for AI AgentsSource: Coding guidelines |
||
| } | ||
|
|
||
| func TestToEtcdApplicationHA(t *testing.T) { | ||
|
|
@@ -130,6 +136,11 @@ func TestToBufstreamApplication(t *testing.T) { | |
| require.Equal(t, "wandb-kafka", app.Name) | ||
| require.Equal(t, "Deployment", app.Spec.Kind) | ||
| require.NotNil(t, app.Spec.Replicas) | ||
| require.Equal(t, BuildWandbKafkaLabels(wandb), app.Labels) | ||
| require.Equal(t, "wandb-kafka", app.Spec.MetaTemplate.Labels[common.AppNameLabel]) | ||
| require.Equal(t, common.PartOfWandb, app.Spec.MetaTemplate.Labels[common.AppPartOfLabel]) | ||
| require.Equal(t, common.ManagedByWandbOperator, app.Spec.MetaTemplate.Labels[common.AppManagedByLabel]) | ||
| require.Equal(t, KafkaModuleName, app.Spec.MetaTemplate.Labels[common.WandbComponentLabel]) | ||
| require.Len(t, app.Spec.PodTemplate.Spec.InitContainers, 1) | ||
| ensureBucket := app.Spec.PodTemplate.Spec.InitContainers[0] | ||
| require.Equal(t, "ensure-bucket", ensureBucket.Name) | ||
|
|
||
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.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Do not delete resources based only on user-controlled labels.
The broadened selectors can match unrelated Jobs or CronJobs in the namespace. A user can create a resource with the same application-name and instance labels. Cleanup then deletes it without checking its controller owner or an accepted managed-by value.
internal/controller/application_controller.go#L701-L706: list broadly for migration, then delete only Jobs controlled byappand with an accepted legacy or current managed-by value.internal/controller/application_controller.go#L796-L801: apply the same ownership and managed-by validation before deleting CronJobs.📍 Affects 1 file
internal/controller/application_controller.go#L701-L706(this comment)internal/controller/application_controller.go#L796-L801🤖 Prompt for AI Agents