-
Notifications
You must be signed in to change notification settings - Fork 241
/
parsePolicy.go
148 lines (124 loc) · 4.74 KB
/
parsePolicy.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// Copyright 2018 Microsoft. All rights reserved.
// MIT License
package controllers
import (
"fmt"
"reflect"
networkingv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// compare all fields including name of two network policies, which network policy controller need to care about.
func isSameNetworkPolicy(old, new *networkingv1.NetworkPolicy) bool {
if old.ObjectMeta.Name != new.ObjectMeta.Name {
return false
}
return isSamePolicy(old, new)
}
// (TODO): isSamePolicy function does not compare name of two network policies since trying to reduce the number of rules if below three conditions are the same.
// Will optimize networkPolicyController code with addPolicy and deductPolicy functions if possible. Refer to https://github.com/Azure/azure-container-networking/pull/390
func isSamePolicy(old, new *networkingv1.NetworkPolicy) bool {
if !reflect.DeepEqual(old.TypeMeta, new.TypeMeta) {
return false
}
if old.ObjectMeta.Namespace != new.ObjectMeta.Namespace {
return false
}
if !reflect.DeepEqual(old.Spec, new.Spec) {
return false
}
return true
}
// addPolicy merges policies based on labels.
// if namespace matches && podSelector matches, then merge two network policies. Otherwise, return as is.
func addPolicy(old, new *networkingv1.NetworkPolicy) (*networkingv1.NetworkPolicy, error) {
if !reflect.DeepEqual(old.TypeMeta, new.TypeMeta) {
return nil, fmt.Errorf("Old and new networkpolicies don't have the same TypeMeta")
}
if old.ObjectMeta.Namespace != new.ObjectMeta.Namespace {
return nil, fmt.Errorf("Old and new networkpolicies don't have the same namespace")
}
if !reflect.DeepEqual(old.Spec.PodSelector, new.Spec.PodSelector) {
return nil, fmt.Errorf("Old and new networkpolicies don't apply to the same set of target pods")
}
addedPolicy := &networkingv1.NetworkPolicy{
TypeMeta: old.TypeMeta,
ObjectMeta: metav1.ObjectMeta{
Name: old.ObjectMeta.Name,
Namespace: old.ObjectMeta.Namespace,
},
Spec: networkingv1.NetworkPolicySpec{
PodSelector: old.Spec.PodSelector,
},
}
spec := &(addedPolicy.Spec)
if len(old.Spec.PolicyTypes) == 1 && len(new.Spec.PolicyTypes) == 1 && old.Spec.PolicyTypes[0] == new.Spec.PolicyTypes[0] {
spec.PolicyTypes = []networkingv1.PolicyType{new.Spec.PolicyTypes[0]}
} else {
spec.PolicyTypes = []networkingv1.PolicyType{
networkingv1.PolicyTypeIngress,
networkingv1.PolicyTypeEgress,
}
}
// (TODO): It seems ingress and egress may have duplicated fields, but in translatePolicy, it seems duplicated fields are removed.
ingress := append(old.Spec.Ingress, new.Spec.Ingress...)
egress := append(old.Spec.Egress, new.Spec.Egress...)
addedPolicy.Spec.Ingress = ingress
addedPolicy.Spec.Egress = egress
return addedPolicy, nil
}
// deductPolicy deduct one policy from the other.
func deductPolicy(old, new *networkingv1.NetworkPolicy) (*networkingv1.NetworkPolicy, error) {
// if namespace matches && podSelector matches, then merge
// else return as is.
if !reflect.DeepEqual(old.TypeMeta, new.TypeMeta) {
return nil, fmt.Errorf("Old and new networkpolicy don't have the same TypeMeta")
}
if old.ObjectMeta.Namespace != new.ObjectMeta.Namespace {
return nil, fmt.Errorf("Old and new networkpolicy don't have the same namespace")
}
if !reflect.DeepEqual(old.Spec.PodSelector, new.Spec.PodSelector) {
return nil, fmt.Errorf("Old and new networkpolicy don't have apply to the same set of target pods")
}
if reflect.DeepEqual(old.Spec, new.Spec) {
return nil, nil
}
deductedPolicy := &networkingv1.NetworkPolicy{
TypeMeta: old.TypeMeta,
ObjectMeta: metav1.ObjectMeta{
Name: old.ObjectMeta.Name,
Namespace: old.ObjectMeta.Namespace,
},
Spec: networkingv1.NetworkPolicySpec{
PodSelector: old.Spec.PodSelector,
},
}
deductedIngress, newIngress := old.Spec.Ingress, new.Spec.Ingress
deductedEgress, newEgress := old.Spec.Egress, new.Spec.Egress
for _, ni := range newIngress {
for i, di := range deductedIngress {
if reflect.DeepEqual(di, ni) {
deductedIngress = append(deductedIngress[:i], deductedIngress[i+1:]...)
break
}
}
}
for _, ne := range newEgress {
for i, de := range deductedEgress {
if reflect.DeepEqual(de, ne) {
deductedEgress = append(deductedEgress[:i], deductedEgress[i+1:]...)
break
}
}
}
deductedPolicy.Spec.Ingress = deductedIngress
deductedPolicy.Spec.Egress = deductedEgress
if len(old.Spec.PolicyTypes) == 1 && len(new.Spec.PolicyTypes) == 1 && old.Spec.PolicyTypes[0] == new.Spec.PolicyTypes[0] {
deductedPolicy.Spec.PolicyTypes = []networkingv1.PolicyType{new.Spec.PolicyTypes[0]}
} else {
deductedPolicy.Spec.PolicyTypes = []networkingv1.PolicyType{
networkingv1.PolicyTypeIngress,
networkingv1.PolicyTypeEgress,
}
}
return deductedPolicy, nil
}