Skip to content

Commit 01496f7

Browse files
committed
Update if AlreadyExists
Adds code to the client calls for Create to run an Update if the object already exists. This allows us to bypass issues where the object was not found in cache but already exists in the cluster. Signed-off-by: Daniel Franz <[email protected]>
1 parent be20100 commit 01496f7

14 files changed

+81
-32
lines changed

Diff for: pkg/api/wrappers/deployment_install_client.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,11 @@ func (c *InstallStrategyDeploymentClientForNamespace) GetOpLister() operatorlist
5858
}
5959

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

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

6868
func (c *InstallStrategyDeploymentClientForNamespace) EnsureServiceAccount(serviceAccount *corev1.ServiceAccount, owner ownerutil.Owner) (*corev1.ServiceAccount, error) {

Diff for: pkg/controller/bundle/bundle_unpacker.go

+6
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,9 @@ func (c *ConfigMapUnpacker) ensureRole(cmRef *corev1.ObjectReference) (role *rba
734734
if err != nil {
735735
if apierrors.IsNotFound(err) {
736736
role, err = c.client.RbacV1().Roles(fresh.GetNamespace()).Create(context.TODO(), fresh, metav1.CreateOptions{})
737+
if apierrors.IsAlreadyExists(err) {
738+
role, err = c.client.RbacV1().Roles(fresh.GetNamespace()).Update(context.TODO(), fresh, metav1.UpdateOptions{})
739+
}
737740
}
738741

739742
return
@@ -778,6 +781,9 @@ func (c *ConfigMapUnpacker) ensureRoleBinding(cmRef *corev1.ObjectReference) (ro
778781
if err != nil {
779782
if apierrors.IsNotFound(err) {
780783
roleBinding, err = c.client.RbacV1().RoleBindings(fresh.GetNamespace()).Create(context.TODO(), fresh, metav1.CreateOptions{})
784+
if apierrors.IsAlreadyExists(err) {
785+
roleBinding, err = c.client.RbacV1().RoleBindings(fresh.GetNamespace()).Update(context.TODO(), fresh, metav1.UpdateOptions{})
786+
}
781787
}
782788

783789
return

Diff for: pkg/controller/operators/olm/operatorgroup.go

+5-18
Original file line numberDiff line numberDiff line change
@@ -408,11 +408,8 @@ func (a *Operator) ensureProvidedAPIClusterRole(namePrefix, suffix string, verbs
408408
return err
409409
}
410410
if apierrors.IsNotFound(err) {
411-
existingCR, err = a.opClient.KubernetesInterface().RbacV1().ClusterRoles().Create(context.TODO(), clusterRole, metav1.CreateOptions{})
412-
if err == nil {
413-
return nil
414-
}
415-
if !apierrors.IsAlreadyExists(err) {
411+
existingCR, err = a.opClient.CreateClusterRole(clusterRole)
412+
if err != nil {
416413
a.logger.WithError(err).Errorf("Create cluster role failed: %v", clusterRole)
417414
return err
418415
}
@@ -546,12 +543,7 @@ func (a *Operator) ensureSingletonRBAC(operatorNamespace string, csv *v1alpha1.C
546543
Resources: []string{"namespaces"},
547544
}),
548545
}
549-
// TODO: this should do something smarter if the cluster role already exists
550-
if cr, err := a.opClient.CreateClusterRole(clusterRole); err != nil {
551-
// If the CR already exists, but the label is correct, the cache is just behind
552-
if apierrors.IsAlreadyExists(err) && cr != nil && ownerutil.IsOwnedByLabel(cr, csv) {
553-
continue
554-
}
546+
if _, err := a.opClient.CreateClusterRole(clusterRole); err != nil {
555547
return err
556548
}
557549
a.logger.Debug("created cluster role")
@@ -585,12 +577,7 @@ func (a *Operator) ensureSingletonRBAC(operatorNamespace string, csv *v1alpha1.C
585577
Name: r.RoleRef.Name,
586578
},
587579
}
588-
// TODO: this should do something smarter if the cluster role binding already exists
589-
if crb, err := a.opClient.CreateClusterRoleBinding(clusterRoleBinding); err != nil {
590-
// If the CRB already exists, but the label is correct, the cache is just behind
591-
if apierrors.IsAlreadyExists(err) && crb != nil && ownerutil.IsOwnedByLabel(crb, csv) {
592-
continue
593-
}
580+
if _, err := a.opClient.CreateClusterRoleBinding(clusterRoleBinding); err != nil {
594581
return err
595582
}
596583
}
@@ -1056,7 +1043,7 @@ func (a *Operator) ensureOpGroupClusterRole(op *operatorsv1.OperatorGroup, suffi
10561043
clusterRole.Labels[install.OLMManagedLabelKey] = install.OLMManagedLabelValue
10571044

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

Diff for: pkg/controller/operators/operatorcondition_controller.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,10 @@ func (r *OperatorConditionReconciler) ensureOperatorConditionRole(operatorCondit
150150
if !apierrors.IsNotFound(err) {
151151
return err
152152
}
153-
return r.Client.Create(context.TODO(), role)
153+
err = r.Client.Create(context.TODO(), role)
154+
if apierrors.IsAlreadyExists(err) {
155+
return r.Client.Update(context.TODO(), role)
156+
}
154157
}
155158

156159
if ownerutil.IsOwnedBy(existingRole, operatorCondition) &&
@@ -199,7 +202,10 @@ func (r *OperatorConditionReconciler) ensureOperatorConditionRoleBinding(operato
199202
if !apierrors.IsNotFound(err) {
200203
return err
201204
}
202-
return r.Client.Create(context.TODO(), roleBinding)
205+
err = r.Client.Create(context.TODO(), roleBinding)
206+
if apierrors.IsAlreadyExists(err) {
207+
return r.Client.Update(context.TODO(), roleBinding)
208+
}
203209
}
204210

205211
if ownerutil.IsOwnedBy(existingRoleBinding, operatorCondition) &&

Diff for: pkg/lib/operatorclient/apiservice.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"fmt"
66

7+
apierrors "k8s.io/apimachinery/pkg/api/errors"
78
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
89
"k8s.io/apimachinery/pkg/types"
910
"k8s.io/klog"
@@ -12,7 +13,11 @@ import (
1213

1314
// CreateAPIService creates the APIService.
1415
func (c *Client) CreateAPIService(ig *apiregistrationv1.APIService) (*apiregistrationv1.APIService, error) {
15-
return c.ApiregistrationV1Interface().ApiregistrationV1().APIServices().Create(context.TODO(), ig, metav1.CreateOptions{})
16+
createdAS, err := c.ApiregistrationV1Interface().ApiregistrationV1().APIServices().Create(context.TODO(), ig, metav1.CreateOptions{})
17+
if apierrors.IsAlreadyExists(err) {
18+
return c.UpdateAPIService(ig)
19+
}
20+
return createdAS, err
1621
}
1722

1823
// GetAPIService returns the existing APIService.

Diff for: pkg/lib/operatorclient/clusterrole.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,19 @@ import (
55
"fmt"
66

77
rbacv1 "k8s.io/api/rbac/v1"
8+
apierrors "k8s.io/apimachinery/pkg/api/errors"
89
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
910
"k8s.io/apimachinery/pkg/types"
1011
"k8s.io/klog"
1112
)
1213

1314
// CreateClusterRole creates the ClusterRole.
1415
func (c *Client) CreateClusterRole(r *rbacv1.ClusterRole) (*rbacv1.ClusterRole, error) {
15-
return c.RbacV1().ClusterRoles().Create(context.TODO(), r, metav1.CreateOptions{})
16+
createdClusterRole, err := c.RbacV1().ClusterRoles().Create(context.TODO(), r, metav1.CreateOptions{})
17+
if apierrors.IsAlreadyExists(err) {
18+
return c.UpdateClusterRole(r)
19+
}
20+
return createdClusterRole, err
1621
}
1722

1823
// GetClusterRole returns the existing ClusterRole.

Diff for: pkg/lib/operatorclient/clusterrolebinding.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66

77
rbacv1 "k8s.io/api/rbac/v1"
8+
apierrors "k8s.io/apimachinery/pkg/api/errors"
89
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
910
"k8s.io/apimachinery/pkg/types"
1011
acv1 "k8s.io/client-go/applyconfigurations/rbac/v1"
@@ -18,7 +19,11 @@ func (c *Client) ApplyClusterRoleBinding(applyConfig *acv1.ClusterRoleBindingApp
1819

1920
// CreateRoleBinding creates the roleBinding.
2021
func (c *Client) CreateClusterRoleBinding(ig *rbacv1.ClusterRoleBinding) (*rbacv1.ClusterRoleBinding, error) {
21-
return c.RbacV1().ClusterRoleBindings().Create(context.TODO(), ig, metav1.CreateOptions{})
22+
createdCRB, err := c.RbacV1().ClusterRoleBindings().Create(context.TODO(), ig, metav1.CreateOptions{})
23+
if apierrors.IsAlreadyExists(err) {
24+
return c.UpdateClusterRoleBinding(ig)
25+
}
26+
return createdCRB, err
2227
}
2328

2429
// GetRoleBinding returns the existing roleBinding.

Diff for: pkg/lib/operatorclient/configmap.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,19 @@ import (
55
"fmt"
66

77
corev1 "k8s.io/api/core/v1"
8+
apierrors "k8s.io/apimachinery/pkg/api/errors"
89
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
910
"k8s.io/apimachinery/pkg/types"
1011
"k8s.io/klog"
1112
)
1213

1314
// CreateConfigMap creates the ConfigMap.
1415
func (c *Client) CreateConfigMap(ig *corev1.ConfigMap) (*corev1.ConfigMap, error) {
15-
return c.CoreV1().ConfigMaps(ig.GetNamespace()).Create(context.TODO(), ig, metav1.CreateOptions{})
16+
createdCM, err := c.CoreV1().ConfigMaps(ig.GetNamespace()).Create(context.TODO(), ig, metav1.CreateOptions{})
17+
if apierrors.IsAlreadyExists(err) {
18+
return c.UpdateConfigMap(ig)
19+
}
20+
return createdCM, err
1621
}
1722

1823
// GetConfigMap returns the existing ConfigMap.

Diff for: pkg/lib/operatorclient/customresources.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"time"
1010

1111
"k8s.io/apimachinery/pkg/api/errors"
12+
apierrors "k8s.io/apimachinery/pkg/api/errors"
1213
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1314
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
1415
"k8s.io/apimachinery/pkg/util/wait"
@@ -104,7 +105,11 @@ func (c *Client) CreateCustomResourceRawIfNotFound(apiGroup, version, namespace,
104105
return false, err
105106
}
106107
err = c.CreateCustomResourceRaw(apiGroup, version, namespace, kind, data)
107-
if err != nil {
108+
if apierrors.IsAlreadyExists(err) {
109+
if err = c.UpdateCustomResourceRaw(apiGroup, version, namespace, kind, name, data); err != nil {
110+
return false, err
111+
}
112+
} else if err != nil {
108113
return false, err
109114
}
110115
return true, nil

Diff for: pkg/lib/operatorclient/deployment.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,12 @@ func (c *Client) GetDeployment(namespace, name string) (*appsv1.Deployment, erro
2828
// CreateDeployment creates the Deployment object.
2929
func (c *Client) CreateDeployment(dep *appsv1.Deployment) (*appsv1.Deployment, error) {
3030
klog.V(4).Infof("[CREATE Deployment]: %s:%s", dep.Namespace, dep.Name)
31-
return c.AppsV1().Deployments(dep.Namespace).Create(context.TODO(), dep, metav1.CreateOptions{})
31+
createdDep, err := c.AppsV1().Deployments(dep.Namespace).Create(context.TODO(), dep, metav1.CreateOptions{})
32+
if apierrors.IsAlreadyExists(err) {
33+
updatedDep, _, err := c.UpdateDeployment(dep)
34+
return updatedDep, err
35+
}
36+
return createdDep, err
3237
}
3338

3439
// DeleteDeployment deletes the Deployment object.

Diff for: pkg/lib/operatorclient/role.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,19 @@ import (
55
"fmt"
66

77
rbacv1 "k8s.io/api/rbac/v1"
8+
apierrors "k8s.io/apimachinery/pkg/api/errors"
89
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
910
"k8s.io/apimachinery/pkg/types"
1011
"k8s.io/klog"
1112
)
1213

1314
// CreateRole creates the role.
1415
func (c *Client) CreateRole(r *rbacv1.Role) (*rbacv1.Role, error) {
15-
return c.RbacV1().Roles(r.GetNamespace()).Create(context.TODO(), r, metav1.CreateOptions{})
16+
createdRole, err := c.RbacV1().Roles(r.GetNamespace()).Create(context.TODO(), r, metav1.CreateOptions{})
17+
if apierrors.IsAlreadyExists(err) {
18+
return c.UpdateRole(r)
19+
}
20+
return createdRole, err
1621
}
1722

1823
// GetRole returns the existing role.

Diff for: pkg/lib/operatorclient/rolebinding.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66

77
rbacv1 "k8s.io/api/rbac/v1"
8+
apierrors "k8s.io/apimachinery/pkg/api/errors"
89
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
910
"k8s.io/apimachinery/pkg/types"
1011
acv1 "k8s.io/client-go/applyconfigurations/rbac/v1"
@@ -18,7 +19,11 @@ func (c *Client) ApplyRoleBinding(applyConfig *acv1.RoleBindingApplyConfiguratio
1819

1920
// CreateRoleBinding creates the roleBinding.
2021
func (c *Client) CreateRoleBinding(ig *rbacv1.RoleBinding) (*rbacv1.RoleBinding, error) {
21-
return c.RbacV1().RoleBindings(ig.GetNamespace()).Create(context.TODO(), ig, metav1.CreateOptions{})
22+
createdRB, err := c.RbacV1().RoleBindings(ig.GetNamespace()).Create(context.TODO(), ig, metav1.CreateOptions{})
23+
if apierrors.IsAlreadyExists(err) {
24+
return c.UpdateRoleBinding(ig)
25+
}
26+
return createdRB, err
2227
}
2328

2429
// GetRoleBinding returns the existing roleBinding.

Diff for: pkg/lib/operatorclient/secret.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,19 @@ import (
55
"fmt"
66

77
v1 "k8s.io/api/core/v1"
8+
apierrors "k8s.io/apimachinery/pkg/api/errors"
89
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
910
"k8s.io/apimachinery/pkg/types"
1011
"k8s.io/klog"
1112
)
1213

1314
// CreateSecret creates the Secret.
1415
func (c *Client) CreateSecret(ig *v1.Secret) (*v1.Secret, error) {
15-
return c.CoreV1().Secrets(ig.GetNamespace()).Create(context.TODO(), ig, metav1.CreateOptions{})
16+
createdSecret, err := c.CoreV1().Secrets(ig.GetNamespace()).Create(context.TODO(), ig, metav1.CreateOptions{})
17+
if apierrors.IsAlreadyExists(err) {
18+
return c.UpdateSecret(ig)
19+
}
20+
return createdSecret, err
1621
}
1722

1823
// GetSecret returns the existing Secret.

Diff for: pkg/lib/operatorclient/service.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66

77
v1 "k8s.io/api/core/v1"
8+
apierrors "k8s.io/apimachinery/pkg/api/errors"
89
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
910
"k8s.io/apimachinery/pkg/types"
1011
acv1 "k8s.io/client-go/applyconfigurations/core/v1"
@@ -18,7 +19,11 @@ func (c *Client) ApplyService(applyConfig *acv1.ServiceApplyConfiguration, apply
1819

1920
// CreateService creates the Service.
2021
func (c *Client) CreateService(ig *v1.Service) (*v1.Service, error) {
21-
return c.CoreV1().Services(ig.GetNamespace()).Create(context.TODO(), ig, metav1.CreateOptions{})
22+
createdService, err := c.CoreV1().Services(ig.GetNamespace()).Create(context.TODO(), ig, metav1.CreateOptions{})
23+
if apierrors.IsAlreadyExists(err) {
24+
return c.UpdateService(ig)
25+
}
26+
return createdService, err
2227
}
2328

2429
// GetService returns the existing Service.

0 commit comments

Comments
 (0)