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
8 changes: 8 additions & 0 deletions lib/resourceapply/apiext.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ func ApplyCustomResourceDefinition(client apiextclientv1beta1.CustomResourceDefi
if err != nil {
return nil, false, err
}
// if we only create this resource, we have no need to continue further
if IsCreateOnly(required) {
return nil, false, nil
}

modified := pointer.BoolPtr(false)
resourcemerge.EnsureCustomResourceDefinition(modified, existing, *required)
Expand All @@ -39,6 +43,10 @@ func ApplyCustomResourceDefinitionFromCache(lister apiextlistersv1beta1.CustomRe
if err != nil {
return nil, false, err
}
// if we only create this resource, we have no need to continue further
if IsCreateOnly(required) {
return nil, false, nil
}

existing = existing.DeepCopy()
modified := pointer.BoolPtr(false)
Expand Down
4 changes: 4 additions & 0 deletions lib/resourceapply/apireg.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ func ApplyAPIService(client apiregclientv1.APIServicesGetter, required *apiregv1
if err != nil {
return nil, false, err
}
// if we only create this resource, we have no need to continue further
if IsCreateOnly(required) {
return nil, false, nil
}

modified := pointer.BoolPtr(false)
resourcemerge.EnsureAPIService(modified, existing, *required)
Expand Down
16 changes: 16 additions & 0 deletions lib/resourceapply/apps.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ func ApplyDeployment(client appsclientv1.DeploymentsGetter, required *appsv1.Dep
if err != nil {
return nil, false, err
}
// if we only create this resource, we have no need to continue further
if IsCreateOnly(required) {
return nil, false, nil
}

modified := pointer.BoolPtr(false)
resourcemerge.EnsureDeployment(modified, existing, *required)
Expand All @@ -41,6 +45,10 @@ func ApplyDeploymentFromCache(lister appslisterv1.DeploymentLister, client appsc
if err != nil {
return nil, false, err
}
// if we only create this resource, we have no need to continue further
if IsCreateOnly(required) {
return nil, false, nil
}

existing = existing.DeepCopy()
modified := pointer.BoolPtr(false)
Expand All @@ -63,6 +71,10 @@ func ApplyDaemonSet(client appsclientv1.DaemonSetsGetter, required *appsv1.Daemo
if err != nil {
return nil, false, err
}
// if we only create this resource, we have no need to continue further
if IsCreateOnly(required) {
return nil, false, nil
}

modified := pointer.BoolPtr(false)
resourcemerge.EnsureDaemonSet(modified, existing, *required)
Expand All @@ -84,6 +96,10 @@ func ApplyDaemonSetFromCache(lister appslisterv1.DaemonSetLister, client appscli
if err != nil {
return nil, false, err
}
// if we only create this resource, we have no need to continue further
if IsCreateOnly(required) {
return nil, false, nil
}

existing = existing.DeepCopy()
modified := pointer.BoolPtr(false)
Expand Down
4 changes: 4 additions & 0 deletions lib/resourceapply/batch.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ func ApplyJob(client batchclientv1.JobsGetter, required *batchv1.Job) (*batchv1.
if err != nil {
return nil, false, err
}
// if we only create this resource, we have no need to continue further
if IsCreateOnly(required) {
return nil, false, nil
}

modified := pointer.BoolPtr(false)
resourcemerge.EnsureJob(modified, existing, *required)
Expand Down
16 changes: 16 additions & 0 deletions lib/resourceapply/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ func ApplyNamespace(client coreclientv1.NamespacesGetter, required *corev1.Names
if err != nil {
return nil, false, err
}
// if we only create this resource, we have no need to continue further
if IsCreateOnly(required) {
return nil, false, nil
}

modified := pointer.BoolPtr(false)
resourcemerge.EnsureObjectMeta(modified, &existing.ObjectMeta, required.ObjectMeta)
Expand All @@ -44,6 +48,10 @@ func ApplyService(client coreclientv1.ServicesGetter, required *corev1.Service)
if err != nil {
return nil, false, err
}
// if we only create this resource, we have no need to continue further
if IsCreateOnly(required) {
return nil, false, nil
}

modified := pointer.BoolPtr(false)
resourcemerge.EnsureObjectMeta(modified, &existing.ObjectMeta, required.ObjectMeta)
Expand All @@ -69,6 +77,10 @@ func ApplyServiceAccount(client coreclientv1.ServiceAccountsGetter, required *co
if err != nil {
return nil, false, err
}
// if we only create this resource, we have no need to continue further
if IsCreateOnly(required) {
return nil, false, nil
}

modified := pointer.BoolPtr(false)
resourcemerge.EnsureObjectMeta(modified, &existing.ObjectMeta, required.ObjectMeta)
Expand All @@ -90,6 +102,10 @@ func ApplyConfigMap(client coreclientv1.ConfigMapsGetter, required *corev1.Confi
if err != nil {
return nil, false, err
}
// if we only create this resource, we have no need to continue further
if IsCreateOnly(required) {
return nil, false, nil
}

modified := pointer.BoolPtr(false)
resourcemerge.EnsureConfigMap(modified, existing, *required)
Expand Down
8 changes: 8 additions & 0 deletions lib/resourceapply/cv.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ func ApplyClusterVersion(client configclientv1.ClusterVersionsGetter, required *
if err != nil {
return nil, false, err
}
// if we only create this resource, we have no need to continue further
if IsCreateOnly(required) {
return nil, false, nil
}

modified := pointer.BoolPtr(false)
resourcemerge.EnsureClusterVersion(modified, existing, *required)
Expand All @@ -39,6 +43,10 @@ func ApplyClusterVersionFromCache(lister configlistersv1.ClusterVersionLister, c
if err != nil {
return nil, false, err
}
// if we only create this resource, we have no need to continue further
if IsCreateOnly(required) {
return nil, false, nil
}

// Don't want to mutate cache.
existing := obj.DeepCopy()
Expand Down
18 changes: 18 additions & 0 deletions lib/resourceapply/interface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package resourceapply

import (
"strings"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// CreateOnlyAnnotation means that this resource should be created if it does not exist, but should not be updated
// if it already exists. It is uniformly respected across all resources, but the first known use-cases are for
// empty config.openshift.io and initial low-level operator resources.
// Set .metadata.annotations["release.openshift.io/create-only"]="true" to have a create-only resource.
const CreateOnlyAnnotation = "release.openshift.io/create-only"

// IsCreateOnly takes metadata and returns true if the resource should only be created, not updated.
func IsCreateOnly(metadata metav1.Object) bool {
return strings.EqualFold(metadata.GetAnnotations()[CreateOnlyAnnotation], "true")
}
16 changes: 16 additions & 0 deletions lib/resourceapply/rbac.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ func ApplyClusterRoleBinding(client rbacclientv1.ClusterRoleBindingsGetter, requ
if err != nil {
return nil, false, err
}
// if we only create this resource, we have no need to continue further
if IsCreateOnly(required) {
return nil, false, nil
}

modified := pointer.BoolPtr(false)
resourcemerge.EnsureClusterRoleBinding(modified, existing, *required)
Expand All @@ -40,6 +44,10 @@ func ApplyClusterRole(client rbacclientv1.ClusterRolesGetter, required *rbacv1.C
if err != nil {
return nil, false, err
}
// if we only create this resource, we have no need to continue further
if IsCreateOnly(required) {
return nil, false, nil
}

modified := pointer.BoolPtr(false)
resourcemerge.EnsureClusterRole(modified, existing, *required)
Expand All @@ -61,6 +69,10 @@ func ApplyRoleBinding(client rbacclientv1.RoleBindingsGetter, required *rbacv1.R
if err != nil {
return nil, false, err
}
// if we only create this resource, we have no need to continue further
if IsCreateOnly(required) {
return nil, false, nil
}

modified := pointer.BoolPtr(false)
resourcemerge.EnsureRoleBinding(modified, existing, *required)
Expand All @@ -82,6 +94,10 @@ func ApplyRole(client rbacclientv1.RolesGetter, required *rbacv1.Role) (*rbacv1.
if err != nil {
return nil, false, err
}
// if we only create this resource, we have no need to continue further
if IsCreateOnly(required) {
return nil, false, nil
}

modified := pointer.BoolPtr(false)
resourcemerge.EnsureRole(modified, existing, *required)
Expand Down
4 changes: 4 additions & 0 deletions lib/resourceapply/security.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ func ApplySecurityContextConstraints(client securityclientv1.SecurityContextCons
if err != nil {
return nil, false, err
}
// if we only create this resource, we have no need to continue further
if IsCreateOnly(required) {
return nil, false, nil
}

modified := pointer.BoolPtr(false)
resourcemerge.EnsureObjectMeta(modified, &existing.ObjectMeta, required.ObjectMeta)
Expand Down
6 changes: 6 additions & 0 deletions pkg/cvo/internal/generic.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"encoding/json"
"fmt"

"github.com/openshift/cluster-version-operator/lib/resourceapply"

apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
Expand Down Expand Up @@ -39,6 +41,10 @@ func applyUnstructured(client dynamic.ResourceInterface, required *unstructured.
if err != nil {
return nil, false, err
}
// if we only create this resource, we have no need to continue further
if resourceapply.IsCreateOnly(required) {
return nil, false, nil
}

existing.SetAnnotations(required.GetAnnotations())
existing.SetLabels(required.GetLabels())
Expand Down
84 changes: 84 additions & 0 deletions pkg/cvo/internal/generic_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package internal

import (
"testing"

"k8s.io/apimachinery/pkg/runtime/schema"

"k8s.io/apimachinery/pkg/runtime"

"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"

"k8s.io/client-go/dynamic/fake"
)

func TestCreateOnlyCreate(t *testing.T) {
feature := `{
"kind": "FeatureGate",
"apiVersion": "config.openshift.io/v1",
"metadata": {
"name": "cluster",
"annotations": {
"release.openshift.io/create-only": "true"
}
}
}`
obj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, []byte(feature))
if err != nil {
t.Fatal(err)
}

fakeClient := fake.NewSimpleDynamicClient(runtime.NewScheme())
_, modified, err := applyUnstructured(
fakeClient.Resource(schema.GroupVersionResource{Group: "config.openshift.io", Version: "v1", Resource: "featuregates"}),
obj.(*unstructured.Unstructured))
if err != nil {
t.Fatal(err)
}
if !modified {
t.Error("should have created")
}
}

func TestCreateOnlyUpdate(t *testing.T) {
feature := `{
"kind": "FeatureGate",
"apiVersion": "config.openshift.io/v1",
"metadata": {
"name": "cluster",
"annotations": {
"release.openshift.io/create-only": "true",
"change": "here"
}
}
}`
existing := `{
"kind": "FeatureGate",
"apiVersion": "config.openshift.io/v1",
"metadata": {
"name": "cluster",
"annotations": {
"release.openshift.io/create-only": "true"
}
}
}`
obj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, []byte(feature))
if err != nil {
t.Fatal(err)
}
existingObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, []byte(existing))
if err != nil {
t.Fatal(err)
}

fakeClient := fake.NewSimpleDynamicClient(runtime.NewScheme(), existingObj)
_, modified, err := applyUnstructured(
fakeClient.Resource(schema.GroupVersionResource{Group: "config.openshift.io", Version: "v1", Resource: "featuregates"}),
obj.(*unstructured.Unstructured))
if err != nil {
t.Fatal(err)
}
if modified {
t.Error("should not have updated")
}
}