mirror of https://github.com/k3s-io/k3s
allow reconcilation of namespaced rolebindings
parent
81d01a84e0
commit
a849df9dff
|
@ -11,8 +11,8 @@ load(
|
|||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"reconcile_clusterrolebindings_test.go",
|
||||
"reconcile_role_test.go",
|
||||
"reconcile_rolebindings_test.go",
|
||||
],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
|
@ -26,9 +26,12 @@ go_test(
|
|||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"reconcile_clusterrolebindings.go",
|
||||
"clusterrole_interfaces.go",
|
||||
"clusterrolebinding_interfaces.go",
|
||||
"reconcile_role.go",
|
||||
"reconcile_rolebindings.go",
|
||||
"role_interfaces.go",
|
||||
"rolebinding_interfaces.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
|
@ -38,6 +41,7 @@ go_library(
|
|||
"//pkg/registry/rbac/validation:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/errors",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apimachinery/pkg/types",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package reconciliation
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion"
|
||||
)
|
||||
|
||||
type ClusterRoleRuleOwner struct {
|
||||
ClusterRole *rbac.ClusterRole
|
||||
}
|
||||
|
||||
func (o ClusterRoleRuleOwner) GetNamespace() string {
|
||||
return o.ClusterRole.Namespace
|
||||
}
|
||||
|
||||
func (o ClusterRoleRuleOwner) GetName() string {
|
||||
return o.ClusterRole.Name
|
||||
}
|
||||
|
||||
func (o ClusterRoleRuleOwner) GetLabels() map[string]string {
|
||||
return o.ClusterRole.Labels
|
||||
}
|
||||
|
||||
func (o ClusterRoleRuleOwner) SetLabels(in map[string]string) {
|
||||
o.ClusterRole.Labels = in
|
||||
}
|
||||
|
||||
func (o ClusterRoleRuleOwner) GetAnnotations() map[string]string {
|
||||
return o.ClusterRole.Annotations
|
||||
}
|
||||
|
||||
func (o ClusterRoleRuleOwner) SetAnnotations(in map[string]string) {
|
||||
o.ClusterRole.Annotations = in
|
||||
}
|
||||
|
||||
func (o ClusterRoleRuleOwner) GetRules() []rbac.PolicyRule {
|
||||
return o.ClusterRole.Rules
|
||||
}
|
||||
|
||||
func (o ClusterRoleRuleOwner) SetRules(in []rbac.PolicyRule) {
|
||||
o.ClusterRole.Rules = in
|
||||
}
|
||||
|
||||
type ClusterRoleModifier struct {
|
||||
Client internalversion.ClusterRoleInterface
|
||||
}
|
||||
|
||||
func (c ClusterRoleModifier) Get(namespace, name string) (RuleOwner, error) {
|
||||
ret, err := c.Client.Get(name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ClusterRoleRuleOwner{ClusterRole: ret}, err
|
||||
}
|
||||
|
||||
func (c ClusterRoleModifier) Create(in RuleOwner) (RuleOwner, error) {
|
||||
ret, err := c.Client.Create(in.(ClusterRoleRuleOwner).ClusterRole)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ClusterRoleRuleOwner{ClusterRole: ret}, err
|
||||
}
|
||||
|
||||
func (c ClusterRoleModifier) Update(in RuleOwner) (RuleOwner, error) {
|
||||
ret, err := c.Client.Update(in.(ClusterRoleRuleOwner).ClusterRole)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ClusterRoleRuleOwner{ClusterRole: ret}, err
|
||||
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package reconciliation
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion"
|
||||
)
|
||||
|
||||
type ClusterRoleBindingAdapter struct {
|
||||
ClusterRoleBinding *rbac.ClusterRoleBinding
|
||||
}
|
||||
|
||||
func (o ClusterRoleBindingAdapter) GetNamespace() string {
|
||||
return o.ClusterRoleBinding.Namespace
|
||||
}
|
||||
|
||||
func (o ClusterRoleBindingAdapter) GetName() string {
|
||||
return o.ClusterRoleBinding.Name
|
||||
}
|
||||
|
||||
func (o ClusterRoleBindingAdapter) GetUID() types.UID {
|
||||
return o.ClusterRoleBinding.UID
|
||||
}
|
||||
|
||||
func (o ClusterRoleBindingAdapter) GetLabels() map[string]string {
|
||||
return o.ClusterRoleBinding.Labels
|
||||
}
|
||||
|
||||
func (o ClusterRoleBindingAdapter) SetLabels(in map[string]string) {
|
||||
o.ClusterRoleBinding.Labels = in
|
||||
}
|
||||
|
||||
func (o ClusterRoleBindingAdapter) GetAnnotations() map[string]string {
|
||||
return o.ClusterRoleBinding.Annotations
|
||||
}
|
||||
|
||||
func (o ClusterRoleBindingAdapter) SetAnnotations(in map[string]string) {
|
||||
o.ClusterRoleBinding.Annotations = in
|
||||
}
|
||||
|
||||
func (o ClusterRoleBindingAdapter) GetRoleRef() rbac.RoleRef {
|
||||
return o.ClusterRoleBinding.RoleRef
|
||||
}
|
||||
|
||||
func (o ClusterRoleBindingAdapter) GetSubjects() []rbac.Subject {
|
||||
return o.ClusterRoleBinding.Subjects
|
||||
}
|
||||
|
||||
func (o ClusterRoleBindingAdapter) SetSubjects(in []rbac.Subject) {
|
||||
o.ClusterRoleBinding.Subjects = in
|
||||
}
|
||||
|
||||
type ClusterRoleBindingClientAdapter struct {
|
||||
Client internalversion.ClusterRoleBindingInterface
|
||||
}
|
||||
|
||||
func (c ClusterRoleBindingClientAdapter) Get(namespace, name string) (RoleBinding, error) {
|
||||
ret, err := c.Client.Get(name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ClusterRoleBindingAdapter{ClusterRoleBinding: ret}, err
|
||||
}
|
||||
|
||||
func (c ClusterRoleBindingClientAdapter) Create(in RoleBinding) (RoleBinding, error) {
|
||||
ret, err := c.Client.Create(in.(ClusterRoleBindingAdapter).ClusterRoleBinding)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ClusterRoleBindingAdapter{ClusterRoleBinding: ret}, err
|
||||
}
|
||||
|
||||
func (c ClusterRoleBindingClientAdapter) Update(in RoleBinding) (RoleBinding, error) {
|
||||
ret, err := c.Client.Update(in.(ClusterRoleBindingAdapter).ClusterRoleBinding)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ClusterRoleBindingAdapter{ClusterRoleBinding: ret}, err
|
||||
|
||||
}
|
||||
|
||||
func (c ClusterRoleBindingClientAdapter) Delete(namespace, name string, uid types.UID) error {
|
||||
return c.Client.Delete(name, &metav1.DeleteOptions{Preconditions: &metav1.Preconditions{UID: &uid}})
|
||||
}
|
|
@ -21,10 +21,8 @@ import (
|
|||
"reflect"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion"
|
||||
"k8s.io/kubernetes/pkg/registry/rbac/validation"
|
||||
)
|
||||
|
||||
|
@ -54,7 +52,7 @@ type RuleOwner interface {
|
|||
SetRules([]rbac.PolicyRule)
|
||||
}
|
||||
|
||||
type ReconcileClusterRoleOptions struct {
|
||||
type ReconcileRoleOptions struct {
|
||||
// Role is the expected role that will be reconciled
|
||||
Role RuleOwner
|
||||
// Confirm indicates writes should be performed. When false, results are returned as a dry-run.
|
||||
|
@ -85,11 +83,11 @@ type ReconcileClusterRoleResult struct {
|
|||
Protected bool
|
||||
}
|
||||
|
||||
func (o *ReconcileClusterRoleOptions) Run() (*ReconcileClusterRoleResult, error) {
|
||||
func (o *ReconcileRoleOptions) Run() (*ReconcileClusterRoleResult, error) {
|
||||
return o.run(0)
|
||||
}
|
||||
|
||||
func (o *ReconcileClusterRoleOptions) run(attempts int) (*ReconcileClusterRoleResult, error) {
|
||||
func (o *ReconcileRoleOptions) run(attempts int) (*ReconcileClusterRoleResult, error) {
|
||||
// This keeps us from retrying forever if a role keeps appearing and disappearing as we reconcile.
|
||||
// Conflict errors on update are handled at a higher level.
|
||||
if attempts > 2 {
|
||||
|
@ -215,68 +213,3 @@ func merge(maps ...map[string]string) map[string]string {
|
|||
}
|
||||
return output
|
||||
}
|
||||
|
||||
type ClusterRoleRuleOwner struct {
|
||||
ClusterRole *rbac.ClusterRole
|
||||
}
|
||||
|
||||
func (o ClusterRoleRuleOwner) GetNamespace() string {
|
||||
return o.ClusterRole.Namespace
|
||||
}
|
||||
|
||||
func (o ClusterRoleRuleOwner) GetName() string {
|
||||
return o.ClusterRole.Name
|
||||
}
|
||||
|
||||
func (o ClusterRoleRuleOwner) GetLabels() map[string]string {
|
||||
return o.ClusterRole.Labels
|
||||
}
|
||||
|
||||
func (o ClusterRoleRuleOwner) SetLabels(in map[string]string) {
|
||||
o.ClusterRole.Labels = in
|
||||
}
|
||||
|
||||
func (o ClusterRoleRuleOwner) GetAnnotations() map[string]string {
|
||||
return o.ClusterRole.Annotations
|
||||
}
|
||||
|
||||
func (o ClusterRoleRuleOwner) SetAnnotations(in map[string]string) {
|
||||
o.ClusterRole.Annotations = in
|
||||
}
|
||||
|
||||
func (o ClusterRoleRuleOwner) GetRules() []rbac.PolicyRule {
|
||||
return o.ClusterRole.Rules
|
||||
}
|
||||
|
||||
func (o ClusterRoleRuleOwner) SetRules(in []rbac.PolicyRule) {
|
||||
o.ClusterRole.Rules = in
|
||||
}
|
||||
|
||||
type ClusterRoleModifier struct {
|
||||
Client internalversion.ClusterRoleInterface
|
||||
}
|
||||
|
||||
func (c ClusterRoleModifier) Get(namespace, name string) (RuleOwner, error) {
|
||||
ret, err := c.Client.Get(name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ClusterRoleRuleOwner{ClusterRole: ret}, err
|
||||
}
|
||||
|
||||
func (c ClusterRoleModifier) Create(in RuleOwner) (RuleOwner, error) {
|
||||
ret, err := c.Client.Create(in.(ClusterRoleRuleOwner).ClusterRole)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ClusterRoleRuleOwner{ClusterRole: ret}, err
|
||||
}
|
||||
|
||||
func (c ClusterRoleModifier) Update(in RuleOwner) (RuleOwner, error) {
|
||||
ret, err := c.Client.Create(in.(ClusterRoleRuleOwner).ClusterRole)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ClusterRoleRuleOwner{ClusterRole: ret}, err
|
||||
|
||||
}
|
||||
|
|
|
@ -21,29 +21,48 @@ import (
|
|||
"reflect"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion"
|
||||
)
|
||||
|
||||
// ReconcileClusterRoleBindingOptions holds options for running a role binding reconciliation
|
||||
type ReconcileClusterRoleBindingOptions struct {
|
||||
type RoleBindingModifier interface {
|
||||
Get(namespace, name string) (RoleBinding, error)
|
||||
Delete(namespace, name string, uid types.UID) error
|
||||
Create(RoleBinding) (RoleBinding, error)
|
||||
Update(RoleBinding) (RoleBinding, error)
|
||||
}
|
||||
|
||||
type RoleBinding interface {
|
||||
GetNamespace() string
|
||||
GetName() string
|
||||
GetUID() types.UID
|
||||
GetLabels() map[string]string
|
||||
SetLabels(map[string]string)
|
||||
GetAnnotations() map[string]string
|
||||
SetAnnotations(map[string]string)
|
||||
GetRoleRef() rbac.RoleRef
|
||||
GetSubjects() []rbac.Subject
|
||||
SetSubjects([]rbac.Subject)
|
||||
}
|
||||
|
||||
// ReconcileRoleBindingOptions holds options for running a role binding reconciliation
|
||||
type ReconcileRoleBindingOptions struct {
|
||||
// RoleBinding is the expected rolebinding that will be reconciled
|
||||
RoleBinding *rbac.ClusterRoleBinding
|
||||
RoleBinding RoleBinding
|
||||
// Confirm indicates writes should be performed. When false, results are returned as a dry-run.
|
||||
Confirm bool
|
||||
// RemoveExtraSubjects indicates reconciliation should remove extra subjects from an existing role binding
|
||||
RemoveExtraSubjects bool
|
||||
// Client is used to look up existing rolebindings, and create/update the rolebinding when Confirm=true
|
||||
Client internalversion.ClusterRoleBindingInterface
|
||||
Client RoleBindingModifier
|
||||
}
|
||||
|
||||
// ReconcileClusterRoleBindingResult holds the result of a reconciliation operation.
|
||||
type ReconcileClusterRoleBindingResult struct {
|
||||
// RoleBinding is the reconciled rolebinding from the reconciliation operation.
|
||||
// If the reconcile was performed as a dry-run, or the existing rolebinding was protected, the reconciled rolebinding is not persisted.
|
||||
RoleBinding *rbac.ClusterRoleBinding
|
||||
RoleBinding RoleBinding
|
||||
|
||||
// MissingSubjects contains expected subjects that were missing from the currently persisted rolebinding
|
||||
MissingSubjects []rbac.Subject
|
||||
|
@ -60,11 +79,11 @@ type ReconcileClusterRoleBindingResult struct {
|
|||
Protected bool
|
||||
}
|
||||
|
||||
func (o *ReconcileClusterRoleBindingOptions) Run() (*ReconcileClusterRoleBindingResult, error) {
|
||||
func (o *ReconcileRoleBindingOptions) Run() (*ReconcileClusterRoleBindingResult, error) {
|
||||
return o.run(0)
|
||||
}
|
||||
|
||||
func (o *ReconcileClusterRoleBindingOptions) run(attempts int) (*ReconcileClusterRoleBindingResult, error) {
|
||||
func (o *ReconcileRoleBindingOptions) run(attempts int) (*ReconcileClusterRoleBindingResult, error) {
|
||||
// This keeps us from retrying forever if a rolebinding keeps appearing and disappearing as we reconcile.
|
||||
// Conflict errors on update are handled at a higher level.
|
||||
if attempts > 3 {
|
||||
|
@ -73,12 +92,12 @@ func (o *ReconcileClusterRoleBindingOptions) run(attempts int) (*ReconcileCluste
|
|||
|
||||
var result *ReconcileClusterRoleBindingResult
|
||||
|
||||
existingBinding, err := o.Client.Get(o.RoleBinding.Name, metav1.GetOptions{})
|
||||
existingBinding, err := o.Client.Get(o.RoleBinding.GetNamespace(), o.RoleBinding.GetName())
|
||||
switch {
|
||||
case errors.IsNotFound(err):
|
||||
result = &ReconcileClusterRoleBindingResult{
|
||||
RoleBinding: o.RoleBinding,
|
||||
MissingSubjects: o.RoleBinding.Subjects,
|
||||
MissingSubjects: o.RoleBinding.GetSubjects(),
|
||||
Operation: ReconcileCreate,
|
||||
}
|
||||
|
||||
|
@ -104,10 +123,7 @@ func (o *ReconcileClusterRoleBindingOptions) run(attempts int) (*ReconcileCluste
|
|||
switch result.Operation {
|
||||
case ReconcileRecreate:
|
||||
// Try deleting
|
||||
err := o.Client.Delete(
|
||||
existingBinding.Name,
|
||||
&metav1.DeleteOptions{Preconditions: &metav1.Preconditions{UID: &existingBinding.UID}},
|
||||
)
|
||||
err := o.Client.Delete(existingBinding.GetNamespace(), existingBinding.GetName(), existingBinding.GetUID())
|
||||
switch {
|
||||
case err == nil, errors.IsNotFound(err):
|
||||
// object no longer exists, as desired
|
||||
|
@ -155,13 +171,13 @@ func (o *ReconcileClusterRoleBindingOptions) run(attempts int) (*ReconcileCluste
|
|||
|
||||
// computeReconciledRoleBinding returns the rolebinding that must be created and/or updated to make the
|
||||
// existing rolebinding's subjects, roleref, labels, and annotations match the expected rolebinding
|
||||
func computeReconciledRoleBinding(existing, expected *rbac.ClusterRoleBinding, removeExtraSubjects bool) (*ReconcileClusterRoleBindingResult, error) {
|
||||
func computeReconciledRoleBinding(existing, expected RoleBinding, removeExtraSubjects bool) (*ReconcileClusterRoleBindingResult, error) {
|
||||
result := &ReconcileClusterRoleBindingResult{Operation: ReconcileNone}
|
||||
|
||||
result.Protected = (existing.Annotations[rbac.AutoUpdateAnnotationKey] == "false")
|
||||
result.Protected = (existing.GetAnnotations()[rbac.AutoUpdateAnnotationKey] == "false")
|
||||
|
||||
// Reset the binding completely if the roleRef is different
|
||||
if expected.RoleRef != existing.RoleRef {
|
||||
if expected.GetRoleRef() != existing.GetRoleRef() {
|
||||
result.RoleBinding = expected
|
||||
result.Operation = ReconcileRecreate
|
||||
return result, nil
|
||||
|
@ -172,30 +188,30 @@ func computeReconciledRoleBinding(existing, expected *rbac.ClusterRoleBinding, r
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.RoleBinding = changedObj.(*rbac.ClusterRoleBinding)
|
||||
result.RoleBinding = changedObj.(RoleBinding)
|
||||
|
||||
// Merge expected annotations and labels
|
||||
result.RoleBinding.Annotations = merge(expected.Annotations, result.RoleBinding.Annotations)
|
||||
if !reflect.DeepEqual(result.RoleBinding.Annotations, existing.Annotations) {
|
||||
result.RoleBinding.SetAnnotations(merge(expected.GetAnnotations(), result.RoleBinding.GetAnnotations()))
|
||||
if !reflect.DeepEqual(result.RoleBinding.GetAnnotations(), existing.GetAnnotations()) {
|
||||
result.Operation = ReconcileUpdate
|
||||
}
|
||||
result.RoleBinding.Labels = merge(expected.Labels, result.RoleBinding.Labels)
|
||||
if !reflect.DeepEqual(result.RoleBinding.Labels, existing.Labels) {
|
||||
result.RoleBinding.SetLabels(merge(expected.GetLabels(), result.RoleBinding.GetLabels()))
|
||||
if !reflect.DeepEqual(result.RoleBinding.GetLabels(), existing.GetLabels()) {
|
||||
result.Operation = ReconcileUpdate
|
||||
}
|
||||
|
||||
// Compute extra and missing subjects
|
||||
result.MissingSubjects, result.ExtraSubjects = diffSubjectLists(expected.Subjects, existing.Subjects)
|
||||
result.MissingSubjects, result.ExtraSubjects = diffSubjectLists(expected.GetSubjects(), existing.GetSubjects())
|
||||
|
||||
switch {
|
||||
case !removeExtraSubjects && len(result.MissingSubjects) > 0:
|
||||
// add missing subjects in the union case
|
||||
result.RoleBinding.Subjects = append(result.RoleBinding.Subjects, result.MissingSubjects...)
|
||||
result.RoleBinding.SetSubjects(append(result.RoleBinding.GetSubjects(), result.MissingSubjects...))
|
||||
result.Operation = ReconcileUpdate
|
||||
|
||||
case removeExtraSubjects && (len(result.MissingSubjects) > 0 || len(result.ExtraSubjects) > 0):
|
||||
// stomp to expected subjects in the non-union case
|
||||
result.RoleBinding.Subjects = expected.Subjects
|
||||
result.RoleBinding.SetSubjects(expected.GetSubjects())
|
||||
result.Operation = ReconcileUpdate
|
||||
}
|
||||
|
|
@ -161,13 +161,15 @@ func TestComputeUpdate(t *testing.T) {
|
|||
}
|
||||
|
||||
for k, tc := range tests {
|
||||
result, err := computeReconciledRoleBinding(tc.ActualBinding, tc.ExpectedBinding, tc.RemoveExtraSubjects)
|
||||
actualRoleBinding := ClusterRoleBindingAdapter{ClusterRoleBinding: tc.ActualBinding}
|
||||
expectedRoleBinding := ClusterRoleBindingAdapter{ClusterRoleBinding: tc.ExpectedBinding}
|
||||
result, err := computeReconciledRoleBinding(actualRoleBinding, expectedRoleBinding, tc.RemoveExtraSubjects)
|
||||
if err != nil {
|
||||
t.Errorf("%s: %v", k, err)
|
||||
continue
|
||||
}
|
||||
updateNeeded := result.Operation != ReconcileNone
|
||||
updatedBinding := result.RoleBinding
|
||||
updatedBinding := result.RoleBinding.(ClusterRoleBindingAdapter).ClusterRoleBinding
|
||||
if updateNeeded != tc.ExpectedUpdateNeeded {
|
||||
t.Errorf("%s: Expected\n\t%v\ngot\n\t%v (%v)", k, tc.ExpectedUpdateNeeded, updateNeeded, result.Operation)
|
||||
continue
|
|
@ -79,7 +79,7 @@ func (c RoleModifier) Create(in RuleOwner) (RuleOwner, error) {
|
|||
}
|
||||
|
||||
func (c RoleModifier) Update(in RuleOwner) (RuleOwner, error) {
|
||||
ret, err := c.Client.Roles(in.GetNamespace()).Create(in.(RoleRuleOwner).Role)
|
||||
ret, err := c.Client.Roles(in.GetNamespace()).Update(in.(RoleRuleOwner).Role)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package reconciliation
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion"
|
||||
)
|
||||
|
||||
type RoleBindingAdapter struct {
|
||||
RoleBinding *rbac.RoleBinding
|
||||
}
|
||||
|
||||
func (o RoleBindingAdapter) GetNamespace() string {
|
||||
return o.RoleBinding.Namespace
|
||||
}
|
||||
|
||||
func (o RoleBindingAdapter) GetName() string {
|
||||
return o.RoleBinding.Name
|
||||
}
|
||||
|
||||
func (o RoleBindingAdapter) GetUID() types.UID {
|
||||
return o.RoleBinding.UID
|
||||
}
|
||||
|
||||
func (o RoleBindingAdapter) GetLabels() map[string]string {
|
||||
return o.RoleBinding.Labels
|
||||
}
|
||||
|
||||
func (o RoleBindingAdapter) SetLabels(in map[string]string) {
|
||||
o.RoleBinding.Labels = in
|
||||
}
|
||||
|
||||
func (o RoleBindingAdapter) GetAnnotations() map[string]string {
|
||||
return o.RoleBinding.Annotations
|
||||
}
|
||||
|
||||
func (o RoleBindingAdapter) SetAnnotations(in map[string]string) {
|
||||
o.RoleBinding.Annotations = in
|
||||
}
|
||||
|
||||
func (o RoleBindingAdapter) GetRoleRef() rbac.RoleRef {
|
||||
return o.RoleBinding.RoleRef
|
||||
}
|
||||
|
||||
func (o RoleBindingAdapter) GetSubjects() []rbac.Subject {
|
||||
return o.RoleBinding.Subjects
|
||||
}
|
||||
|
||||
func (o RoleBindingAdapter) SetSubjects(in []rbac.Subject) {
|
||||
o.RoleBinding.Subjects = in
|
||||
}
|
||||
|
||||
type RoleBindingClientAdapter struct {
|
||||
Client internalversion.RoleBindingsGetter
|
||||
}
|
||||
|
||||
func (c RoleBindingClientAdapter) Get(namespace, name string) (RoleBinding, error) {
|
||||
ret, err := c.Client.RoleBindings(namespace).Get(name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return RoleBindingAdapter{RoleBinding: ret}, err
|
||||
}
|
||||
|
||||
func (c RoleBindingClientAdapter) Create(in RoleBinding) (RoleBinding, error) {
|
||||
ret, err := c.Client.RoleBindings(in.GetNamespace()).Create(in.(RoleBindingAdapter).RoleBinding)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return RoleBindingAdapter{RoleBinding: ret}, err
|
||||
}
|
||||
|
||||
func (c RoleBindingClientAdapter) Update(in RoleBinding) (RoleBinding, error) {
|
||||
ret, err := c.Client.RoleBindings(in.GetNamespace()).Update(in.(RoleBindingAdapter).RoleBinding)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return RoleBindingAdapter{RoleBinding: ret}, err
|
||||
|
||||
}
|
||||
|
||||
func (c RoleBindingClientAdapter) Delete(namespace, name string, uid types.UID) error {
|
||||
return c.Client.RoleBindings(namespace).Delete(name, &metav1.DeleteOptions{Preconditions: &metav1.Preconditions{UID: &uid}})
|
||||
}
|
|
@ -147,7 +147,7 @@ func PostStartHook(hookContext genericapiserver.PostStartHookContext) error {
|
|||
|
||||
// ensure bootstrap roles are created or reconciled
|
||||
for _, clusterRole := range append(bootstrappolicy.ClusterRoles(), bootstrappolicy.ControllerRoles()...) {
|
||||
opts := reconciliation.ReconcileClusterRoleOptions{
|
||||
opts := reconciliation.ReconcileRoleOptions{
|
||||
Role: reconciliation.ClusterRoleRuleOwner{ClusterRole: &clusterRole},
|
||||
Client: reconciliation.ClusterRoleModifier{Client: clientset.ClusterRoles()},
|
||||
Confirm: true,
|
||||
|
@ -175,9 +175,9 @@ func PostStartHook(hookContext genericapiserver.PostStartHookContext) error {
|
|||
|
||||
// ensure bootstrap rolebindings are created or reconciled
|
||||
for _, clusterRoleBinding := range append(bootstrappolicy.ClusterRoleBindings(), bootstrappolicy.ControllerRoleBindings()...) {
|
||||
opts := reconciliation.ReconcileClusterRoleBindingOptions{
|
||||
RoleBinding: &clusterRoleBinding,
|
||||
Client: clientset.ClusterRoleBindings(),
|
||||
opts := reconciliation.ReconcileRoleBindingOptions{
|
||||
RoleBinding: reconciliation.ClusterRoleBindingAdapter{ClusterRoleBinding: &clusterRoleBinding},
|
||||
Client: reconciliation.ClusterRoleBindingClientAdapter{Client: clientset.ClusterRoleBindings()},
|
||||
Confirm: true,
|
||||
}
|
||||
err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {
|
||||
|
@ -206,7 +206,7 @@ func PostStartHook(hookContext genericapiserver.PostStartHookContext) error {
|
|||
// ensure bootstrap namespaced roles are created or reconciled
|
||||
for namespace, roles := range bootstrappolicy.NamespaceRoles() {
|
||||
for _, role := range roles {
|
||||
opts := reconciliation.ReconcileClusterRoleOptions{
|
||||
opts := reconciliation.ReconcileRoleOptions{
|
||||
Role: reconciliation.RoleRuleOwner{Role: &role},
|
||||
Client: reconciliation.RoleModifier{Client: clientset},
|
||||
Confirm: true,
|
||||
|
|
Loading…
Reference in New Issue