From e4d19f33a8fe6e33275d0f13bbeaa13620481b55 Mon Sep 17 00:00:00 2001 From: Will Nevis Date: Tue, 28 Apr 2026 11:20:05 -0700 Subject: [PATCH 1/7] Fixes for crc development --- Tiltfile | 1 + hack/scripts/setup_crc.sh | 1 + 2 files changed, 2 insertions(+) diff --git a/Tiltfile b/Tiltfile index fa4e4e6..4888eb7 100644 --- a/Tiltfile +++ b/Tiltfile @@ -261,6 +261,7 @@ third_party_operator_flags = [ if settings.get('openshiftSCC'): third_party_operator_flags += [ '--set=altinity-clickhouse-operator.crdHook.enabled=false', + '--values=./deploy/operator/profiles/openshift.yaml' ] if settings.get("installTelemetry"): diff --git a/hack/scripts/setup_crc.sh b/hack/scripts/setup_crc.sh index 94efd06..90d6838 100755 --- a/hack/scripts/setup_crc.sh +++ b/hack/scripts/setup_crc.sh @@ -7,6 +7,7 @@ command -v oc >/dev/null 2>&1 || { echo "Error: oc is required but not installed command -v docker >/dev/null 2>&1 || { echo "Error: docker is required but not installed." >&2; exit 1; } echo "Configuring CRC resources..." +crc config set cpus 6 crc config set memory 16384 crc config set disk-size 80 From 481ed85d37a8574947168366d4350ca6f4a85c6a Mon Sep 17 00:00:00 2001 From: Will Nevis Date: Tue, 28 Apr 2026 11:20:19 -0700 Subject: [PATCH 2/7] Add openshift separate config --- deploy/operator/profiles/openshift.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 deploy/operator/profiles/openshift.yaml diff --git a/deploy/operator/profiles/openshift.yaml b/deploy/operator/profiles/openshift.yaml new file mode 100644 index 0000000..63e84ff --- /dev/null +++ b/deploy/operator/profiles/openshift.yaml @@ -0,0 +1,9 @@ +minio-operator: + operator: + securityContext: + runAsUser: null + runAsGroup: null + fsGroup: null + containerSecurityContext: + runAsUser: null + runAsGroup: null From 52d33cb12ba97b306877487b75192981eac65454 Mon Sep 17 00:00:00 2001 From: Will Nevis Date: Tue, 28 Apr 2026 12:08:44 -0700 Subject: [PATCH 3/7] Add openshift fsGroup support for kafka --- api/v2/weightsandbiases_types.go | 1 + api/v2/zz_generated.deepcopy.go | 5 +++++ .../overlays/openshift-kafka/kustomization.yaml | 4 ++++ .../kustomize/overlays/openshift-kafka/patch.yaml | 8 ++++++++ .../controller/infra/managed/kafka/strimzi/spec.go | 13 ++++++++++++- 5 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 hack/testing-manifests/wandb/kustomize/overlays/openshift-kafka/kustomization.yaml create mode 100644 hack/testing-manifests/wandb/kustomize/overlays/openshift-kafka/patch.yaml diff --git a/api/v2/weightsandbiases_types.go b/api/v2/weightsandbiases_types.go index c355ab0..53c86c2 100644 --- a/api/v2/weightsandbiases_types.go +++ b/api/v2/weightsandbiases_types.go @@ -387,6 +387,7 @@ type ManagedKafkaSpec struct { Name string `json:"name,omitempty"` Telemetry Telemetry `json:"telemetry,omitempty"` SkipDataRecovery bool `json:"skipDataRecovery,omitempty"` + FsGroup *int64 `json:"fsGroup,omitempty"` } type KafkaConnection struct { diff --git a/api/v2/zz_generated.deepcopy.go b/api/v2/zz_generated.deepcopy.go index f350b37..3911608 100644 --- a/api/v2/zz_generated.deepcopy.go +++ b/api/v2/zz_generated.deepcopy.go @@ -735,6 +735,11 @@ func (in *ManagedKafkaSpec) DeepCopyInto(out *ManagedKafkaSpec) { in.ManagedInfraSpec.DeepCopyInto(&out.ManagedInfraSpec) in.Config.DeepCopyInto(&out.Config) out.Telemetry = in.Telemetry + if in.FsGroup != nil { + in, out := &in.FsGroup, &out.FsGroup + *out = new(int64) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedKafkaSpec. diff --git a/hack/testing-manifests/wandb/kustomize/overlays/openshift-kafka/kustomization.yaml b/hack/testing-manifests/wandb/kustomize/overlays/openshift-kafka/kustomization.yaml new file mode 100644 index 0000000..a33514a --- /dev/null +++ b/hack/testing-manifests/wandb/kustomize/overlays/openshift-kafka/kustomization.yaml @@ -0,0 +1,4 @@ +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component +patches: + - path: patch.yaml diff --git a/hack/testing-manifests/wandb/kustomize/overlays/openshift-kafka/patch.yaml b/hack/testing-manifests/wandb/kustomize/overlays/openshift-kafka/patch.yaml new file mode 100644 index 0000000..c12eec6 --- /dev/null +++ b/hack/testing-manifests/wandb/kustomize/overlays/openshift-kafka/patch.yaml @@ -0,0 +1,8 @@ +apiVersion: apps.wandb.com/v2 +kind: WeightsAndBiases +metadata: + name: wandb +spec: + kafka: + managedKafka: + fsGroup: 0 diff --git a/internal/controller/infra/managed/kafka/strimzi/spec.go b/internal/controller/infra/managed/kafka/strimzi/spec.go index 65c60cd..6d6b9c4 100644 --- a/internal/controller/infra/managed/kafka/strimzi/spec.go +++ b/internal/controller/infra/managed/kafka/strimzi/spec.go @@ -8,7 +8,8 @@ import ( apiv2 "github.com/wandb/operator/api/v2" "github.com/wandb/operator/internal/controller/common" "github.com/wandb/operator/internal/logx" - "github.com/wandb/operator/pkg/vendored/strimzi-kafka/v1" + v1 "github.com/wandb/operator/pkg/vendored/strimzi-kafka/v1" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" @@ -41,6 +42,15 @@ func createKafkaMetricsConfig(telemetry apiv2.Telemetry) *v1.MetricsConfig { } } +// kafkaPodSecurityContext returns a PodSecurityContext with FSGroup set if fsGroup is non-nil. +// Returns nil when fsGroup is not configured, allowing the platform to apply its own defaults. +func kafkaPodSecurityContext(fsGroup *int64) *corev1.PodSecurityContext { + if fsGroup == nil { + return nil + } + return &corev1.PodSecurityContext{FSGroup: fsGroup} +} + // ToKafkaVendorSpec converts a KafkaSpec to a Kafka CR. // This function translates the high-level Kafka spec into the vendor-specific // Kafka format used by the Strimzi operator. @@ -187,6 +197,7 @@ func ToKafkaNodePoolVendorSpec( Metadata: &v1.MetadataTemplate{ Labels: BuildWandbKafkaLabels(wandb), }, + SecurityContext: kafkaPodSecurityContext(infraSpec.FsGroup), }, PersistentVolumeClaim: &v1.ResourceTemplate{ Metadata: &v1.MetadataTemplate{ From c949e8eb7a3788424edd2bbfca901d49f97729ad Mon Sep 17 00:00:00 2001 From: Will Nevis Date: Tue, 28 Apr 2026 12:25:12 -0700 Subject: [PATCH 4/7] Add property for openShift grafana, update API schema --- config/crd/bases/apps.wandb.com_weightsandbiases.yaml | 3 +++ deploy/operator/profiles/openshift.yaml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/config/crd/bases/apps.wandb.com_weightsandbiases.yaml b/config/crd/bases/apps.wandb.com_weightsandbiases.yaml index e26152d..b4f6f3e 100644 --- a/config/crd/bases/apps.wandb.com_weightsandbiases.yaml +++ b/config/crd/bases/apps.wandb.com_weightsandbiases.yaml @@ -1691,6 +1691,9 @@ spec: type: object type: object type: object + fsGroup: + format: int64 + type: integer name: type: string namespace: diff --git a/deploy/operator/profiles/openshift.yaml b/deploy/operator/profiles/openshift.yaml index 63e84ff..72f2106 100644 --- a/deploy/operator/profiles/openshift.yaml +++ b/deploy/operator/profiles/openshift.yaml @@ -1,3 +1,6 @@ +grafana-operator: + isOpenShift: true + minio-operator: operator: securityContext: From 7c9e26369077e59789526683017a8cbe2f1ad838 Mon Sep 17 00:00:00 2001 From: Will Nevis Date: Wed, 29 Apr 2026 14:30:18 -0700 Subject: [PATCH 5/7] Shift kafka fsgroup setting to environment variable --- api/v2/weightsandbiases_types.go | 1 - api/v2/zz_generated.deepcopy.go | 5 ----- config/openshift-dev/openshift-security.yaml | 5 +++++ .../openshift-kafka/kustomization.yaml | 4 ---- .../overlays/openshift-kafka/patch.yaml | 8 -------- .../infra/managed/kafka/strimzi/spec.go | 19 +++++++++++++------ 6 files changed, 18 insertions(+), 24 deletions(-) delete mode 100644 hack/testing-manifests/wandb/kustomize/overlays/openshift-kafka/kustomization.yaml delete mode 100644 hack/testing-manifests/wandb/kustomize/overlays/openshift-kafka/patch.yaml diff --git a/api/v2/weightsandbiases_types.go b/api/v2/weightsandbiases_types.go index 53c86c2..c355ab0 100644 --- a/api/v2/weightsandbiases_types.go +++ b/api/v2/weightsandbiases_types.go @@ -387,7 +387,6 @@ type ManagedKafkaSpec struct { Name string `json:"name,omitempty"` Telemetry Telemetry `json:"telemetry,omitempty"` SkipDataRecovery bool `json:"skipDataRecovery,omitempty"` - FsGroup *int64 `json:"fsGroup,omitempty"` } type KafkaConnection struct { diff --git a/api/v2/zz_generated.deepcopy.go b/api/v2/zz_generated.deepcopy.go index 3911608..f350b37 100644 --- a/api/v2/zz_generated.deepcopy.go +++ b/api/v2/zz_generated.deepcopy.go @@ -735,11 +735,6 @@ func (in *ManagedKafkaSpec) DeepCopyInto(out *ManagedKafkaSpec) { in.ManagedInfraSpec.DeepCopyInto(&out.ManagedInfraSpec) in.Config.DeepCopyInto(&out.Config) out.Telemetry = in.Telemetry - if in.FsGroup != nil { - in, out := &in.FsGroup, &out.FsGroup - *out = new(int64) - **out = **in - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedKafkaSpec. diff --git a/config/openshift-dev/openshift-security.yaml b/config/openshift-dev/openshift-security.yaml index c75c387..d2d93ae 100644 --- a/config/openshift-dev/openshift-security.yaml +++ b/config/openshift-dev/openshift-security.yaml @@ -12,3 +12,8 @@ capabilities: drop: - ALL +- op: add + path: /spec/template/spec/containers/0/env/- + value: + name: KAFKA_FSGROUP + value: "0" diff --git a/hack/testing-manifests/wandb/kustomize/overlays/openshift-kafka/kustomization.yaml b/hack/testing-manifests/wandb/kustomize/overlays/openshift-kafka/kustomization.yaml deleted file mode 100644 index a33514a..0000000 --- a/hack/testing-manifests/wandb/kustomize/overlays/openshift-kafka/kustomization.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1alpha1 -kind: Component -patches: - - path: patch.yaml diff --git a/hack/testing-manifests/wandb/kustomize/overlays/openshift-kafka/patch.yaml b/hack/testing-manifests/wandb/kustomize/overlays/openshift-kafka/patch.yaml deleted file mode 100644 index c12eec6..0000000 --- a/hack/testing-manifests/wandb/kustomize/overlays/openshift-kafka/patch.yaml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: apps.wandb.com/v2 -kind: WeightsAndBiases -metadata: - name: wandb -spec: - kafka: - managedKafka: - fsGroup: 0 diff --git a/internal/controller/infra/managed/kafka/strimzi/spec.go b/internal/controller/infra/managed/kafka/strimzi/spec.go index 6d6b9c4..8bf0aed 100644 --- a/internal/controller/infra/managed/kafka/strimzi/spec.go +++ b/internal/controller/infra/managed/kafka/strimzi/spec.go @@ -3,6 +3,7 @@ package strimzi import ( "context" "fmt" + "os" "strconv" apiv2 "github.com/wandb/operator/api/v2" @@ -42,13 +43,19 @@ func createKafkaMetricsConfig(telemetry apiv2.Telemetry) *v1.MetricsConfig { } } -// kafkaPodSecurityContext returns a PodSecurityContext with FSGroup set if fsGroup is non-nil. -// Returns nil when fsGroup is not configured, allowing the platform to apply its own defaults. -func kafkaPodSecurityContext(fsGroup *int64) *corev1.PodSecurityContext { - if fsGroup == nil { +// kafkaPodSecurityContext returns a PodSecurityContext with FSGroup set if the +// KAFKA_FSGROUP env var is configured on the operator. Returns nil otherwise, +// allowing the platform to apply its own defaults. +func kafkaPodSecurityContext() *corev1.PodSecurityContext { + val, ok := os.LookupEnv("KAFKA_FSGROUP") + if !ok { return nil } - return &corev1.PodSecurityContext{FSGroup: fsGroup} + fsGroup, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return nil + } + return &corev1.PodSecurityContext{FSGroup: &fsGroup} } // ToKafkaVendorSpec converts a KafkaSpec to a Kafka CR. @@ -197,7 +204,7 @@ func ToKafkaNodePoolVendorSpec( Metadata: &v1.MetadataTemplate{ Labels: BuildWandbKafkaLabels(wandb), }, - SecurityContext: kafkaPodSecurityContext(infraSpec.FsGroup), + SecurityContext: kafkaPodSecurityContext(), }, PersistentVolumeClaim: &v1.ResourceTemplate{ Metadata: &v1.MetadataTemplate{ From c695a87ce6d97c69e2755a8f21bf168194918964 Mon Sep 17 00:00:00 2001 From: Will Nevis Date: Wed, 29 Apr 2026 14:36:32 -0700 Subject: [PATCH 6/7] Regenerate CRD --- config/crd/bases/apps.wandb.com_weightsandbiases.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/config/crd/bases/apps.wandb.com_weightsandbiases.yaml b/config/crd/bases/apps.wandb.com_weightsandbiases.yaml index b4f6f3e..e26152d 100644 --- a/config/crd/bases/apps.wandb.com_weightsandbiases.yaml +++ b/config/crd/bases/apps.wandb.com_weightsandbiases.yaml @@ -1691,9 +1691,6 @@ spec: type: object type: object type: object - fsGroup: - format: int64 - type: integer name: type: string namespace: From 8fa4b4783c11da89ebee7696f30d80d7aed1d1cf Mon Sep 17 00:00:00 2001 From: Will Nevis Date: Wed, 29 Apr 2026 15:09:09 -0700 Subject: [PATCH 7/7] Fix to switch to proper context after creating new namespaces --- hack/scripts/setup_crc.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/hack/scripts/setup_crc.sh b/hack/scripts/setup_crc.sh index 90d6838..721991c 100755 --- a/hack/scripts/setup_crc.sh +++ b/hack/scripts/setup_crc.sh @@ -7,9 +7,9 @@ command -v oc >/dev/null 2>&1 || { echo "Error: oc is required but not installed command -v docker >/dev/null 2>&1 || { echo "Error: docker is required but not installed." >&2; exit 1; } echo "Configuring CRC resources..." -crc config set cpus 6 -crc config set memory 16384 -crc config set disk-size 80 +crc config set cpus 6 >/dev/null +crc config set memory 16384 >/dev/null +crc config set disk-size 80 >/dev/null CRC_STATUS=$(crc status --output json 2>/dev/null | python3 -c "import sys,json; print(json.load(sys.stdin).get('crcStatus','Unknown'))" 2>/dev/null || echo "Unknown") if [[ "$CRC_STATUS" != "Running" ]]; then @@ -75,6 +75,8 @@ oc new-project operator-system 2>/dev/null || oc project operator-system 2>/dev/ echo "Creating wandb-operator namespace..." oc new-project wandb-operator 2>/dev/null || oc project wandb-operator 2>/dev/null || true +kubectl config use-context crc-admin + echo "" echo "Done. CRC is ready for Tilt." echo ""