diff --git a/e2e/fleet_attachedcluster_test.go b/e2e/fleet_attachedcluster_test.go index 4d06c223..5bb6cd69 100644 --- a/e2e/fleet_attachedcluster_test.go +++ b/e2e/fleet_attachedcluster_test.go @@ -59,7 +59,7 @@ var _ = ginkgo.Describe("[AttachedClusters] AttachedClusters testing", func() { ginkgo.It("Create Fleet", func() { // create fleet and checkout fleet status - fleetCreateErr := resources.CreateFleet(kuratorClient, fleet) + fleetCreateErr := resources.CreateOrUpdateFleet(kuratorClient, fleet) gomega.Expect(fleetCreateErr).ShouldNot(gomega.HaveOccurred()) resources.WaitFleetFitWith(kuratorClient, namespace, fleetname, func(fleet *fleetv1a1.Fleet) bool { return fleet.Status.Phase == fleetv1a1.ReadyPhase diff --git a/e2e/resources/attachedcluster.go b/e2e/resources/attachedcluster.go index 3a02eeda..b450c0bb 100644 --- a/e2e/resources/attachedcluster.go +++ b/e2e/resources/attachedcluster.go @@ -18,10 +18,13 @@ package resources import ( "context" + "encoding/json" + jsonpatch "github.com/evanphx/json-patch" "github.com/onsi/gomega" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" clusterv1a1 "kurator.dev/kurator/pkg/apis/cluster/v1alpha1" kurator "kurator.dev/kurator/pkg/client-go/generated/clientset/versioned" @@ -44,33 +47,29 @@ func NewAttachedCluster(namespace string, name string, config clusterv1a1.Secret } // CreateAttachedCluster create AttachedCluster. -func CreateAttachedCluster(client kurator.Interface, attachedCluster *clusterv1a1.AttachedCluster) error { - _, err := client.ClusterV1alpha1().AttachedClusters(attachedCluster.Namespace).Create(context.TODO(), attachedCluster, metav1.CreateOptions{}) - if err != nil { - if apierrors.IsAlreadyExists(err) { - return UpdateAttachedCluster(client, attachedCluster) +func CreateOrUpdateAttachedCluster(client kurator.Interface, attachedCluster *clusterv1a1.AttachedCluster) error { + _, createErr := client.ClusterV1alpha1().AttachedClusters(attachedCluster.GetNamespace()).Create(context.TODO(), attachedCluster, metav1.CreateOptions{}) + if createErr != nil { + if apierrors.IsAlreadyExists(createErr) { + originalAttachedCluster, getErr := client.ClusterV1alpha1().AttachedClusters(attachedCluster.GetNamespace()).Get(context.TODO(), attachedCluster.GetName(), metav1.GetOptions{}) + if getErr != nil { + return getErr + } + attachedClusterPatchData, createPatchErr := createAttachedClusterPatchData(originalAttachedCluster, attachedCluster) + if createPatchErr != nil { + return createPatchErr + } + _, patchErr := client.ClusterV1alpha1().AttachedClusters(attachedCluster.GetNamespace()).Patch(context.TODO(), attachedCluster.GetName(), types.MergePatchType, attachedClusterPatchData, metav1.PatchOptions{}) + if patchErr != nil { + return patchErr + } } else { - return err + return createErr } } return nil } -// UpdateAttachedCluster update AttachedCluster -func UpdateAttachedCluster(client kurator.Interface, attachedCluster *clusterv1a1.AttachedCluster) error { - attachedClusterPresentOnCluster, attacattachedClusterGetErr := client.ClusterV1alpha1().AttachedClusters(attachedCluster.Namespace).Get(context.TODO(), attachedCluster.Name, metav1.GetOptions{}) - if attacattachedClusterGetErr != nil { - return attacattachedClusterGetErr - } - DCattachedcluster := attachedClusterPresentOnCluster.DeepCopy() - DCattachedcluster.Spec = attachedCluster.Spec - _, err := client.ClusterV1alpha1().AttachedClusters(DCattachedcluster.Namespace).Update(context.TODO(), DCattachedcluster, metav1.UpdateOptions{}) - if err != nil { - return err - } - return nil -} - func RemoveAttachedCluster(client kurator.Interface, namespace, name string) error { err := client.ClusterV1alpha1().AttachedClusters(namespace).Delete(context.TODO(), name, metav1.DeleteOptions{}) if err != nil { @@ -93,3 +92,23 @@ func WaitAttachedClusterFitWith(client kurator.Interface, namespace, name string return fit(attachedClusterPresentOnCluster) }, pollTimeoutInHostCluster, pollIntervalInHostCluster).Should(gomega.Equal(true)) } + +func createAttachedClusterPatchData(originalAttachedCluster, modifiedAttachedCluster *clusterv1a1.AttachedCluster) ([]byte, error) { + originalData, originalErr := json.Marshal(originalAttachedCluster) + if originalErr != nil { + return nil, originalErr + } + modifiedData, modifiedErr := json.Marshal(modifiedAttachedCluster) + if modifiedErr != nil { + return nil, modifiedErr + } + diffPatchData, createErr := jsonpatch.CreateMergePatch(originalData, modifiedData) + if createErr != nil { + return nil, createErr + } + patchData, mergeErr := jsonpatch.MergePatch(originalData, diffPatchData) + if mergeErr != nil { + return nil, mergeErr + } + return patchData, nil +} diff --git a/e2e/resources/fleet.go b/e2e/resources/fleet.go index 8e82c79f..f09d805a 100644 --- a/e2e/resources/fleet.go +++ b/e2e/resources/fleet.go @@ -18,11 +18,14 @@ package resources import ( "context" + "encoding/json" + jsonpatch "github.com/evanphx/json-patch" "github.com/onsi/gomega" 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" fleetv1a1 "kurator.dev/kurator/pkg/apis/fleet/v1alpha1" kurator "kurator.dev/kurator/pkg/client-go/generated/clientset/versioned" @@ -46,33 +49,28 @@ func NewFleet(namespace string, name string, clusters []*corev1.ObjectReference) } // CreateAttachedCluster create AttachedCluster. -func CreateFleet(client kurator.Interface, fleet *fleetv1a1.Fleet) error { - _, err := client.FleetV1alpha1().Fleets(fleet.Namespace).Create(context.TODO(), fleet, metav1.CreateOptions{}) - if err != nil { - if apierrors.IsAlreadyExists(err) { - return UpdateFleet(client, fleet) +func CreateOrUpdateFleet(client kurator.Interface, fleet *fleetv1a1.Fleet) error { + _, createErr := client.FleetV1alpha1().Fleets(fleet.GetNamespace()).Create(context.TODO(), fleet, metav1.CreateOptions{}) + if createErr != nil { + if apierrors.IsAlreadyExists(createErr) { + originalFleet, getErr := client.FleetV1alpha1().Fleets(fleet.GetNamespace()).Get(context.TODO(), fleet.GetName(), metav1.GetOptions{}) + if getErr != nil { + return getErr + } + fleetPatchData, createPatchErr := createFleetPatchData(originalFleet, fleet) + if createPatchErr != nil { + return createPatchErr + } + if _, patchErr := client.FleetV1alpha1().Fleets(fleet.GetNamespace()).Patch(context.TODO(), fleet.GetName(), types.MergePatchType, fleetPatchData, metav1.PatchOptions{}); patchErr != nil { + return patchErr + } } else { - return err + return createErr } } return nil } -// UpdateAttachedCluster update AttachedCluster -func UpdateFleet(client kurator.Interface, fleet *fleetv1a1.Fleet) error { - fleetOnCluster, fleetGetErr := client.FleetV1alpha1().Fleets(fleet.Namespace).Get(context.TODO(), fleet.Name, metav1.GetOptions{}) - if fleetGetErr != nil { - return fleetGetErr - } - DCfleet := fleetOnCluster.DeepCopy() - DCfleet.Spec = fleet.Spec - _, err := client.FleetV1alpha1().Fleets(fleet.Namespace).Update(context.TODO(), DCfleet, metav1.UpdateOptions{}) - if err != nil { - return err - } - return nil -} - func RemoveFleet(client kurator.Interface, namespace, name string) error { err := client.FleetV1alpha1().Fleets(namespace).Delete(context.TODO(), name, metav1.DeleteOptions{}) if err != nil { @@ -95,3 +93,23 @@ func WaitFleetFitWith(client kurator.Interface, namespace, name string, fit func return fit(fleetPresentOnCluster) }, pollTimeoutInHostCluster, pollIntervalInHostCluster).Should(gomega.Equal(true)) } + +func createFleetPatchData(originalFleet, modifiedFleet *fleetv1a1.Fleet) ([]byte, error) { + originalData, originalErr := json.Marshal(originalFleet) + if originalErr != nil { + return nil, originalErr + } + modifiedData, modifiedErr := json.Marshal(modifiedFleet) + if modifiedErr != nil { + return nil, modifiedErr + } + diffPatchData, createErr := jsonpatch.CreateMergePatch(originalData, modifiedData) + if createErr != nil { + return nil, createErr + } + patchData, mergeErr := jsonpatch.MergePatch(originalData, diffPatchData) + if mergeErr != nil { + return nil, mergeErr + } + return patchData, nil +} diff --git a/e2e/resources/secret.go b/e2e/resources/secret.go index 78a69ee5..59f7a848 100644 --- a/e2e/resources/secret.go +++ b/e2e/resources/secret.go @@ -18,10 +18,13 @@ package resources import ( "context" + "encoding/json" + jsonpatch "github.com/evanphx/json-patch" 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/client-go/kubernetes" ) @@ -41,27 +44,29 @@ func NewSecret(namespace string, name string, data map[string][]byte) *corev1.Se } // CreateSecret create Secret. -func CreateSecret(client kubernetes.Interface, secret *corev1.Secret) error { - _, err := client.CoreV1().Secrets(secret.Namespace).Create(context.TODO(), secret, metav1.CreateOptions{}) - if err != nil { - if apierrors.IsAlreadyExists(err) { - return UpdateSecret(client, secret) +func CreateOrUpdateSecret(client kubernetes.Interface, secret *corev1.Secret) error { + _, createErr := client.CoreV1().Secrets(secret.GetNamespace()).Create(context.TODO(), secret, metav1.CreateOptions{}) + if createErr != nil { + if apierrors.IsAlreadyExists(createErr) { + originalSecret, getErr := client.CoreV1().Secrets(secret.GetNamespace()).Get(context.TODO(), secret.GetName(), metav1.GetOptions{}) + if getErr != nil { + return getErr + } + secretPatchData, createPatchErr := createSecretPatchData(originalSecret, secret) + if createPatchErr != nil { + return createPatchErr + } + _, patchErr := client.CoreV1().Secrets(secret.GetNamespace()).Patch(context.TODO(), secret.GetName(), types.MergePatchType, secretPatchData, metav1.PatchOptions{}) + if patchErr != nil { + return patchErr + } } else { - return err + return createErr } } return nil } -// UpdateSecret update Secret -func UpdateSecret(client kubernetes.Interface, secret *corev1.Secret) error { - _, err := client.CoreV1().Secrets(secret.Namespace).Update(context.TODO(), secret, metav1.UpdateOptions{}) - if err != nil { - return err - } - return nil -} - func RemoveSecret(client kubernetes.Interface, namespace, name string) error { err := client.CoreV1().Secrets(namespace).Delete(context.TODO(), name, metav1.DeleteOptions{}) if err != nil { @@ -73,3 +78,23 @@ func RemoveSecret(client kubernetes.Interface, namespace, name string) error { } return nil } + +func createSecretPatchData(originalSecret, modifiedSecret *corev1.Secret) ([]byte, error) { + originalData, originalErr := json.Marshal(originalSecret) + if originalErr != nil { + return nil, originalErr + } + modifiedData, modifiedErr := json.Marshal(modifiedSecret) + if modifiedErr != nil { + return nil, modifiedErr + } + diffPatchData, createErr := jsonpatch.CreateMergePatch(originalData, modifiedData) + if createErr != nil { + return nil, createErr + } + patchData, mergeErr := jsonpatch.MergePatch(originalData, diffPatchData) + if mergeErr != nil { + return nil, mergeErr + } + return patchData, nil +} diff --git a/e2e/suite_test.go b/e2e/suite_test.go index 982d21f1..1ae6a459 100644 --- a/e2e/suite_test.go +++ b/e2e/suite_test.go @@ -92,10 +92,10 @@ var _ = ginkgo.SynchronizedBeforeSuite(func() []byte { } attachedcluster = resources.NewAttachedCluster(namespace, memberClusterName, secretKeyRef) - secretCreateErr := resources.CreateSecret(kubeClient, secret) + secretCreateErr := resources.CreateOrUpdateSecret(kubeClient, secret) gomega.Expect(secretCreateErr).ShouldNot(gomega.HaveOccurred()) - attachedCreateErr := resources.CreateAttachedCluster(kuratorClient, attachedcluster) + attachedCreateErr := resources.CreateOrUpdateAttachedCluster(kuratorClient, attachedcluster) resources.WaitAttachedClusterFitWith(kuratorClient, namespace, memberClusterName, func(attachedCluster *clusterv1a1.AttachedCluster) bool { return attachedCluster.Status.Ready })