@@ -2,6 +2,7 @@ package translation
22
33import (
44 "github.com/Azure/azure-container-networking/log"
5+ "github.com/Azure/azure-container-networking/npm/pkg/dataplane/ipsets"
56 "github.com/Azure/azure-container-networking/npm/util"
67 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
78)
@@ -45,7 +46,6 @@ func GetOperatorsAndLabels(labelsWithOps []string) (ops, labelsWithoutOps []stri
4546 ops [i ] = op
4647 labelsWithoutOps [i ] = labelWithoutOp
4748 }
48-
4949 return ops , labelsWithoutOps
5050}
5151
@@ -59,7 +59,7 @@ func getSetNameForMultiValueSelector(key string, vals []string) string {
5959 return newIPSet
6060}
6161
62- // FlattenNameSpaceSelector will help flatten multiple NameSpace selector match Expressions values
62+ // FlattenNameSpaceSelector will help flatten multiple nameSpace selector match Expressions values
6363// into multiple label selectors helping with the OR condition.
6464func FlattenNameSpaceSelector (nsSelector * metav1.LabelSelector ) []metav1.LabelSelector {
6565 /*
@@ -238,3 +238,148 @@ func parseSelector(selector *metav1.LabelSelector) (labels []string, vals map[st
238238
239239 return labels , vals
240240}
241+
242+ // labelSelector has parsed matchLabels and MatchExpressions information.
243+ type labelSelector struct {
244+ // include is a flag to indicate whether Op exists or not.
245+ include bool
246+ setType ipsets.SetType
247+ // setName is among
248+ // 1. matchKey + ":" + matchVal (can be empty string) case
249+ // 2. "matchKey" case
250+ // or 3. "matchKey + : + multiple matchVals" case.
251+ setName string
252+ // members slice exists only if setType is only NestedLabelOfPod.
253+ members []string
254+ }
255+
256+ // parsedSelectors maintains slice of unique labelSelector.
257+ type parsedSelectors struct {
258+ labelSelectors []labelSelector
259+ // Use set data structure to avoid the duplicate setName among matchLabels and MatchExpression.
260+ // The key of labelSet includes "!" if operator is "OpNotIn" or "OpDoesNotExist"
261+ // to make difference when it has the same key (and value), but different operator
262+ // while this is weird since it is not always matched, but K8s accepts this spec.
263+ labelSet map [string ]struct {}
264+ }
265+
266+ func newParsedSelectors () parsedSelectors {
267+ return parsedSelectors {
268+ labelSelectors : []labelSelector {},
269+ labelSet : map [string ]struct {}{},
270+ }
271+ }
272+
273+ // addSelector only adds non-duplicated labelSelector.
274+ // Only nested labels from podSelector has members fields.
275+ func (ps * parsedSelectors ) addSelector (include bool , setType ipsets.SetType , setName string , members ... string ) {
276+ setNameWithOp := setName
277+ if ! include {
278+ setNameWithOp = "!" + setName
279+ }
280+
281+ // in case setNameWithOp exists in a set, do not need to add it.
282+ if _ , exist := ps .labelSet [setNameWithOp ]; exist {
283+ return
284+ }
285+
286+ ls := labelSelector {
287+ include : include ,
288+ setType : setType ,
289+ setName : setName ,
290+ members : members ,
291+ }
292+
293+ ps .labelSelectors = append (ps .labelSelectors , ls )
294+ ps .labelSet [setNameWithOp ] = struct {}{}
295+ }
296+
297+ // parseNSSelector parses namespaceSelector and returns slice of labelSelector object
298+ // which includes operator, setType, ipset name and always nil members slice.
299+ // Member slices is always nil since parseNSSelector function is called
300+ // after FlattenNameSpaceSelector function is called, which guarantees
301+ // there is no matchExpression with multiple values.
302+ // TODO: good to remove this dependency later if possible.
303+ func parseNSSelector (selector * metav1.LabelSelector ) []labelSelector {
304+ parsedSelectors := newParsedSelectors ()
305+
306+ // #1. All namespaces case
307+ if len (selector .MatchLabels ) == 0 && len (selector .MatchExpressions ) == 0 {
308+ parsedSelectors .addSelector (true , ipsets .KeyLabelOfNamespace , util .KubeAllNamespacesFlag )
309+ return parsedSelectors .labelSelectors
310+ }
311+
312+ // #2. MatchLabels
313+ for matchKey , matchVal := range selector .MatchLabels {
314+ // matchKey + ":" + matchVal (can be empty string) case
315+ setName := util .GetIpSetFromLabelKV (matchKey , matchVal )
316+ parsedSelectors .addSelector (true , ipsets .KeyValueLabelOfNamespace , setName )
317+ }
318+
319+ // #3. MatchExpressions
320+ for _ , req := range selector .MatchExpressions {
321+ var setName string
322+ var setType ipsets.SetType
323+ switch op := req .Operator ; op {
324+ case metav1 .LabelSelectorOpIn , metav1 .LabelSelectorOpNotIn :
325+ // "(!) + matchKey + : + matchVal" case
326+ setName = util .GetIpSetFromLabelKV (req .Key , req .Values [0 ])
327+ setType = ipsets .KeyValueLabelOfNamespace
328+ case metav1 .LabelSelectorOpExists , metav1 .LabelSelectorOpDoesNotExist :
329+ // "(!) + matchKey" case
330+ setName = req .Key
331+ setType = ipsets .KeyLabelOfNamespace
332+ }
333+
334+ noNegativeOp := (req .Operator == metav1 .LabelSelectorOpIn ) || (req .Operator == metav1 .LabelSelectorOpExists )
335+ parsedSelectors .addSelector (noNegativeOp , setType , setName )
336+ }
337+
338+ return parsedSelectors .labelSelectors
339+ }
340+
341+ // parsePodSelector parses podSelector and returns slice of labelSelector object
342+ // which includes operator, setType, ipset name and its members slice.
343+ // Members slice exists only if setType is only NestedLabelOfPod.
344+ func parsePodSelector (selector * metav1.LabelSelector ) []labelSelector {
345+ parsedSelectors := newParsedSelectors ()
346+
347+ // #1. MatchLabels
348+ for matchKey , matchVal := range selector .MatchLabels {
349+ // matchKey + ":" + matchVal (can be empty string) case
350+ setName := util .GetIpSetFromLabelKV (matchKey , matchVal )
351+ parsedSelectors .addSelector (true , ipsets .KeyValueLabelOfPod , setName )
352+ }
353+
354+ // #2. MatchExpressions
355+ for _ , req := range selector .MatchExpressions {
356+ var setName string
357+ var setType ipsets.SetType
358+ var members []string
359+ switch op := req .Operator ; op {
360+ case metav1 .LabelSelectorOpIn , metav1 .LabelSelectorOpNotIn :
361+ // "(!) + matchKey + : + matchVal" case
362+ if len (req .Values ) == 1 {
363+ setName = util .GetIpSetFromLabelKV (req .Key , req .Values [0 ])
364+ setType = ipsets .KeyValueLabelOfPod
365+ } else {
366+ // "(!) + matchKey + : + multiple matchVals" case
367+ setName = req .Key
368+ for _ , val := range req .Values {
369+ setName = util .GetIpSetFromLabelKV (setName , val )
370+ members = append (members , util .GetIpSetFromLabelKV (req .Key , val ))
371+ }
372+ setType = ipsets .NestedLabelOfPod
373+ }
374+ case metav1 .LabelSelectorOpExists , metav1 .LabelSelectorOpDoesNotExist :
375+ // "(!) + matchKey" case
376+ setName = req .Key
377+ setType = ipsets .KeyLabelOfPod
378+ }
379+
380+ noNegativeOp := (req .Operator == metav1 .LabelSelectorOpIn ) || (req .Operator == metav1 .LabelSelectorOpExists )
381+ parsedSelectors .addSelector (noNegativeOp , setType , setName , members ... )
382+ }
383+
384+ return parsedSelectors .labelSelectors
385+ }
0 commit comments