diff --git a/api/v1alpha1/dragonfly_types.go b/api/v1alpha1/dragonfly_types.go index 99397b53..65ebe11f 100644 --- a/api/v1alpha1/dragonfly_types.go +++ b/api/v1alpha1/dragonfly_types.go @@ -189,14 +189,6 @@ type DragonflySpec struct { // +kubebuilder:validation:Optional EnableReplicationReadinessGate bool `json:"enableReplicationReadinessGate,omitempty"` - // (Optional) Whether to create a NetworkPolicy for this Dragonfly instance. - // The NetworkPolicy restricts admin port access to operator and peer pods only. - // Defaults to true. - // +optional - // +kubebuilder:validation:Optional - // +kubebuilder:default:=true - NetworkPolicyEnabled *bool `json:"networkPolicyEnabled,omitempty"` - // (Optional) Dragonfly Pod Disruption Budget configuration // +optional // +kubebuilder:validation:Optional diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 99755151..3586c8f6 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -246,11 +246,6 @@ func (in *DragonflySpec) DeepCopyInto(out *DragonflySpec) { *out = new(MetadataSpec) (*in).DeepCopyInto(*out) } - if in.NetworkPolicyEnabled != nil { - in, out := &in.NetworkPolicyEnabled, &out.NetworkPolicyEnabled - *out = new(bool) - **out = **in - } if in.Pdb != nil { in, out := &in.Pdb, &out.Pdb *out = new(PdbSpec) diff --git a/charts/dragonfly-operator/templates/clusterroles.yaml b/charts/dragonfly-operator/templates/clusterroles.yaml index 0d0f2ee1..51015708 100644 --- a/charts/dragonfly-operator/templates/clusterroles.yaml +++ b/charts/dragonfly-operator/templates/clusterroles.yaml @@ -82,18 +82,6 @@ rules: - patch - update - watch - - apiGroups: - - networking.k8s.io - resources: - - networkpolicies - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - apiGroups: - dragonflydb.io resources: diff --git a/charts/dragonfly-operator/templates/crds.yaml b/charts/dragonfly-operator/templates/crds.yaml index ddcc083c..853e44ad 100644 --- a/charts/dragonfly-operator/templates/crds.yaml +++ b/charts/dragonfly-operator/templates/crds.yaml @@ -6099,13 +6099,6 @@ spec: description: (Optional) Dragonfly memcached port format: int32 type: integer - networkPolicyEnabled: - default: true - description: |- - (Optional) Whether to create a NetworkPolicy for this Dragonfly instance. - The NetworkPolicy restricts admin port access to operator and peer pods only. - Defaults to true. - type: boolean nodeSelector: additionalProperties: type: string diff --git a/charts/dragonfly-operator/templates/deployment.yaml b/charts/dragonfly-operator/templates/deployment.yaml index f20e532e..a5881822 100644 --- a/charts/dragonfly-operator/templates/deployment.yaml +++ b/charts/dragonfly-operator/templates/deployment.yaml @@ -67,8 +67,6 @@ spec: {{- toYaml .Values.rbacProxy.resources | nindent 12 }} {{- end }} - name: manager - command: - - /manager args: - --leader-elect {{- if .Values.dragonflyImage }} @@ -80,11 +78,8 @@ spec: {{- with .Values.manager.extraArgs}} {{- toYaml . | nindent 12 }} {{- end }} - env: - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace + command: + - /manager securityContext: {{- toYaml .Values.manager.securityContext | nindent 12 }} image: "{{ .Values.manager.image.repository }}:{{ .Values.manager.image.tag | default .Chart.AppVersion }}" diff --git a/cmd/main.go b/cmd/main.go index 850cfce8..6ed6724b 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -145,20 +145,12 @@ func main() { defer eventBroadcaster.Shutdown() - operatorNamespace := getOperatorNamespace() - if operatorNamespace != "" { - setupLog.Info(fmt.Sprintf("Operator namespace: %s", operatorNamespace)) - } else { - setupLog.Info("Operator namespace could not be determined; admin port NetworkPolicy will be restricted to same-namespace only") - } - if err = (&controller.DragonflyReconciler{ Reconciler: controller.Reconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), EventRecorder: eventRecorder, DefaultDragonflyImage: dragonflyImage, - OperatorNamespace: operatorNamespace, }, }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "Dragonfly") @@ -171,7 +163,6 @@ func main() { Scheme: mgr.GetScheme(), EventRecorder: eventRecorder, DefaultDragonflyImage: dragonflyImage, - OperatorNamespace: operatorNamespace, }, }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "Health") @@ -236,21 +227,3 @@ func addNamespacesToOpts(namespaces string, ops *ctrl.Options) error { } return nil } - -const saNamespaceFile = "/var/run/secrets/kubernetes.io/serviceaccount/namespace" - -func getOperatorNamespace() string { - return resolveOperatorNamespace(saNamespaceFile) -} - -func resolveOperatorNamespace(saFile string) string { - if ns, ok := os.LookupEnv("POD_NAMESPACE"); ok && ns != "" { - return ns - } - if data, err := os.ReadFile(saFile); err == nil { - if ns := strings.TrimSpace(string(data)); ns != "" { - return ns - } - } - return "" -} diff --git a/cmd/main_test.go b/cmd/main_test.go deleted file mode 100644 index c33539ad..00000000 --- a/cmd/main_test.go +++ /dev/null @@ -1,78 +0,0 @@ -package main - -import ( - "os" - "path/filepath" - "testing" -) - -func TestResolveOperatorNamespace(t *testing.T) { - tests := []struct { - name string - envValue *string // nil = unset, "" = set but empty - fileBody string // written to a temp file; empty string means no file - want string - }{ - { - name: "env var set", - envValue: strPtr("operator-ns"), - want: "operator-ns", - }, - { - name: "env var takes precedence over file", - envValue: strPtr("from-env"), - fileBody: "from-file", - want: "from-env", - }, - { - name: "falls back to SA file when env unset", - fileBody: "sa-namespace\n", - want: "sa-namespace", - }, - { - name: "trims whitespace from SA file", - fileBody: " my-ns \n", - want: "my-ns", - }, - { - name: "empty env var ignored, falls back to file", - envValue: strPtr(""), - fileBody: "fallback-ns", - want: "fallback-ns", - }, - { - name: "returns empty when nothing available", - want: "", - }, - { - name: "empty SA file returns empty", - fileBody: " \n", - want: "", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - t.Setenv("POD_NAMESPACE", "") - os.Unsetenv("POD_NAMESPACE") - - if tt.envValue != nil { - t.Setenv("POD_NAMESPACE", *tt.envValue) - } - - saFile := filepath.Join(t.TempDir(), "namespace") - if tt.fileBody != "" { - if err := os.WriteFile(saFile, []byte(tt.fileBody), 0o600); err != nil { - t.Fatal(err) - } - } - - got := resolveOperatorNamespace(saFile) - if got != tt.want { - t.Errorf("resolveOperatorNamespace() = %q, want %q", got, tt.want) - } - }) - } -} - -func strPtr(s string) *string { return &s } diff --git a/config/crd/bases/dragonflydb.io_dragonflies.yaml b/config/crd/bases/dragonflydb.io_dragonflies.yaml index 61574fde..f2c66a4f 100644 --- a/config/crd/bases/dragonflydb.io_dragonflies.yaml +++ b/config/crd/bases/dragonflydb.io_dragonflies.yaml @@ -6093,13 +6093,6 @@ spec: description: (Optional) Dragonfly memcached port format: int32 type: integer - networkPolicyEnabled: - default: true - description: |- - (Optional) Whether to create a NetworkPolicy for this Dragonfly instance. - The NetworkPolicy restricts admin port access to operator and peer pods only. - Defaults to true. - type: boolean nodeSelector: additionalProperties: type: string diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index 8cb61413..dd6029ca 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -72,11 +72,6 @@ spec: - --leader-elect image: controller:latest name: manager - env: - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace securityContext: allowPrivilegeEscalation: false capabilities: diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index dd342efe..7f0cc79c 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -71,18 +71,6 @@ rules: - get - patch - update -- apiGroups: - - networking.k8s.io - resources: - - networkpolicies - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - apiGroups: - policy resources: diff --git a/e2e/dragonfly_controller_test.go b/e2e/dragonfly_controller_test.go index cb6e022c..c629d69d 100644 --- a/e2e/dragonfly_controller_test.go +++ b/e2e/dragonfly_controller_test.go @@ -620,16 +620,14 @@ user john on >peacepass -@all +@string +hset }, }) Expect(err).To(BeNil()) - disabled := false err = k8sClient.Create(ctx, &resourcesv1.Dragonfly{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: namespace, }, Spec: resourcesv1.DragonflySpec{ - Replicas: 1, - Args: args, - NetworkPolicyEnabled: &disabled, + Replicas: 1, + Args: args, AclFromSecret: &corev1.SecretKeySelector{ LocalObjectReference: corev1.LocalObjectReference{ Name: "df-acl", diff --git a/e2e/dragonfly_pod_lifecycle_controller_test.go b/e2e/dragonfly_pod_lifecycle_controller_test.go index a4d145b4..3e0c6118 100644 --- a/e2e/dragonfly_pod_lifecycle_controller_test.go +++ b/e2e/dragonfly_pod_lifecycle_controller_test.go @@ -42,15 +42,13 @@ var _ = Describe("DF Pod Lifecycle Reconciler", Ordered, FlakeAttempts(3), func( namespace := "default" replicas := 4 - disabled := false df := dfv1alpha1.Dragonfly{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: namespace, }, Spec: dfv1alpha1.DragonflySpec{ - Replicas: int32(replicas), - NetworkPolicyEnabled: &disabled, + Replicas: int32(replicas), }, } diff --git a/internal/controller/base_controller.go b/internal/controller/base_controller.go index 0516d1e8..9d83fc15 100644 --- a/internal/controller/base_controller.go +++ b/internal/controller/base_controller.go @@ -32,7 +32,6 @@ type Reconciler struct { Scheme *runtime.Scheme EventRecorder record.EventRecorder DefaultDragonflyImage string - OperatorNamespace string } func (r *Reconciler) getDragonflyInstance(ctx context.Context, namespacedName types.NamespacedName, log logr.Logger) (*DragonflyInstance, error) { @@ -50,6 +49,5 @@ func (r *Reconciler) getDragonflyInstance(ctx context.Context, namespacedName ty scheme: r.Scheme, eventRecorder: r.EventRecorder, defaultDragonflyImage: r.DefaultDragonflyImage, - operatorNamespace: r.OperatorNamespace, }, nil } diff --git a/internal/controller/dragonfly_controller.go b/internal/controller/dragonfly_controller.go index 788b6636..849e8e57 100644 --- a/internal/controller/dragonfly_controller.go +++ b/internal/controller/dragonfly_controller.go @@ -24,7 +24,6 @@ import ( dfv1alpha1 "github.com/dragonflydb/dragonfly-operator/api/v1alpha1" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" - networkingv1 "k8s.io/api/networking/v1" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" @@ -46,7 +45,6 @@ type DragonflyReconciler struct { //+kubebuilder:rbac:groups="",resources=pods,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups="",resources=events,verbs=create;patch //+kubebuilder:rbac:groups="",resources=configmaps,verbs=get;list;watch;create;update;patch;delete -//+kubebuilder:rbac:groups=networking.k8s.io,resources=networkpolicies,verbs=get;list;watch;create;update;patch;delete // Reconcile is part of the main kubernetes reconciliation loop which aims to // move the current state of the cluster closer to the desired state. @@ -160,7 +158,6 @@ func (r *DragonflyReconciler) SetupWithManager(mgr ctrl.Manager) error { Owns(&appsv1.StatefulSet{}, builder.MatchEveryOwner). Owns(&corev1.Service{}, builder.MatchEveryOwner). Owns(&corev1.ConfigMap{}, builder.MatchEveryOwner). - Owns(&networkingv1.NetworkPolicy{}, builder.MatchEveryOwner). Named("Dragonfly"). Complete(r) } diff --git a/internal/controller/dragonfly_instance.go b/internal/controller/dragonfly_instance.go index 8873fc81..a9f25bc1 100644 --- a/internal/controller/dragonfly_instance.go +++ b/internal/controller/dragonfly_instance.go @@ -33,7 +33,6 @@ import ( "github.com/redis/go-redis/v9/maintnotifications" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" - networkingv1 "k8s.io/api/networking/v1" policyv1 "k8s.io/api/policy/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -54,7 +53,6 @@ type DragonflyInstance struct { scheme *runtime.Scheme eventRecorder record.EventRecorder defaultDragonflyImage string - operatorNamespace string redisClients map[string]*redis.Client } @@ -617,7 +615,7 @@ func (dfi *DragonflyInstance) hasMasterRole(ctx context.Context, redisClient *re // reconcileResources creates or updates the dragonfly resources func (dfi *DragonflyInstance) reconcileResources(ctx context.Context) error { - dfResources, err := resources.GenerateDragonflyResources(dfi.df, dfi.defaultDragonflyImage, dfi.operatorNamespace) + dfResources, err := resources.GenerateDragonflyResources(dfi.df, dfi.defaultDragonflyImage) if err != nil { return fmt.Errorf("failed to generate dragonfly resources") } @@ -732,16 +730,6 @@ func (dfi *DragonflyInstance) reconcileResources(ctx context.Context) error { return fmt.Errorf("failed to delete pod disruption budget: %w", err) } } - if dfi.df.Spec.NetworkPolicyEnabled != nil && !*dfi.df.Spec.NetworkPolicyEnabled { - if err = dfi.client.Delete(ctx, &networkingv1.NetworkPolicy{ - ObjectMeta: metav1.ObjectMeta{ - Name: dfi.df.Name, - Namespace: dfi.df.Namespace, - }, - }); err != nil && !apierrors.IsNotFound(err) { - return fmt.Errorf("failed to delete network policy: %w", err) - } - } status := dfi.getStatus() if status.Phase == "" { status.Phase = PhaseResourcesCreated diff --git a/internal/resources/const.go b/internal/resources/const.go index 9cfb30b2..5509057d 100644 --- a/internal/resources/const.go +++ b/internal/resources/const.go @@ -97,13 +97,6 @@ const ( ReplicationReadyConditionType = "dragonflydb.io/replication-ready" - OperatorControlPlaneLabelKey = "control-plane" - OperatorControlPlaneLabelValue = "controller-manager" - - // KubernetesNamespaceLabelKey is the well-known label automatically set on - // namespaces by Kubernetes >= 1.21, used to pin NetworkPolicy selectors. - KubernetesNamespaceLabelKey = "kubernetes.io/metadata.name" - // Probe ConfigMap suffixes — appended to df.Name LivenessProbeConfigMapSuffix = "liveness-probe" ReadinessProbeConfigMapSuffix = "readiness-probe" diff --git a/internal/resources/image_test.go b/internal/resources/image_test.go index 0309f820..6a12fedd 100644 --- a/internal/resources/image_test.go +++ b/internal/resources/image_test.go @@ -44,7 +44,7 @@ func TestGenerateDragonflyResources_ImageResolution(t *testing.T) { }, } - objs, err := GenerateDragonflyResources(df, tt.defaultImage, "") + objs, err := GenerateDragonflyResources(df, tt.defaultImage) assert.NoError(t, err) var sts *appsv1.StatefulSet diff --git a/internal/resources/resources.go b/internal/resources/resources.go index 2ae709e1..3979cb2c 100644 --- a/internal/resources/resources.go +++ b/internal/resources/resources.go @@ -23,7 +23,6 @@ import ( resourcesv1 "github.com/dragonflydb/dragonfly-operator/api/v1alpha1" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" - networkingv1 "k8s.io/api/networking/v1" policyv1 "k8s.io/api/policy/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" @@ -128,7 +127,7 @@ func generateProbeConfigMap(df *resourcesv1.Dragonfly, name, key, script string) // GenerateDragonflyResources returns the resources required for a Dragonfly // Instance -func GenerateDragonflyResources(df *resourcesv1.Dragonfly, defaultDragonflyImage, operatorNamespace string) ([]client.Object, error) { +func GenerateDragonflyResources(df *resourcesv1.Dragonfly, defaultDragonflyImage string) ([]client.Object, error) { if err := checkLabels("spec.labels", df.Spec.Labels); err != nil { return nil, err } @@ -663,113 +662,9 @@ func GenerateDragonflyResources(df *resourcesv1.Dragonfly, defaultDragonflyImage resources = append(resources, &pdb) } - if isNetworkPolicyEnabled(df) { - np := generateNetworkPolicy(df, operatorNamespace) - resources = append(resources, &np) - } - return resources, nil } -func isNetworkPolicyEnabled(df *resourcesv1.Dragonfly) bool { - return df.Spec.NetworkPolicyEnabled == nil || *df.Spec.NetworkPolicyEnabled -} - -func generateNetworkPolicy(df *resourcesv1.Dragonfly, operatorNamespace string) networkingv1.NetworkPolicy { - protocolTCP := corev1.ProtocolTCP - - instanceSelector := map[string]string{ - DragonflyNameLabelKey: df.Name, - KubernetesPartOfLabelKey: KubernetesPartOf, - KubernetesAppNameLabelKey: KubernetesAppName, - } - - sameNamespacePeer := networkingv1.NetworkPolicyPeer{ - PodSelector: &metav1.LabelSelector{}, - } - - clientPortRule := networkingv1.NetworkPolicyIngressRule{ - Ports: []networkingv1.NetworkPolicyPort{ - { - Protocol: &protocolTCP, - Port: &intstr.IntOrString{Type: intstr.Int, IntVal: DragonflyPort}, - }, - }, - From: []networkingv1.NetworkPolicyPeer{sameNamespacePeer}, - } - - operatorPeer := networkingv1.NetworkPolicyPeer{ - PodSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - OperatorControlPlaneLabelKey: OperatorControlPlaneLabelValue, - }, - }, - } - if operatorNamespace != "" { - operatorPeer.NamespaceSelector = &metav1.LabelSelector{ - MatchLabels: map[string]string{ - KubernetesNamespaceLabelKey: operatorNamespace, - }, - } - } - - adminPortRule := networkingv1.NetworkPolicyIngressRule{ - Ports: []networkingv1.NetworkPolicyPort{ - { - Protocol: &protocolTCP, - Port: &intstr.IntOrString{Type: intstr.Int, IntVal: DragonflyAdminPort}, - }, - }, - From: []networkingv1.NetworkPolicyPeer{ - operatorPeer, - { - PodSelector: &metav1.LabelSelector{ - MatchLabels: instanceSelector, - }, - }, - }, - } - - ingressRules := []networkingv1.NetworkPolicyIngressRule{clientPortRule, adminPortRule} - - if df.Spec.MemcachedPort != 0 { - memcachedPortRule := networkingv1.NetworkPolicyIngressRule{ - Ports: []networkingv1.NetworkPolicyPort{ - { - Protocol: &protocolTCP, - Port: &intstr.IntOrString{Type: intstr.Int, IntVal: df.Spec.MemcachedPort}, - }, - }, - From: []networkingv1.NetworkPolicyPeer{sameNamespacePeer}, - } - ingressRules = append(ingressRules, memcachedPortRule) - } - - return networkingv1.NetworkPolicy{ - ObjectMeta: metav1.ObjectMeta{ - Name: df.Name, - Namespace: df.Namespace, - OwnerReferences: []metav1.OwnerReference{ - { - APIVersion: df.APIVersion, - Kind: df.Kind, - Name: df.Name, - UID: df.UID, - }, - }, - Labels: generateResourceLabels(df), - Annotations: generateResourceAnnotations(df), - }, - Spec: networkingv1.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{ - MatchLabels: instanceSelector, - }, - Ingress: ingressRules, - PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeIngress}, - }, - } -} - // mergeNamedSlices will merge base into override, override takes precendence func mergeNamedSlices[T any](base, override []T, getName func(T) string) []T { existing := make(map[string]bool, len(override)) diff --git a/internal/resources/resources_test.go b/internal/resources/resources_test.go index d73cc0a7..44e5bfbb 100644 --- a/internal/resources/resources_test.go +++ b/internal/resources/resources_test.go @@ -9,10 +9,8 @@ import ( "github.com/stretchr/testify/require" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" - networkingv1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/intstr" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -97,7 +95,7 @@ func TestGenerateDragonflyResources_ReadinessGateDisabled(t *testing.T) { df := newTestDragonfly(2) df.Spec.EnableReplicationReadinessGate = false - resources, err := GenerateDragonflyResources(df, "", "") + resources, err := GenerateDragonflyResources(df, "") require.NoError(t, err) for _, obj := range resources { @@ -114,7 +112,7 @@ func TestGenerateDragonflyResources_ReadinessGateEnabled(t *testing.T) { df := newTestDragonfly(2) df.Spec.EnableReplicationReadinessGate = true - resources, err := GenerateDragonflyResources(df, "", "") + resources, err := GenerateDragonflyResources(df, "") require.NoError(t, err) for _, obj := range resources { @@ -131,97 +129,6 @@ func TestGenerateDragonflyResources_ReadinessGateEnabled(t *testing.T) { t.Fatal("StatefulSet not found in generated resources") } -func findNetworkPolicy(objs []client.Object) *networkingv1.NetworkPolicy { - for _, obj := range objs { - if np, ok := obj.(*networkingv1.NetworkPolicy); ok { - return np - } - } - return nil -} - -func TestGenerateDragonflyResources_NetworkPolicyDefault(t *testing.T) { - df := &resourcesv1.Dragonfly{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-df", - Namespace: "default", - }, - Spec: resourcesv1.DragonflySpec{ - Replicas: 1, - }, - } - - objs, err := GenerateDragonflyResources(df, "", "dragonfly-system") - require.NoError(t, err) - - np := findNetworkPolicy(objs) - require.NotNil(t, np, "NetworkPolicy should be generated by default") - - assert.Equal(t, "test-df", np.Name) - assert.Equal(t, "default", np.Namespace) - - assert.Equal(t, map[string]string{ - DragonflyNameLabelKey: "test-df", - KubernetesPartOfLabelKey: KubernetesPartOf, - KubernetesAppNameLabelKey: KubernetesAppName, - }, np.Spec.PodSelector.MatchLabels) - - require.Len(t, np.Spec.Ingress, 2) - assert.Equal(t, []networkingv1.PolicyType{networkingv1.PolicyTypeIngress}, np.Spec.PolicyTypes) - - protocolTCP := corev1.ProtocolTCP - - clientRule := np.Spec.Ingress[0] - require.Len(t, clientRule.From, 1, "client port should be restricted to same namespace") - assert.Equal(t, &metav1.LabelSelector{}, clientRule.From[0].PodSelector) - assert.Nil(t, clientRule.From[0].NamespaceSelector, "client port should not allow cross-namespace") - require.Len(t, clientRule.Ports, 1) - assert.Equal(t, &protocolTCP, clientRule.Ports[0].Protocol) - assert.Equal(t, intstr.FromInt32(DragonflyPort), *clientRule.Ports[0].Port) - - adminRule := np.Spec.Ingress[1] - require.Len(t, adminRule.Ports, 1) - assert.Equal(t, intstr.FromInt32(DragonflyAdminPort), *adminRule.Ports[0].Port) - require.Len(t, adminRule.From, 2) - - operatorPeer := adminRule.From[0] - assert.Equal(t, map[string]string{ - OperatorControlPlaneLabelKey: OperatorControlPlaneLabelValue, - }, operatorPeer.PodSelector.MatchLabels) - require.NotNil(t, operatorPeer.NamespaceSelector, "operator peer should allow cross-namespace") - assert.Equal(t, map[string]string{ - KubernetesNamespaceLabelKey: "dragonfly-system", - }, operatorPeer.NamespaceSelector.MatchLabels, "operator peer namespace should be pinned") - - peerPod := adminRule.From[1] - assert.Equal(t, map[string]string{ - DragonflyNameLabelKey: "test-df", - KubernetesPartOfLabelKey: KubernetesPartOf, - KubernetesAppNameLabelKey: KubernetesAppName, - }, peerPod.PodSelector.MatchLabels) - assert.Nil(t, peerPod.NamespaceSelector, "peer pod should be same-namespace only") -} - -func TestGenerateDragonflyResources_NetworkPolicyDisabled(t *testing.T) { - disabled := false - df := &resourcesv1.Dragonfly{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-df", - Namespace: "default", - }, - Spec: resourcesv1.DragonflySpec{ - Replicas: 1, - NetworkPolicyEnabled: &disabled, - }, - } - - objs, err := GenerateDragonflyResources(df, "", "dragonfly-system") - require.NoError(t, err) - - np := findNetworkPolicy(objs) - assert.Nil(t, np, "NetworkPolicy should not be generated when disabled") -} - func TestGenerateDragonflyResources_PodMetadataLabels(t *testing.T) { df := newTestDragonfly(1) df.Spec.PodMetadata = &resourcesv1.MetadataSpec{ @@ -229,7 +136,7 @@ func TestGenerateDragonflyResources_PodMetadataLabels(t *testing.T) { Annotations: map[string]string{"prometheus.io/scrape": "true"}, } - objs, err := GenerateDragonflyResources(df, "", "") + objs, err := GenerateDragonflyResources(df, "") require.NoError(t, err) sts := findStatefulSet(objs) @@ -247,7 +154,7 @@ func TestGenerateDragonflyResources_PodMetadataWinsOverDeprecated(t *testing.T) Annotations: map[string]string{"note": "new"}, } - objs, err := GenerateDragonflyResources(df, "", "") + objs, err := GenerateDragonflyResources(df, "") require.NoError(t, err) sts := findStatefulSet(objs) @@ -292,7 +199,7 @@ func TestGenerateDragonflyResources_RejectProtectedPodLabel(t *testing.T) { t.Run(field.name, func(t *testing.T) { df := newTestDragonfly(1) field.spec(&df.Spec) - _, err := GenerateDragonflyResources(df, "", "") + _, err := GenerateDragonflyResources(df, "") require.Error(t, err) assert.Contains(t, err.Error(), field.errMsg) }) @@ -306,7 +213,7 @@ func TestGenerateDragonflyResources_OwnedObjectsMetadataLabels(t *testing.T) { Annotations: map[string]string{"owner": "platform"}, } - objs, err := GenerateDragonflyResources(df, "", "") + objs, err := GenerateDragonflyResources(df, "") require.NoError(t, err) sts := findStatefulSet(objs) @@ -315,64 +222,6 @@ func TestGenerateDragonflyResources_OwnedObjectsMetadataLabels(t *testing.T) { assert.Equal(t, "platform", sts.Annotations["owner"]) } -func TestGenerateDragonflyResources_NetworkPolicyWithMemcached(t *testing.T) { - df := &resourcesv1.Dragonfly{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-df", - Namespace: "default", - }, - Spec: resourcesv1.DragonflySpec{ - Replicas: 1, - MemcachedPort: 11211, - }, - } - - objs, err := GenerateDragonflyResources(df, "", "dragonfly-system") - require.NoError(t, err) - - np := findNetworkPolicy(objs) - require.NotNil(t, np) - - require.Len(t, np.Spec.Ingress, 3, "should have client, admin, and memcached rules") - - protocolTCP := corev1.ProtocolTCP - memcachedRule := np.Spec.Ingress[2] - require.Len(t, memcachedRule.From, 1, "memcached port should be restricted to same namespace") - assert.Equal(t, &metav1.LabelSelector{}, memcachedRule.From[0].PodSelector) - assert.Nil(t, memcachedRule.From[0].NamespaceSelector, "memcached port should not allow cross-namespace") - require.Len(t, memcachedRule.Ports, 1) - assert.Equal(t, &protocolTCP, memcachedRule.Ports[0].Protocol) - assert.Equal(t, intstr.FromInt32(11211), *memcachedRule.Ports[0].Port) -} - -func TestGenerateDragonflyResources_NetworkPolicyEmptyOperatorNamespace(t *testing.T) { - df := &resourcesv1.Dragonfly{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-df", - Namespace: "default", - }, - Spec: resourcesv1.DragonflySpec{ - Replicas: 1, - }, - } - - objs, err := GenerateDragonflyResources(df, "", "") - require.NoError(t, err) - - np := findNetworkPolicy(objs) - require.NotNil(t, np) - - adminRule := np.Spec.Ingress[1] - require.Len(t, adminRule.From, 2) - - operatorPeer := adminRule.From[0] - assert.Equal(t, map[string]string{ - OperatorControlPlaneLabelKey: OperatorControlPlaneLabelValue, - }, operatorPeer.PodSelector.MatchLabels) - assert.Nil(t, operatorPeer.NamespaceSelector, - "when operator namespace is unknown, admin port should fall back to same-namespace only") -} - func findStatefulSet(objs []client.Object) *appsv1.StatefulSet { for _, obj := range objs { if sts, ok := obj.(*appsv1.StatefulSet); ok { @@ -393,7 +242,7 @@ func findConfigMap(objs []client.Object, name string) *corev1.ConfigMap { func TestProbeConfigMaps_NotGeneratedByDefault(t *testing.T) { df := newTestDragonfly(1) - objs, err := GenerateDragonflyResources(df, "", "") + objs, err := GenerateDragonflyResources(df, "") require.NoError(t, err) assert.Nil(t, findConfigMap(objs, "test-df-liveness-probe"), "no ConfigMaps without custom probes") @@ -404,7 +253,7 @@ func TestProbeConfigMaps_NotGeneratedByDefault(t *testing.T) { func TestProbeConfigMaps_GeneratedWhenCustomProbeSet(t *testing.T) { df := newTestDragonfly(1) df.Spec.CustomLivenessProbeConfigMap = &corev1.LocalObjectReference{Name: "my-liveness"} - objs, err := GenerateDragonflyResources(df, "", "") + objs, err := GenerateDragonflyResources(df, "") require.NoError(t, err) // custom liveness overrides the default, so no default ConfigMap generated @@ -425,7 +274,7 @@ func TestProbeConfigMaps_AllCustomNoneGenerated(t *testing.T) { df.Spec.CustomLivenessProbeConfigMap = &corev1.LocalObjectReference{Name: "my-liveness"} df.Spec.CustomReadinessProbeConfigMap = &corev1.LocalObjectReference{Name: "my-readiness"} df.Spec.CustomStartupProbeConfigMap = &corev1.LocalObjectReference{Name: "my-startup"} - objs, err := GenerateDragonflyResources(df, "", "") + objs, err := GenerateDragonflyResources(df, "") require.NoError(t, err) assert.Nil(t, findConfigMap(objs, "test-df-liveness-probe"), "no default when all custom") @@ -436,7 +285,7 @@ func TestProbeConfigMaps_AllCustomNoneGenerated(t *testing.T) { func TestProbeConfigMaps_EmptyNameTreatedAsNoCustom(t *testing.T) { df := newTestDragonfly(1) df.Spec.CustomLivenessProbeConfigMap = &corev1.LocalObjectReference{Name: ""} - objs, err := GenerateDragonflyResources(df, "", "") + objs, err := GenerateDragonflyResources(df, "") require.NoError(t, err) // empty name is treated as no custom probe, keeps default path @@ -452,7 +301,7 @@ func TestProbeConfigMaps_EmptyNameTreatedAsNoCustom(t *testing.T) { func TestHealthcheckPortEnvVar_IsAdminPort(t *testing.T) { // HEALTHCHECK_PORT always points to the admin port (never requires TLS). df := newTestDragonfly(1) - objs, err := GenerateDragonflyResources(df, "", "") + objs, err := GenerateDragonflyResources(df, "") require.NoError(t, err) sts := findStatefulSet(objs) @@ -474,7 +323,7 @@ func TestHealthcheckPortEnvVar_UnchangedByCustomRedisPort(t *testing.T) { // HEALTHCHECK_PORT stays at the admin port even when the Redis port is customised. df := newTestDragonfly(1) df.Spec.Args = []string{"--port=6380"} - objs, err := GenerateDragonflyResources(df, "", "") + objs, err := GenerateDragonflyResources(df, "") require.NoError(t, err) sts := findStatefulSet(objs) @@ -494,7 +343,7 @@ func TestHealthcheckPortEnvVar_UnchangedByCustomRedisPort(t *testing.T) { func TestProbeVolumesAndMounts_DefaultHasNoProbeVolumes(t *testing.T) { df := newTestDragonfly(1) - objs, err := GenerateDragonflyResources(df, "", "") + objs, err := GenerateDragonflyResources(df, "") require.NoError(t, err) sts := findStatefulSet(objs) @@ -510,7 +359,7 @@ func TestProbeVolumesAndMounts_DefaultHasNoProbeVolumes(t *testing.T) { func TestProbeVolumesAndMounts_PresentWhenCustomProbeSet(t *testing.T) { df := newTestDragonfly(1) df.Spec.CustomReadinessProbeConfigMap = &corev1.LocalObjectReference{Name: "my-readiness"} - objs, err := GenerateDragonflyResources(df, "", "") + objs, err := GenerateDragonflyResources(df, "") require.NoError(t, err) sts := findStatefulSet(objs) @@ -537,7 +386,7 @@ func TestProbeVolumesAndMounts_PresentWhenCustomProbeSet(t *testing.T) { func TestProbes_DefaultUseImageHealthcheck(t *testing.T) { df := newTestDragonfly(1) - objs, err := GenerateDragonflyResources(df, "", "") + objs, err := GenerateDragonflyResources(df, "") require.NoError(t, err) sts := findStatefulSet(objs) @@ -556,7 +405,7 @@ func TestProbes_DefaultUseImageHealthcheck(t *testing.T) { func TestProbes_PointToMountedScriptsWhenCustomSet(t *testing.T) { df := newTestDragonfly(1) df.Spec.CustomStartupProbeConfigMap = &corev1.LocalObjectReference{Name: "my-startup"} - objs, err := GenerateDragonflyResources(df, "", "") + objs, err := GenerateDragonflyResources(df, "") require.NoError(t, err) sts := findStatefulSet(objs) @@ -613,7 +462,7 @@ func TestProbeVolumes_CustomConfigMapOverride(t *testing.T) { df := newTestDragonfly(1) tc.setup(df) - objs, err := GenerateDragonflyResources(df, "", "") + objs, err := GenerateDragonflyResources(df, "") require.NoError(t, err) // volume should reference the custom ConfigMap diff --git a/manifests/crd.yaml b/manifests/crd.yaml index e1c39062..e5ed94a0 100644 --- a/manifests/crd.yaml +++ b/manifests/crd.yaml @@ -6092,13 +6092,6 @@ spec: description: (Optional) Dragonfly memcached port format: int32 type: integer - networkPolicyEnabled: - default: true - description: |- - (Optional) Whether to create a NetworkPolicy for this Dragonfly instance. - The NetworkPolicy restricts admin port access to operator and peer pods only. - Defaults to true. - type: boolean nodeSelector: additionalProperties: type: string diff --git a/manifests/dragonfly-operator.yaml b/manifests/dragonfly-operator.yaml index 7b9432be..e6c21061 100644 --- a/manifests/dragonfly-operator.yaml +++ b/manifests/dragonfly-operator.yaml @@ -6105,13 +6105,6 @@ spec: description: (Optional) Dragonfly memcached port format: int32 type: integer - networkPolicyEnabled: - default: true - description: |- - (Optional) Whether to create a NetworkPolicy for this Dragonfly instance. - The NetworkPolicy restricts admin port access to operator and peer pods only. - Defaults to true. - type: boolean nodeSelector: additionalProperties: type: string @@ -7303,18 +7296,6 @@ rules: - get - patch - update -- apiGroups: - - networking.k8s.io - resources: - - networkpolicies - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - apiGroups: - policy resources: @@ -7524,11 +7505,6 @@ spec: - --leader-elect command: - /manager - env: - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace image: docker.dragonflydb.io/dragonflydb/operator:v1.6.1 livenessProbe: httpGet: