Skip to content
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

Add global() selector #1229

Merged
merged 7 commits into from
Jun 11, 2020
Merged

Add global() selector #1229

merged 7 commits into from
Jun 11, 2020

Conversation

lmm
Copy link
Contributor

@lmm lmm commented Apr 27, 2020

Description

This PR adds support for the global() keyword

Todos

  • Tests
  • Documentation
  • Release note

Release Note

Network policy now has the global() namespace selector which selects host endpoints or global network sets

1) Implement a Token Global for handling `global'
Add support for rules and selector for global keyword and add unit test
case
Copy link
Member

@caseydavenport caseydavenport left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need some validation that global() isn't specified in regular selectors, since IIUC it won't function properly in that case, right?

e.g.,

spec.Selector will never select non-namespaced things, so it should be imposible to put global() in that field.

@caseydavenport caseydavenport added this to the Calico v3.15.0 milestone Apr 27, 2020
@@ -137,6 +137,9 @@ type EntityRule struct {
// For NetworkPolicy, an empty NamespaceSelector implies that the Selector is limited to selecting
// only workload endpoints in the same namespace as the NetworkPolicy.
//
// For NetworkPolicy, `global` NamespaceSelector implies that the Selector is limited to selecting
Copy link
Member

@caseydavenport caseydavenport May 13, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

global -> "global()"

Copy link
Member

@caseydavenport caseydavenport left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, but we need validation to make sure that this selector is not used except in the NamespaceSelector field for NetworkPolicy, and/or main selector in GNPs, since IIUC it's not valid for use in the other selector fields.

@bcreane
Copy link
Contributor

bcreane commented May 16, 2020

@lmm please check with @krishgobinath about adding validation - he's planning to add this in the next week or so.

@nelljerram
Copy link
Member

@lmm Is there already a doc PR for this? I'd quite like to review that too, preferably before or at the same time as this one. (Or a design doc?)

Specifically, as well as what @caseydavenport says, I'm wondering if global() must be the entire content of any selector field where it is used, or if it is allowed (and makes sense) to combine with other expressions, e.g. global() && color == 'red'.

Copy link
Member

@nelljerram nelljerram left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Am I right that this is mostly copied from our Enterprise code? Please can you list or identify the changes that are additional to that? (Because I think there's less value in reviewing Enterprise-copied code.)

If there isn't already a design or doc that says this, please can you also summarise, for me, where global() is allowed, and why?

lib/apis/v3/policy.go Show resolved Hide resolved
@lmm
Copy link
Contributor Author

lmm commented Jun 10, 2020

Am I right that this is mostly copied from our Enterprise code? Please can you list or identify the changes that are additional to that? (Because I think there's less value in reviewing Enterprise-copied code.)

Thanks @neiljerram . The first 2 commits are cherry-picked from enterprise code. The last commit is newly added. The docs PR (also cherry-picked) is here: projectcalico/calico#3643

If there isn't already a design or doc that says this, please can you also summarise, for me, where global() is allowed, and why?

global() is allowed as a value for an EntityRule's namespaceSelector.

Copy link
Member

@nelljerram nelljerram left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just one piece of validation+test missing, I think, and a possible text markup.

reflect.ValueOf(spec.Selector),
"NetworkPolicySpec.Selector",
"",
reason(fmt.Sprintf("%s can only be used in a GlobalNetworkPolicy EntityRule", globalSelector)),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add "namespaceSelector" ? (And similarly in all other occurrences below.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

},
},
}, true,
),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to add test and validation for disallowing global() in EntityRule selector field.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added in 4c46c87. In bdb4189 I added some tests for EntityRule

@lmm
Copy link
Contributor Author

lmm commented Jun 11, 2020

@neiljerram this is ready for another look. One comment re:

I'm wondering if global() must be the entire content of any selector field where it is used, or if it is allowed (and makes sense) to combine with other expressions, e.g. global() && color == 'red'.

I had a chat with @doublek about this and the intent of the all(), global(), and projectcalico.org/name namespaceSelectors is that they should be used on their own and not in combination. I've added validation for this for global() and projectcalico.org/name.

But I left all() untouched as we already do some canonicalization where all() && some-other-selector results in the selector parser to reduce that to all(), and maybe we want to preserve that behaviour?

Copy link
Member

@nelljerram nelljerram left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved because I don't want to block this. I'm not sure about the projectcalico.org/name addition, but happy to leave that to you.

@@ -66,6 +67,13 @@ var (
// Hostname have to be valid ipv4, ipv6 or strings up to 64 characters.
prometheusHostRegexp = regexp.MustCompile(`^[a-zA-Z0-9:._+-]{1,64}$`)

// global() cannot be used with other selectors.
andOr = `(&&|\|\|)`
globalSelectorRegex = regexp.MustCompile(fmt.Sprintf(`%v global\(\)|global\(\) %v`, andOr, andOr))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: should the RE have * after the space, to allow for any amount of whitespace?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I see you already have a test for "global()||all()", so perhaps in the RE already stands for any amount of whitespace? (Otherwise, how is that test passing?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We parse the selector string first and use the String() from that result for the validation matching. The parsing will trim out all of the whitespace.

globalSelectorRegex = regexp.MustCompile(fmt.Sprintf(`%v global\(\)|global\(\) %v`, andOr, andOr))

// projectcalico.org/name cannot be used with other selectors.
namespaceSelectorRegex = regexp.MustCompile(fmt.Sprintf(`%v projectcalico.org/name == ".*"|projectcalico.org/name == ".*" %v`, andOr, andOr))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks plausible to me, but:

  • is it right to add this validation into the current PR? is there a particular motivation for that?
  • what about, for example, projectcalico/name in {"red", "blue", ...} - which I think should be allowed on its own, but probably not combined with anything else.

Unless there's a strong reason to include, I think it might be better to split the projectcalico.org/name validation out into another PR, so we can discuss its motivation and details more there.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you're right - I'll remove the projectcalico.org/name bits

@lmm lmm dismissed caseydavenport’s stale review June 11, 2020 15:55

Comments covered by follow-up commits

@lmm lmm merged commit 36db81b into projectcalico:master Jun 11, 2020
@lmm lmm deleted the lmm-port branch June 11, 2020 15:55
lmm added a commit to lmm/libcalico-go that referenced this pull request Jun 11, 2020
lmm added a commit that referenced this pull request Jun 11, 2020
#1253)

* Update generated crds for #1229

* Re-add manual change to crds
andreas-p pushed a commit to andreas-p/calico-accountant that referenced this pull request Jun 7, 2021
andreas-p pushed a commit to andreas-p/calico-accountant that referenced this pull request Jun 7, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants