-
Notifications
You must be signed in to change notification settings - Fork 260
[NPM] [BUG] Supporting multiple values under label selector MatchExpr #863
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…ontainer-networking into vakr/k8smultiparse
|
/azp run |
|
Azure Pipelines successfully started running 2 pipeline(s). |
| return []metav1.LabelSelector{*nsSelector} | ||
| } | ||
|
|
||
| // Now use the baseSelector and loop over multiValueMatchExprs to create all |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Highly suggest moving codes from 185-192 to "zipMatchExprs". It will improve readability. Now, I need to track for loop in 190 with zipMatchExprs function which uses returned values as input again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or moving codes from "zipMatchExprs" to here. The function name of "zipMatchExprs" is not very intuitive at least to me. I think "FlattenNameSpaceSelector" function has a good name and combining all codes in the function is good to understand and not deep.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I modelled it as a recursive function, where we take in a slice and expand it using each expr.
| for i, _ := range nsLabelsWithoutOps { | ||
| // Add namespaces prefix to distinguish namespace ipset lists and pod ipsets | ||
| nsLabelsWithoutOps[i] = "ns-" + nsLabelsWithoutOps[i] | ||
| for _, nsSelector := range FlattenNameSpaceSelector(fromRule.NamespaceSelector) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer to splitting this one line to two lines to understand what it returns. Same to all in this file, but not strong opinion.
| // for _, egressRule := range nsSelector { | ||
| // log.Logf("%+v", egressRule) | ||
| // } | ||
| /* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure we need these long comments. I think it was well explained in comments (140-142) and is better to add concise explanation in the comments (140-142) based on summary of these long comments.
For example, matchExpressions "ns in (netpol-x, netpol-y)" is converted to multiple matchExpressions [
"ns in (netpol-x)", "ns in (netpol-y)"], then translate policy will replicate each of these nsSelectors to add two different rules in iptables, resulting in OR condition between the values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comes back to what we discussed in our meeting today, having a visual representation of what the YAML looks like and what the transformation looks like will help other developers to quickly understand. I would like to keep this as is if its ok.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be clear, I suggested putting comprehensive information (e.g., pods yaml and netpol yaml which shows the problem in our NPM) to reproduce the problem, which helps to understand big picture at the first. T
his code is very straightforward. So, I don't think we need this, but if you want to keep it, I don't have strong opinion.
| t.Errorf("TestFlattenNameSpaceSelector failed @ 2nd selector length check %+v", testSelectors) | ||
| } | ||
|
|
||
| expectedSelectors := []metav1.LabelSelector{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can make these tests concise and simple for all unit tests in this function and improve readability as well.
There are many things are repeated (e.g., LabelSelectorRequirement and MatchLabels).
We can make it better. One example is below.
matchLabels := map[string]string{
"c": "d",
"a": "b",
}
then use matchLabels whenever creating &metav1.LabelSelector.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added a common matchLabel to help with readability
| t.Errorf("TestFlattenNameSpaceSelector failed @ 1st selector length check %+v", testSelectors) | ||
| } | ||
|
|
||
| if !reflect.DeepEqual(testSelectors[0], *firstSelector) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are multiple time to check length of returned values from FlattenNameSpaceSelector and deepEqual in this function and TestFlattenNameSpaceSelectorWoMatchLabels function. So, I think it is better to make one helper function to check them together.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. but they are only a couple and i feel the code is self explanatory in itself,
| } | ||
|
|
||
| func TestFlattenNameSpaceSelectorWoMatchLabels(t *testing.T) { | ||
| firstSelector := &metav1.LabelSelector{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here. You can make it concise and better readability by using variables to avoid unnecessary repeat.
| if err = ipsMgr.CreateList(listKey); err != nil { | ||
| return fmt.Errorf("[syncAddAndUpdateNetPol] Error: creating ipset list %s with err: %v", listKey, err) | ||
| } | ||
| ipsMgr.IpSetReferIncOrDec(listKey, util.IpsetSetListFlag, ipsm.IncrementOp) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case, I prefer to having another function which functions "CreateList and IPSetReferIncOrDec". It will be easy to remember and help to encapsulate details.
I assume that your next PR is about those reference counts, we can revisit this in the PR.
| return nil | ||
| } | ||
|
|
||
| // Clean removes all the empty sets & lists under the namespace. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When do we use this function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clean() function is not being currently, this is for future work items.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would suggest not to add function which is not used in this PR. I think this is a good practice.
There are multiple reasons.
- Reviewer do not need to spend time.
- Add the function with the PR for your future work items. So, it will be well aligned and easy to understand PR.
- There are possibility that this function will not be used in the future. At that time, this function just stays for long time.
I think you have future work item to use this function. So, add this function in the PR.
|
|
||
| // IpSetReferIncOrDec checks if an element exists in setMap/listMap and then increases or decreases tis refer count. | ||
| // IpSetReferIncOrDec checks if an element exists in setMap/listMap and then increases or decreases this referCount. | ||
| func (ipsMgr *IpsetManager) IpSetReferIncOrDec(ipsetName string, kind string, countOperation ReferCountOperation) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you have plan to extend this function for other types in addition to "list" as well?
In this PR, kind is always "list".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes in the next work item(refer coutn) we will extend support of this IncDec to SetMap where we will track the use of iptable rules and their references to a given ipset. we will track both kinds of ipsets.
JungukCho
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for applying comments. Look forward to your next PR.
|
Merging, we got a green in Cyclonus. https://github.com/Azure/azure-container-networking/pull/863/checks?check_run_id=3004138884 |
This PR is fix the bug of supporting multiple values in a LabelSelector match expressions.
Today NPM considers the values of the above selector to be b AND c, but it should be b OR c
NPM now follows different design for podSelector and nameSpaceSelector.
For PodSelector, NPM has ipsets with immutable members like ips or ip,proto:port. Ipset allows creating 2nd level ipset ype list:set to be created with pod label ipsets as members and NPM will use this 2nd level ipset as the matchset criteria in rules.
For NameSpaceSelector, NPM uses ipsets with mutable members like other ipsets. Ipset does not allow adding list:set as members to list:set ipset, so 2nd level ipset cannot be used in case of nameSelectors. For this reason NPM will create combinations of nameSpaceSelectors and add individual rule for each combination.