Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ func (c *InstallStrategyDeploymentClientForNamespace) GetOpLister() operatorlist
}

func (c *InstallStrategyDeploymentClientForNamespace) CreateRole(role *rbacv1.Role) (*rbacv1.Role, error) {
return c.opClient.KubernetesInterface().RbacV1().Roles(c.Namespace).Create(context.TODO(), role, metav1.CreateOptions{})
return c.opClient.CreateRole(role)
}

func (c *InstallStrategyDeploymentClientForNamespace) CreateRoleBinding(roleBinding *rbacv1.RoleBinding) (*rbacv1.RoleBinding, error) {
return c.opClient.KubernetesInterface().RbacV1().RoleBindings(c.Namespace).Create(context.TODO(), roleBinding, metav1.CreateOptions{})
return c.opClient.CreateRoleBinding(roleBinding)
}

func (c *InstallStrategyDeploymentClientForNamespace) EnsureServiceAccount(serviceAccount *corev1.ServiceAccount, owner ownerutil.Owner) (*corev1.ServiceAccount, error) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -734,6 +734,9 @@ func (c *ConfigMapUnpacker) ensureRole(cmRef *corev1.ObjectReference) (role *rba
if err != nil {
if apierrors.IsNotFound(err) {
role, err = c.client.RbacV1().Roles(fresh.GetNamespace()).Create(context.TODO(), fresh, metav1.CreateOptions{})
if apierrors.IsAlreadyExists(err) {
role, err = c.client.RbacV1().Roles(fresh.GetNamespace()).Update(context.TODO(), fresh, metav1.UpdateOptions{})
}
}

return
Expand Down Expand Up @@ -778,6 +781,9 @@ func (c *ConfigMapUnpacker) ensureRoleBinding(cmRef *corev1.ObjectReference) (ro
if err != nil {
if apierrors.IsNotFound(err) {
roleBinding, err = c.client.RbacV1().RoleBindings(fresh.GetNamespace()).Create(context.TODO(), fresh, metav1.CreateOptions{})
if apierrors.IsAlreadyExists(err) {
roleBinding, err = c.client.RbacV1().RoleBindings(fresh.GetNamespace()).Update(context.TODO(), fresh, metav1.UpdateOptions{})
}
}

return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -463,53 +463,24 @@ func (i *StrategyDeploymentInstaller) installCertRequirementsForDeployment(deplo
return nil, nil, err
}

// Create RoleBinding to extension-apiserver-authentication-reader Role in the kube-system namespace.
authReaderRoleBinding := &rbacv1.RoleBinding{
Subjects: []rbacv1.Subject{
{
Kind: "ServiceAccount",
APIGroup: "",
Name: depSpec.Template.Spec.ServiceAccountName,
Namespace: i.owner.GetNamespace(),
},
},
RoleRef: rbacv1.RoleRef{
APIGroup: "rbac.authorization.k8s.io",
Kind: "Role",
Name: "extension-apiserver-authentication-reader",
},
}
authReaderRoleBinding.SetName(AuthReaderRoleBindingName(serviceName))
authReaderRoleBinding.SetNamespace(KubeSystem)
authReaderRoleBinding.SetLabels(map[string]string{OLMManagedLabelKey: OLMManagedLabelValue})
// Apply RoleBinding to extension-apiserver-authentication-reader Role in the kube-system namespace.
authReaderRoleBindingApplyConfig := rbacv1ac.RoleBinding(AuthReaderRoleBindingName(serviceName), KubeSystem).
WithLabels(map[string]string{OLMManagedLabelKey: OLMManagedLabelValue}).
WithSubjects(rbacv1ac.Subject().
WithKind("ServiceAccount").
WithAPIGroup("").
WithName(depSpec.Template.Spec.ServiceAccountName).
WithNamespace(i.owner.GetNamespace())).
WithRoleRef(rbacv1ac.RoleRef().
WithAPIGroup("rbac.authorization.k8s.io").
WithKind("Role").
WithName("extension-apiserver-authentication-reader"))

existingAuthReaderRoleBinding, err := i.strategyClient.GetOpLister().RbacV1().RoleBindingLister().RoleBindings(KubeSystem).Get(authReaderRoleBinding.GetName())
if err == nil {
// Check if the only owners are this CSV or in this CSV's replacement chain.
if ownerutil.AdoptableLabels(existingAuthReaderRoleBinding.GetLabels(), true, i.owner) {
logger.WithFields(log.Fields{"obj": "existingAuthReaderRB", "labels": existingAuthReaderRoleBinding.GetLabels()}).Debug("adopting")
if err := ownerutil.AddOwnerLabels(authReaderRoleBinding, i.owner); err != nil {
return nil, nil, err
}
}
// Attempt an update.
if _, err := i.strategyClient.GetOpClient().UpdateRoleBinding(authReaderRoleBinding); err != nil {
logger.Warnf("could not update auth reader role binding %s", authReaderRoleBinding.GetName())
return nil, nil, err
}
} else if apierrors.IsNotFound(err) {
// Create the role.
if err := ownerutil.AddOwnerLabels(authReaderRoleBinding, i.owner); err != nil {
return nil, nil, err
}
_, err = i.strategyClient.GetOpClient().CreateRoleBinding(authReaderRoleBinding)
if err != nil {
log.Warnf("could not create auth reader role binding %s", authReaderRoleBinding.GetName())
return nil, nil, err
}
} else {
if _, err = i.strategyClient.GetOpClient().ApplyRoleBinding(authReaderRoleBindingApplyConfig, metav1.ApplyOptions{Force: true, FieldManager: "olm.install"}); err != nil {
log.Errorf("could not apply auth reader rolebinding %s: %s", *authReaderRoleBindingApplyConfig.Name, err.Error())
return nil, nil, err
}

AddDefaultCertVolumeAndVolumeMounts(&depSpec, secret.GetName())

// Setting the olm hash label forces a rollout and ensures that the new secret
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,19 @@ func TestInstallCertRequirementsForDeployment(t *testing.T) {
authReaderRoleBinding.SetNamespace(KubeSystem)
authReaderRoleBinding.SetLabels(map[string]string{OLMManagedLabelKey: OLMManagedLabelValue})

mockOpClient.EXPECT().UpdateRoleBinding(authReaderRoleBinding).Return(authReaderRoleBinding, nil)
authReaderRoleBindingApplyConfig := rbacv1ac.RoleBinding(AuthReaderRoleBindingName(service.GetName()), KubeSystem).
WithLabels(map[string]string{OLMManagedLabelKey: OLMManagedLabelValue}).
WithSubjects(rbacv1ac.Subject().
WithKind("ServiceAccount").
WithAPIGroup("").
WithName(args.depSpec.Template.Spec.ServiceAccountName).
WithNamespace(namespace)).
WithRoleRef(rbacv1ac.RoleRef().
WithAPIGroup("rbac.authorization.k8s.io").
WithKind("Role").
WithName("extension-apiserver-authentication-reader"))

mockOpClient.EXPECT().ApplyRoleBinding(authReaderRoleBindingApplyConfig, metav1.ApplyOptions{Force: true, FieldManager: "olm.install"}).Return(authReaderRoleBinding, nil)
},
state: fakeState{
existingService: &corev1.Service{
Expand Down Expand Up @@ -569,7 +581,19 @@ func TestInstallCertRequirementsForDeployment(t *testing.T) {
authReaderRoleBinding.SetNamespace(KubeSystem)
authReaderRoleBinding.SetLabels(map[string]string{OLMManagedLabelKey: OLMManagedLabelValue})

mockOpClient.EXPECT().UpdateRoleBinding(authReaderRoleBinding).Return(authReaderRoleBinding, nil)
authReaderRoleBindingApplyConfig := rbacv1ac.RoleBinding(AuthReaderRoleBindingName(service.GetName()), KubeSystem).
WithLabels(map[string]string{OLMManagedLabelKey: OLMManagedLabelValue}).
WithSubjects(rbacv1ac.Subject().
WithKind("ServiceAccount").
WithAPIGroup("").
WithName(args.depSpec.Template.Spec.ServiceAccountName).
WithNamespace(namespace)).
WithRoleRef(rbacv1ac.RoleRef().
WithAPIGroup("rbac.authorization.k8s.io").
WithKind("Role").
WithName("extension-apiserver-authentication-reader"))

mockOpClient.EXPECT().ApplyRoleBinding(authReaderRoleBindingApplyConfig, metav1.ApplyOptions{Force: true, FieldManager: "olm.install"}).Return(authReaderRoleBinding, nil)
},
state: fakeState{
existingService: &corev1.Service{
Expand Down Expand Up @@ -831,7 +855,19 @@ func TestInstallCertRequirementsForDeployment(t *testing.T) {
authReaderRoleBinding.SetNamespace(KubeSystem)
authReaderRoleBinding.SetLabels(map[string]string{OLMManagedLabelKey: OLMManagedLabelValue})

mockOpClient.EXPECT().UpdateRoleBinding(authReaderRoleBinding).Return(authReaderRoleBinding, nil)
authReaderRoleBindingApplyConfig := rbacv1ac.RoleBinding(AuthReaderRoleBindingName(service.GetName()), KubeSystem).
WithLabels(map[string]string{OLMManagedLabelKey: OLMManagedLabelValue}).
WithSubjects(rbacv1ac.Subject().
WithKind("ServiceAccount").
WithAPIGroup("").
WithName(args.depSpec.Template.Spec.ServiceAccountName).
WithNamespace(namespace)).
WithRoleRef(rbacv1ac.RoleRef().
WithAPIGroup("rbac.authorization.k8s.io").
WithKind("Role").
WithName("extension-apiserver-authentication-reader"))

mockOpClient.EXPECT().ApplyRoleBinding(authReaderRoleBindingApplyConfig, metav1.ApplyOptions{Force: true, FieldManager: "olm.install"}).Return(authReaderRoleBinding, nil)
},
state: fakeState{
existingService: nil,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1511,6 +1511,7 @@ func TestTransitionCSV(t *testing.T) {
// Note: Ideally we would not pre-create these objects, but fake client does not support
// creation through SSA, see issue here: https://github.com/kubernetes/kubernetes/issues/115598
// Once resolved, these objects and others in this file may be removed.
roleBinding("a1-service-auth-reader", "kube-system", "extension-apiserver-authentication-reader", "sa", namespace),
service("a1-service", namespace, "a1", 80),
clusterRoleBinding("a1-service-system:auth-delegator", "system:auth-delegator", "sa", namespace),
},
Expand Down Expand Up @@ -5985,8 +5986,9 @@ func TestCARotation(t *testing.T) {
), defaultTemplateAnnotations), apis("a1.v1.a1Kind"), nil),
},
clientObjs: []runtime.Object{addAnnotation(defaultOperatorGroup, operatorsv1.OperatorGroupProvidedAPIsAnnotationKey, "c1.v1.g1,a1Kind.v1.a1")},
// The service and clusterRoleBinding have been added here as a workaround to fake client not supporting SSA
// The rolebinding, service, and clusterRoleBinding have been added here as a workaround to fake client not supporting SSA
objs: []runtime.Object{
roleBinding("a1-service-auth-reader", "kube-system", "extension-apiserver-authentication-reader", "sa", namespace),
service("a1-service", namespace, "a1", 80, ownerReference),
clusterRoleBinding("a1-service-system:auth-delegator", "system:auth-delegator", "sa", namespace),
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -408,11 +408,8 @@ func (a *Operator) ensureProvidedAPIClusterRole(namePrefix, suffix string, verbs
return err
}
if apierrors.IsNotFound(err) {
existingCR, err = a.opClient.KubernetesInterface().RbacV1().ClusterRoles().Create(context.TODO(), clusterRole, metav1.CreateOptions{})
if err == nil {
return nil
}
if !apierrors.IsAlreadyExists(err) {
existingCR, err = a.opClient.CreateClusterRole(clusterRole)
if err != nil {
a.logger.WithError(err).Errorf("Create cluster role failed: %v", clusterRole)
return err
}
Expand Down Expand Up @@ -546,12 +543,7 @@ func (a *Operator) ensureSingletonRBAC(operatorNamespace string, csv *v1alpha1.C
Resources: []string{"namespaces"},
}),
}
// TODO: this should do something smarter if the cluster role already exists
if cr, err := a.opClient.CreateClusterRole(clusterRole); err != nil {
// If the CR already exists, but the label is correct, the cache is just behind
if apierrors.IsAlreadyExists(err) && cr != nil && ownerutil.IsOwnedByLabel(cr, csv) {
continue
}
if _, err := a.opClient.CreateClusterRole(clusterRole); err != nil {
return err
}
a.logger.Debug("created cluster role")
Expand Down Expand Up @@ -585,12 +577,7 @@ func (a *Operator) ensureSingletonRBAC(operatorNamespace string, csv *v1alpha1.C
Name: r.RoleRef.Name,
},
}
// TODO: this should do something smarter if the cluster role binding already exists
if crb, err := a.opClient.CreateClusterRoleBinding(clusterRoleBinding); err != nil {
// If the CRB already exists, but the label is correct, the cache is just behind
if apierrors.IsAlreadyExists(err) && crb != nil && ownerutil.IsOwnedByLabel(crb, csv) {
continue
}
if _, err := a.opClient.CreateClusterRoleBinding(clusterRoleBinding); err != nil {
return err
}
}
Expand Down Expand Up @@ -1056,7 +1043,7 @@ func (a *Operator) ensureOpGroupClusterRole(op *operatorsv1.OperatorGroup, suffi
clusterRole.Labels[install.OLMManagedLabelKey] = install.OLMManagedLabelValue

a.logger.Infof("creating cluster role: %s owned by operator group: %s/%s", clusterRole.GetName(), op.GetNamespace(), op.GetName())
_, err = a.opClient.KubernetesInterface().RbacV1().ClusterRoles().Create(context.TODO(), clusterRole, metav1.CreateOptions{})
_, err = a.opClient.CreateClusterRole(clusterRole)
return err
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,10 @@ func (r *OperatorConditionReconciler) ensureOperatorConditionRole(operatorCondit
if !apierrors.IsNotFound(err) {
return err
}
return r.Client.Create(context.TODO(), role)
err = r.Client.Create(context.TODO(), role)
if apierrors.IsAlreadyExists(err) {
return r.Client.Update(context.TODO(), role)
}
}

if ownerutil.IsOwnedBy(existingRole, operatorCondition) &&
Expand Down Expand Up @@ -199,7 +202,10 @@ func (r *OperatorConditionReconciler) ensureOperatorConditionRoleBinding(operato
if !apierrors.IsNotFound(err) {
return err
}
return r.Client.Create(context.TODO(), roleBinding)
err = r.Client.Create(context.TODO(), roleBinding)
if apierrors.IsAlreadyExists(err) {
return r.Client.Update(context.TODO(), roleBinding)
}
}

if ownerutil.IsOwnedBy(existingRoleBinding, operatorCondition) &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,20 @@ import (
"context"
"fmt"

apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/klog"
apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
)

// CreateAPIService creates the APIService.
// CreateAPIService creates the APIService or Updates if it already exists.
func (c *Client) CreateAPIService(ig *apiregistrationv1.APIService) (*apiregistrationv1.APIService, error) {
return c.ApiregistrationV1Interface().ApiregistrationV1().APIServices().Create(context.TODO(), ig, metav1.CreateOptions{})
createdAS, err := c.ApiregistrationV1Interface().ApiregistrationV1().APIServices().Create(context.TODO(), ig, metav1.CreateOptions{})
if apierrors.IsAlreadyExists(err) {
return c.UpdateAPIService(ig)
}
return createdAS, err
}

// GetAPIService returns the existing APIService.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ type RoleClient interface {

// RoleBindingClient contains methods for manipulating RoleBindings.
type RoleBindingClient interface {
ApplyRoleBinding(applyConfig *rbacv1ac.RoleBindingApplyConfiguration, applyOptions metav1.ApplyOptions) (*rbacv1.RoleBinding, error)
CreateRoleBinding(*rbacv1.RoleBinding) (*rbacv1.RoleBinding, error)
GetRoleBinding(namespace, name string) (*rbacv1.RoleBinding, error)
UpdateRoleBinding(modified *rbacv1.RoleBinding) (*rbacv1.RoleBinding, error)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,19 @@ import (
"fmt"

rbacv1 "k8s.io/api/rbac/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/klog"
)

// CreateClusterRole creates the ClusterRole.
// CreateClusterRole creates the ClusterRole or Updates if it already exists.
func (c *Client) CreateClusterRole(r *rbacv1.ClusterRole) (*rbacv1.ClusterRole, error) {
return c.RbacV1().ClusterRoles().Create(context.TODO(), r, metav1.CreateOptions{})
createdClusterRole, err := c.RbacV1().ClusterRoles().Create(context.TODO(), r, metav1.CreateOptions{})
if apierrors.IsAlreadyExists(err) {
return c.UpdateClusterRole(r)
}
return createdClusterRole, err
}

// GetClusterRole returns the existing ClusterRole.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"

rbacv1 "k8s.io/api/rbac/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
acv1 "k8s.io/client-go/applyconfigurations/rbac/v1"
Expand All @@ -16,9 +17,13 @@ func (c *Client) ApplyClusterRoleBinding(applyConfig *acv1.ClusterRoleBindingApp
return c.RbacV1().ClusterRoleBindings().Apply(context.TODO(), applyConfig, applyOptions)
}

// CreateRoleBinding creates the roleBinding.
// CreateRoleBinding creates the roleBinding or Updates if it already exists.
func (c *Client) CreateClusterRoleBinding(ig *rbacv1.ClusterRoleBinding) (*rbacv1.ClusterRoleBinding, error) {
return c.RbacV1().ClusterRoleBindings().Create(context.TODO(), ig, metav1.CreateOptions{})
createdCRB, err := c.RbacV1().ClusterRoleBindings().Create(context.TODO(), ig, metav1.CreateOptions{})
if apierrors.IsAlreadyExists(err) {
return c.UpdateClusterRoleBinding(ig)
}
return createdCRB, err
}

// GetRoleBinding returns the existing roleBinding.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,19 @@ import (
"fmt"

corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/klog"
)

// CreateConfigMap creates the ConfigMap.
func (c *Client) CreateConfigMap(ig *corev1.ConfigMap) (*corev1.ConfigMap, error) {
return c.CoreV1().ConfigMaps(ig.GetNamespace()).Create(context.TODO(), ig, metav1.CreateOptions{})
createdCM, err := c.CoreV1().ConfigMaps(ig.GetNamespace()).Create(context.TODO(), ig, metav1.CreateOptions{})
if apierrors.IsAlreadyExists(err) {
return c.UpdateConfigMap(ig)
}
return createdCM, err
}

// GetConfigMap returns the existing ConfigMap.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"time"

"k8s.io/apimachinery/pkg/api/errors"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/util/wait"
Expand Down Expand Up @@ -92,7 +93,7 @@ func (c *Client) CreateCustomResourceRaw(apiGroup, version, namespace, kind stri
return nil
}

// CreateCustomResourceRawIfNotFound creates the raw bytes of the custom resource if it doesn't exist.
// CreateCustomResourceRawIfNotFound creates the raw bytes of the custom resource if it doesn't exist, or Updates if it does exist.
// It also returns a boolean to indicate whether a new custom resource is created.
func (c *Client) CreateCustomResourceRawIfNotFound(apiGroup, version, namespace, kind, name string, data []byte) (bool, error) {
klog.V(4).Infof("[CREATE CUSTOM RESOURCE RAW if not found]: %s:%s", namespace, name)
Expand All @@ -104,7 +105,11 @@ func (c *Client) CreateCustomResourceRawIfNotFound(apiGroup, version, namespace,
return false, err
}
err = c.CreateCustomResourceRaw(apiGroup, version, namespace, kind, data)
if err != nil {
if apierrors.IsAlreadyExists(err) {
if err = c.UpdateCustomResourceRaw(apiGroup, version, namespace, kind, name, data); err != nil {
return false, err
}
} else if err != nil {
return false, err
}
return true, nil
Expand Down
Loading