Skip to content

Commit be718bb

Browse files
authored
Merge pull request #235 from haiyanmeng/rbac
Merge rules in config/rbac/role.yaml
2 parents 886fe23 + 4b05637 commit be718bb

File tree

1 file changed

+71
-6
lines changed

1 file changed

+71
-6
lines changed

pkg/rbac/parser.go

Lines changed: 71 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ limitations under the License.
2323
package rbac
2424

2525
import (
26+
"sort"
27+
"strings"
28+
2629
rbacv1 "k8s.io/api/rbac/v1"
2730
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2831

@@ -44,8 +47,57 @@ type Rule struct {
4447
URLs []string `marker:"urls,optional"`
4548
}
4649

50+
// ruleKey represents the resources and non-resources a Rule applies.
51+
type ruleKey struct {
52+
Groups string
53+
Resources string
54+
URLs string
55+
}
56+
57+
// key normalizes the Rule and returns a ruleKey object.
58+
func (r *Rule) key() ruleKey {
59+
r.normalize()
60+
return ruleKey{
61+
Groups: strings.Join(r.Groups, "&"),
62+
Resources: strings.Join(r.Resources, "&"),
63+
URLs: strings.Join(r.URLs, "&"),
64+
}
65+
}
66+
67+
// addVerbs adds new verbs into a Rule.
68+
// The duplicates in `r.Verbs` will be removed, and then `r.Verbs` will be sorted.
69+
func (r *Rule) addVerbs(verbs []string) {
70+
r.Verbs = removeDupAndSort(append(r.Verbs, verbs...))
71+
}
72+
73+
// normalize removes duplicates from each field of a Rule, and sorts each field.
74+
func (r *Rule) normalize() {
75+
r.Groups = removeDupAndSort(r.Groups)
76+
r.Resources = removeDupAndSort(r.Resources)
77+
r.Verbs = removeDupAndSort(r.Verbs)
78+
r.URLs = removeDupAndSort(r.URLs)
79+
}
80+
81+
// removeDupAndSort removes duplicates in strs, sorts the items, and returns a
82+
// new slice of strings.
83+
func removeDupAndSort(strs []string) []string {
84+
set := make(map[string]bool)
85+
for _, str := range strs {
86+
if _, ok := set[str]; !ok {
87+
set[str] = true
88+
}
89+
}
90+
91+
var result []string
92+
for str := range set {
93+
result = append(result, str)
94+
}
95+
sort.Strings(result)
96+
return result
97+
}
98+
4799
// ToRule converts this rule to its Kubernetes API form.
48-
func (r Rule) ToRule() rbacv1.PolicyRule {
100+
func (r *Rule) ToRule() rbacv1.PolicyRule {
49101
// fix the group names first, since letting people type "core" is nice
50102
for i, group := range r.Groups {
51103
if group == "core" {
@@ -68,20 +120,33 @@ type Generator struct {
68120
func (Generator) RegisterMarkers(into *markers.Registry) error {
69121
return into.Register(RuleDefinition)
70122
}
123+
71124
func (g Generator) Generate(ctx *genall.GenerationContext) error {
72-
var rules []rbacv1.PolicyRule
125+
rules := make(map[ruleKey]*Rule)
73126
for _, root := range ctx.Roots {
74127
markerSet, err := markers.PackageMarkers(ctx.Collector, root)
75128
if err != nil {
76129
root.AddError(err)
77130
}
78131

79-
for _, rule := range markerSet[RuleDefinition.Name] {
80-
rules = append(rules, rule.(Rule).ToRule())
132+
for _, markerValue := range markerSet[RuleDefinition.Name] {
133+
rule := markerValue.(Rule)
134+
key := rule.key()
135+
if _, ok := rules[key]; !ok {
136+
rules[key] = &rule
137+
continue
138+
}
139+
rules[key].addVerbs(rule.Verbs)
81140
}
82141
}
83142

84-
if len(rules) == 0 {
143+
var policyRules []rbacv1.PolicyRule
144+
for _, rule := range rules {
145+
policyRules = append(policyRules, rule.ToRule())
146+
147+
}
148+
149+
if len(policyRules) == 0 {
85150
return nil
86151
}
87152

@@ -93,7 +158,7 @@ func (g Generator) Generate(ctx *genall.GenerationContext) error {
93158
ObjectMeta: metav1.ObjectMeta{
94159
Name: g.RoleName,
95160
},
96-
Rules: rules,
161+
Rules: policyRules,
97162
}); err != nil {
98163
return err
99164
}

0 commit comments

Comments
 (0)