Skip to content

Commit 101f1b4

Browse files
MLE-15992: Implementation for networkPolicy (#25)
* implementation for networkPolicy
1 parent e14201a commit 101f1b4

File tree

9 files changed

+1023
-928
lines changed

9 files changed

+1023
-928
lines changed

api/v1alpha1/common_types.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package v1alpha1
22

33
import (
44
corev1 "k8s.io/api/core/v1"
5+
networkingv1 "k8s.io/api/networking/v1"
6+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
57
)
68

79
type ContainerProbe struct {
@@ -64,6 +66,13 @@ type LogFilesConfig struct {
6466
AuditLogs bool `json:"auditLogs,omitempty"`
6567
}
6668

69+
type NetworkPolicy struct {
70+
Enabled bool `json:"enabled,omitempty"`
71+
PolicyTypes []networkingv1.PolicyType `json:"policyTypes,omitempty"`
72+
PodSelector metav1.LabelSelector `json:"podSelector,omitempty"`
73+
Ingress []networkingv1.NetworkPolicyIngressRule `json:"ingress,omitempty"`
74+
Egress []networkingv1.NetworkPolicyEgressRule `json:"egress,omitempty"`
75+
6776
type HAProxyConfig struct {
6877
Enabled bool `json:"enabled,omitempty"`
6978
// +kubebuilder:default:=1

api/v1alpha1/marklogicgroup_types.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ package v1alpha1
1919
import (
2020
appsv1 "k8s.io/api/apps/v1"
2121
corev1 "k8s.io/api/core/v1"
22-
networkingv1 "k8s.io/api/networking/v1"
2322
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2423
)
2524

@@ -48,7 +47,7 @@ type MarklogicGroupSpec struct {
4847
// +kubebuilder:validation:Enum=OnDelete;RollingUpdate
4948
// +kubebuilder:default:="OnDelete"
5049
UpdateStrategy appsv1.StatefulSetUpdateStrategyType `json:"updateStrategy,omitempty"`
51-
NetworkPolicy *networkingv1.NetworkPolicy `json:"networkPolicy,omitempty"`
50+
NetworkPolicy NetworkPolicy `json:"networkPolicy,omitempty"`
5251
// +kubebuilder:default:={fsGroup: 2, fsGroupChangePolicy: "OnRootMismatch"}
5352
PodSecurityContext *corev1.PodSecurityContext `json:"podSecurityContext,omitempty"`
5453
// +kubebuilder:default:={runAsUser: 1000, runAsNonRoot: true, allowPrivilegeEscalation: false}

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 36 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/database.marklogic.com_marklogicclusters.yaml

Lines changed: 402 additions & 463 deletions
Large diffs are not rendered by default.

config/crd/bases/database.marklogic.com_marklogicgroups.yaml

Lines changed: 398 additions & 458 deletions
Large diffs are not rendered by default.

config/samples/marklogicgroup.yaml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,34 @@ spec:
6262
http_user admin
6363
http_passwd admin
6464
65+
## To configure networkPolicy, set enabled: true and uncomment the following lines
66+
## Below is an example of networkPolicy, update it as per your requirements
67+
## ref: https://kubernetes.io/docs/concepts/services-networking/network-policies
68+
networkPolicy:
69+
enabled: false
70+
# policyTypes:
71+
# - Ingress
72+
# - Egress
73+
# podSelector: {}
74+
# ingress:
75+
# - from:
76+
# - podSelector:
77+
# matchLabels:
78+
# app.kubernetes.io/name: marklogic
79+
# app.kubernetes.io/instance: marklogic
80+
# ports:
81+
# - protocol: TCP
82+
# port: 8000
83+
# egress:
84+
# - to:
85+
# - podSelector:
86+
# matchLabels:
87+
# app.kubernetes.io/name: marklogic
88+
# app.kubernetes.io/instance: marklogicgroup
89+
# ports:
90+
# - protocol: TCP
91+
# port: 8000
92+
6593
## Configuration for the HAProxy load balancer
6694
## An out of box load balancer with configured to handle cookie based session affinity that required by most MarkLogic applications.
6795
## It also support multi-statement transaction and ODBC connections.

internal/controller/marklogicgroup_controller_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
. "github.com/onsi/gomega"
2626
appsv1 "k8s.io/api/apps/v1"
2727
corev1 "k8s.io/api/core/v1"
28+
networkingv1 "k8s.io/api/networking/v1"
2829
"k8s.io/apimachinery/pkg/api/resource"
2930
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3031
"k8s.io/apimachinery/pkg/types"
@@ -50,6 +51,7 @@ var runAsUser = int64(1000)
5051
var runAsNonRoot bool = true
5152
var allowPrivilegeEscalation bool = false
5253
var typeNamespaceName = types.NamespacedName{Name: Name, Namespace: Namespace}
54+
var policy = []networkingv1.PolicyType{networkingv1.PolicyTypeIngress, networkingv1.PolicyTypeEgress}
5355

5456
const resourceCpuValue = int64(1)
5557
const resourceMemoryValue = int64(268435456)
@@ -59,6 +61,8 @@ const resourceHugepageValue = int64(104857600)
5961

6062
var svcName = Name + "-cluster"
6163
var typeNamespaceNameSvc = types.NamespacedName{Name: svcName, Namespace: Namespace}
64+
var netPolicyName = Name + "-network-policy"
65+
var typeNsNameNetPolicy = types.NamespacedName{Name: netPolicyName, Namespace: Namespace}
6266

6367
const fluentBitImage = "fluent/fluent-bit:3.1.1"
6468

@@ -115,6 +119,23 @@ var _ = Describe("MarkLogicGroup controller", func() {
115119
AllowPrivilegeEscalation: &allowPrivilegeEscalation,
116120
},
117121
LogCollection: &databasev1alpha1.LogCollection{Enabled: true, Image: "fluent/fluent-bit:3.1.1", Files: databasev1alpha1.LogFilesConfig{ErrorLogs: true, AccessLogs: true, RequestLogs: true, CrashLogs: true, AuditLogs: true}, Outputs: "stdout"},
122+
NetworkPolicy: databasev1alpha1.NetworkPolicy{
123+
Enabled: true,
124+
PolicyTypes: policy,
125+
PodSelector: metav1.LabelSelector{MatchLabels: map[string]string{"app.kubernetes.io/name": "marklogic", "app.kubernetes.io/instance": "dnode"}},
126+
Ingress: []networkingv1.NetworkPolicyIngressRule{
127+
{From: []networkingv1.NetworkPolicyPeer{{
128+
PodSelector: &metav1.LabelSelector{
129+
MatchLabels: map[string]string{
130+
"app.kubernetes.io/name": "marklogic",
131+
"app.kubernetes.io/instance": "dnode",
132+
},
133+
},
134+
}},
135+
Ports: []networkingv1.NetworkPolicyPort{{Port: &intstr.IntOrString{IntVal: 8000}}},
136+
},
137+
},
138+
},
118139
HAProxyConfig: databasev1alpha1.HAProxyConfig{
119140
Enabled: true,
120141
ReplicaCount: 1,
@@ -201,6 +222,18 @@ var _ = Describe("MarkLogicGroup controller", func() {
201222
}, timeout, interval).Should(BeTrue())
202223
Expect(createdClusterSrv.Name).Should(Equal(svcName))
203224
Expect(createdClusterSrv.Spec.Type).Should(Equal(corev1.ServiceTypeClusterIP))
225+
226+
// Validating if NetworkPolicy is created successfully
227+
createdNetPolicy := &networkingv1.NetworkPolicy{}
228+
Eventually(func() bool {
229+
err := k8sClient.Get(ctx, typeNsNameNetPolicy, createdNetPolicy)
230+
return err == nil
231+
}, timeout, interval).Should(BeTrue())
232+
Expect(createdNetPolicy.Name).Should(Equal(netPolicyName))
233+
Expect(createdNetPolicy.Spec.PolicyTypes).Should(Equal(policy))
234+
Expect(createdNetPolicy.Spec.PodSelector).Should(Equal(metav1.LabelSelector{MatchLabels: map[string]string{"app.kubernetes.io/name": "marklogic", "app.kubernetes.io/instance": "dnode"}}))
235+
Expect(createdNetPolicy.Spec.Ingress[0].From[0].PodSelector.MatchLabels).Should(Equal(map[string]string{"app.kubernetes.io/name": "marklogic", "app.kubernetes.io/instance": "dnode"}))
236+
Expect(createdNetPolicy.Spec.Ingress[0].Ports[0].Port).Should(Equal(&intstr.IntOrString{IntVal: 8000}))
204237
})
205238

206239
It("Should create configmap for MarkLogic scripts", func() {

pkg/k8sutil/handler.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ func (oc *OperatorContext) ReconsileHandler() (reconcile.Result, error) {
2626
}
2727
}
2828

29+
if oc.MarklogicGroup.Spec.NetworkPolicy.Enabled {
30+
if result := oc.ReconcileNetworkPolicy(); result.Completed() {
31+
2932
if oc.MarklogicGroup.Spec.HAProxyConfig.Enabled {
3033
if result := oc.ReconcileHAProxy(); result.Completed() {
3134
return result.Output()

pkg/k8sutil/networkPolicy.go

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
package k8sutil
2+
3+
import (
4+
networkingv1 "k8s.io/api/networking/v1"
5+
"k8s.io/apimachinery/pkg/api/errors"
6+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
7+
"k8s.io/apimachinery/pkg/types"
8+
9+
"github.com/cisco-open/k8s-objectmatcher/patch"
10+
databasev1alpha1 "github.com/marklogic/marklogic-kubernetes-operator/api/v1alpha1"
11+
"github.com/marklogic/marklogic-kubernetes-operator/pkg/result"
12+
)
13+
14+
func generateNetworkPolicyDef(networkPolicyMeta metav1.ObjectMeta, ownerRef metav1.OwnerReference, cr *databasev1alpha1.MarklogicGroup) *networkingv1.NetworkPolicy {
15+
networkPolicySpec := networkingv1.NetworkPolicySpec{
16+
PolicyTypes: cr.Spec.NetworkPolicy.PolicyTypes,
17+
PodSelector: cr.Spec.NetworkPolicy.PodSelector,
18+
Ingress: cr.Spec.NetworkPolicy.Ingress,
19+
Egress: cr.Spec.NetworkPolicy.Egress,
20+
}
21+
networkPolicyDef := &networkingv1.NetworkPolicy{
22+
TypeMeta: metav1.TypeMeta{
23+
Kind: "NetworkPolicy",
24+
APIVersion: "v1",
25+
},
26+
ObjectMeta: networkPolicyMeta,
27+
Spec: networkPolicySpec,
28+
}
29+
networkPolicyDef.SetOwnerReferences(append(networkPolicyDef.GetOwnerReferences(), ownerRef))
30+
return networkPolicyDef
31+
}
32+
33+
func (oc *OperatorContext) getNetworkPolicy(namespace string, networkPolicyName string) (*networkingv1.NetworkPolicy, error) {
34+
logger := oc.ReqLogger
35+
36+
var networkPolicy *networkingv1.NetworkPolicy
37+
networkPolicy = &networkingv1.NetworkPolicy{}
38+
err := oc.Client.Get(oc.Ctx, types.NamespacedName{Name: networkPolicyName, Namespace: namespace}, networkPolicy)
39+
if err != nil {
40+
logger.Info("MarkLogic NetworkPolicy get action failed")
41+
return nil, err
42+
}
43+
logger.Info("MarkLogic NetworkPolicy get action is successful")
44+
return networkPolicy, nil
45+
}
46+
47+
func generateNetworkPolicy(networkPolicyName string, cr *databasev1alpha1.MarklogicGroup) *networkingv1.NetworkPolicy {
48+
labels := getMarkLogicLabels(cr.Spec.Name)
49+
netObjectMeta := generateObjectMeta(networkPolicyName, cr.Namespace, labels, map[string]string{})
50+
networkPolicy := generateNetworkPolicyDef(netObjectMeta, marklogicServerAsOwner(cr), cr)
51+
return networkPolicy
52+
}
53+
54+
func (oc *OperatorContext) ReconcileNetworkPolicy() result.ReconcileResult {
55+
logger := oc.ReqLogger
56+
logger.Info("NetworkPolicy::Reconciling MarkLogic NetworkPolicy")
57+
client := oc.Client
58+
cr := oc.MarklogicGroup
59+
networkPolicyName := cr.Spec.Name
60+
currentNetworkPolicy, err := oc.getNetworkPolicy(cr.Namespace, networkPolicyName)
61+
networkPolicyDef := generateNetworkPolicy(networkPolicyName, cr)
62+
if err != nil {
63+
if errors.IsNotFound(err) {
64+
logger.Info("MarkLogic NetworkPolicy not found, creating a new one")
65+
err = client.Create(oc.Ctx, networkPolicyDef)
66+
if err != nil {
67+
logger.Info("MarkLogic NetworkPolicy creation has failed")
68+
return result.Error(err)
69+
}
70+
logger.Info("MarkLogic NetworkPolicy creation is successful")
71+
oc.Recorder.Event(oc.MarklogicGroup, "Normal", "NetworkPolicyCreated", "MarkLogic NetworkPolicy creation is successful")
72+
} else {
73+
logger.Error(err, "MarkLogic NetworkPolicy creation has failed")
74+
return result.Error(err)
75+
}
76+
} else {
77+
logger.Info("MarkLogic NetworkPolicy already exists")
78+
patchDiff, err := patch.DefaultPatchMaker.Calculate(currentNetworkPolicy, networkPolicyDef,
79+
patch.IgnoreStatusFields(),
80+
patch.IgnoreVolumeClaimTemplateTypeMetaAndStatus(),
81+
patch.IgnoreField("kind"))
82+
if err != nil {
83+
logger.Error(err, "Error calculating patch")
84+
return result.Error(err)
85+
}
86+
if !patchDiff.IsEmpty() {
87+
logger.Info("MarkLogic NetworkPolicy spec is different from the input NetworkPolicy spec, updating the NetworkPolicy")
88+
logger.Info(patchDiff.String())
89+
err := oc.Client.Update(oc.Ctx, networkPolicyDef)
90+
if err != nil {
91+
logger.Error(err, "Error updating NetworkPolicy")
92+
return result.Error(err)
93+
}
94+
} else {
95+
logger.Info("MarkLogic NetworkPolicy spec is the same as the input NetworkPolicy spec")
96+
97+
}
98+
logger.Info("MarkLogic NetworkPolicy is updated")
99+
}
100+
return result.Continue()
101+
}
102+
103+
func (oc *OperatorContext) createNetworkPolicy(namespace string, networkPolicy *networkingv1.NetworkPolicy) error {
104+
logger := oc.ReqLogger
105+
client := oc.Client
106+
err := client.Create(oc.Ctx, networkPolicy)
107+
if err != nil {
108+
logger.Error(err, "MarkLogic NetworkPolicy creation has failed")
109+
return err
110+
}
111+
logger.Info("MarkLogic NetworkPolicy creation is successful")
112+
return nil
113+
}

0 commit comments

Comments
 (0)