Skip to content

Commit

Permalink
Add support for global() selector in calico network policy
Browse files Browse the repository at this point in the history
Add support for rules and selector for global keyword and add unit test
case
  • Loading branch information
Gobinath Krishnamoorthy authored and lmm committed Apr 27, 2020
1 parent 9a7d893 commit f1f9255
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 0 deletions.
5 changes: 5 additions & 0 deletions lib/backend/syncersv1/updateprocessors/rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ func getEndpointSelector(namespaceSelector, endpointSelector, serviceAccountSele
// all endpoints, translate this to an equivalent expression which means select any workload that
// is in a namespace.
nsSelector = strings.Replace(nsSelector, "all()", "has(projectcalico.org/namespace)", -1)

// We treat "global()" as opposite to `all()`, selects only host endpoints or GlobalNetworksets
// Since in the v1 data model "all()" will select all endpoints,
// translate this to an equivalent expressions which means select no workload endpoints
nsSelector = strings.Replace(nsSelector, "global()", "!has(projectcalico.org/namespace)", -1)
} else if ns != "" {
// No namespace selector was given and this is a namespaced network policy,
// so the rule applies only to its own namespace.
Expand Down
33 changes: 33 additions & 0 deletions lib/backend/syncersv1/updateprocessors/rules_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -472,4 +472,37 @@ var _ = Describe("Test the Rules Conversion Functions", func() {
Expect(rulev1.DstSelector).To(Equal(dste))
})
})

It("should parse a set of rules and validates the namespaceselector with label and all()", func() {
rules := []apiv3.Rule{
{
Action: apiv3.Allow,
Destination: apiv3.EntityRule{
NamespaceSelector: "namespace == 'red'",
Selector: "has(label1)",
},
},
{
Action: apiv3.Allow,
Destination: apiv3.EntityRule{
NamespaceSelector: "all()",
Selector: "has(label2)",
},
},
{
Action: apiv3.Allow,
Destination: apiv3.EntityRule{
NamespaceSelector: "global()",
Selector: "has(label3)",
},
},
}

outRules := updateprocessors.RulesAPIV2ToBackend(rules, "namespace")
// The first rule should select "namespace `red`, the second rule should have 'has(projectcalico.org/namespace)'
// and third rule should select '!has(projectcalico.org/namespace)'
Expect(outRules[0].DstSelector).To(Equal("(pcns.namespace == \"red\") && (has(label1))"))
Expect(outRules[1].DstSelector).To(Equal("(has(projectcalico.org/namespace)) && (has(label2))"))
Expect(outRules[2].DstSelector).To(Equal("(!has(projectcalico.org/namespace)) && (has(label3))"))
})
})
16 changes: 16 additions & 0 deletions lib/selector/parser/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -429,3 +429,19 @@ func appendLabelOpAndQuotedString(fragments []string, label, op, s string) []str
}
return append(fragments, label, op, quote, s, quote)
}

type GlobalNode struct {
}

func (node *GlobalNode) Evaluate(labels Labels) bool {

return true
}

func (node *GlobalNode) AcceptVisitor(v Visitor) {
v.Visit(node)
}

func (node *GlobalNode) collectFragments(fragments []string) []string {
return append(fragments, "global()")
}
3 changes: 3 additions & 0 deletions lib/selector/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ func parseOperation(tokens []tokenizer.Token) (sel node, remTokens []tokenizer.T
case tokenizer.TokAll:
sel = &AllNode{}
remTokens = tokens[1:]
case tokenizer.TokGlobal:
sel = &GlobalNode{}
remTokens = tokens[1:]
case tokenizer.TokLabel:
// should have an operator and a literal.
if len(tokens) < 3 {
Expand Down
3 changes: 3 additions & 0 deletions lib/selector/parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ var selectorTests = []selectorTest{
{`all()`, []map[string]string{{}}, []map[string]string{}},
{` all()`, []map[string]string{{}}, []map[string]string{}},
{` all()`, []map[string]string{{"a": "b"}}, []map[string]string{}},
{`global()`, []map[string]string{{}}, []map[string]string{}},
{` global()`, []map[string]string{{}}, []map[string]string{}},
{` global()`, []map[string]string{{"a": "b"}}, []map[string]string{}},

{`a == 'a'`, []map[string]string{}, []map[string]string{{"a": "b"}}},
{`a == 'a'`, []map[string]string{}, []map[string]string{{}}},
Expand Down

0 comments on commit f1f9255

Please sign in to comment.