diff --git a/go.mod b/go.mod index e317e16e7b71a0697f97d9fe3ad80a604bc01930..a3a379d607090a551a891810165de9d8f096d01e 100644 --- a/go.mod +++ b/go.mod @@ -93,6 +93,7 @@ require ( k8s.io/klog/v2 v2.0.0 k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6 k8s.io/kubectl v0.18.6 + k8s.io/kubernetes v1.14.0 k8s.io/utils v0.0.0-20200603063816-c1c6865ac451 openpitrix.io/openpitrix v0.4.9-0.20200611125425-ae07f141e797 sigs.k8s.io/application v0.8.4-0.20201016185654-c8e2959e57a0 diff --git a/go.sum b/go.sum index 3199dd2a25a76f586b1931286e2bc833fd0ff645..5dfde1ecd0941cc2f936d19f303f70db6ef36f5d 100644 --- a/go.sum +++ b/go.sum @@ -770,6 +770,17 @@ k8s.io/kubectl v0.18.6/go.mod h1:3TLzFOrF9h4mlRPAvdNkDbs5NWspN4e0EnPnEB41CGo= k8s.io/metrics v0.18.6/go.mod h1:iAwGeabusQNO3duHDM7BBExTUB8L+iq8PM7N9EtQw6g= k8s.io/utils v0.0.0-20200603063816-c1c6865ac451 h1:v8ud2Up6QK1lNOKFgiIVrZdMg7MpmSnvtrOieolJKoE= k8s.io/utils v0.0.0-20200603063816-c1c6865ac451/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a h1:UcxjrRMyNx/i/y8G7kPvLyy7rfbeuf1PYyBf973pgyU= +k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= +k8s.io/kubectl v0.17.3 h1:9HHYj07kuFkM+sMJMOyQX29CKWq4lvKAG1UIPxNPMQ4= +k8s.io/kubectl v0.17.3/go.mod h1:NUn4IBY7f7yCMwSop2HCXlw/MVYP4HJBiUmOR3n9w28= +k8s.io/kubernetes v1.14.0 h1:6T2iAEoOYQnzQb3WvPlUkcczEEXZ7+YPlAO8olwujRw= +k8s.io/kubernetes v1.14.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= +k8s.io/metrics v0.17.3/go.mod h1:HEJGy1fhHOjHggW9rMDBJBD3YuGroH3Y1pnIRw9FFaI= +k8s.io/utils v0.0.0-20191114184206-e782cd3c129f h1:GiPwtSzdP43eI1hpPCbROQCCIgCuiMMNF8YUVLF3vJo= +k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= +kubesphere.io/application v1.0.0 h1:1H9HOb2OryNdrlUqrrhqtKC+IWmeE1rUsjrtcgKczEk= +kubesphere.io/application v1.0.0/go.mod h1:Mv+ht9RE/QNtITYCzRbt3XTIN6t6so6cInmiyg6wOIg= kubesphere.io/im v0.1.0 h1:Isu/WBOawUb4fzSlQeD1f6Vbq9pqFS0PmDg8v8iFYaY= kubesphere.io/im v0.1.0/go.mod h1:DHJj/JngMUFyaXecLjBPXj/zk5Oi7ifIixLRp0qJkyA= openpitrix.io/iam v0.1.0 h1:cb1mCusim7EGeoXEfuaVa1m7Co/pzim3keoxxKdv944= diff --git a/pkg/apis/devops/v1alpha3/pipeline_types.go b/pkg/apis/devops/v1alpha3/pipeline_types.go index 61478d2afafb35bfc32c29cc4abdaccf1342862a..25f4282baa7eb6ce2190e35dbf8ef017498894d5 100644 --- a/pkg/apis/devops/v1alpha3/pipeline_types.go +++ b/pkg/apis/devops/v1alpha3/pipeline_types.go @@ -30,6 +30,7 @@ const ( ResourceSingularPipeline = "pipeline" ResourcePluralPipeline = "pipelines" PipelinePrefix = "pipeline.devops.kubesphere.io/" + PipelineSpecHash = PipelinePrefix + "spechash" PipelineSyncStatusAnnoKey = PipelinePrefix + "syncstatus" PipelineSyncTimeAnnoKey = PipelinePrefix + "synctime" PipelineSyncMsgAnnoKey = PipelinePrefix + "syncmsg" diff --git a/pkg/controller/pipeline/pipeline_controller.go b/pkg/controller/pipeline/pipeline_controller.go index c176e707e9887a940ba8fb1567fd4545156ffcb9..a9df2efdefa94def1c0659ba64b0facace8314ac 100644 --- a/pkg/controller/pipeline/pipeline_controller.go +++ b/pkg/controller/pipeline/pipeline_controller.go @@ -20,9 +20,11 @@ import ( "context" "fmt" "github.com/emicklei/go-restful" + "hash/fnv" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/rand" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/wait" corev1informer "k8s.io/client-go/informers/core/v1" @@ -34,6 +36,7 @@ import ( "k8s.io/client-go/tools/record" "k8s.io/client-go/util/workqueue" "k8s.io/klog" + hashutil "k8s.io/kubernetes/pkg/util/hash" devopsv1alpha3 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha3" kubesphereclient "kubesphere.io/kubesphere/pkg/client/clientset/versioned" devopsinformers "kubesphere.io/kubesphere/pkg/client/informers/externalversions/devops/v1alpha3" @@ -229,9 +232,21 @@ func (c *Controller) syncHandler(key string) error { copyPipeline := pipeline.DeepCopy() // DeletionTimestamp.IsZero() means copyPipeline has not been deleted. if copyPipeline.ObjectMeta.DeletionTimestamp.IsZero() { + // make sure Annotations is not nil + if copyPipeline.Annotations == nil { + copyPipeline.Annotations = map[string]string{} + } + //If the sync is successful, return handle - if state, ok := pipeline.Annotations[devopsv1alpha3.PipelineSyncStatusAnnoKey]; ok && state == modelsdevops.StatusSuccessful { - return nil + if state, ok := copyPipeline.Annotations[devopsv1alpha3.PipelineSyncStatusAnnoKey]; ok && state == modelsdevops.StatusSuccessful { + specHash := computeHash(copyPipeline.Spec) + oldHash, _ := copyPipeline.Annotations[devopsv1alpha3.PipelineSpecHash] // don't need to check if it's nil, only compare if they're different + if specHash == oldHash { + // it was synced successfully, and there's any change with the Pipeline spec, skip this round + return nil + } else { + copyPipeline.Annotations[devopsv1alpha3.PipelineSpecHash] = specHash + } } // https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/#finalizers @@ -261,9 +276,6 @@ func (c *Controller) syncHandler(key string) error { } //If there is no early return, then the sync is successful. - if copyPipeline.Annotations == nil { - copyPipeline.Annotations = map[string]string{} - } copyPipeline.Annotations[devopsv1alpha3.PipelineSyncStatusAnnoKey] = modelsdevops.StatusSuccessful } else { // Finalizers processing logic @@ -306,6 +318,12 @@ func (c *Controller) syncHandler(key string) error { return nil } +func computeHash(obj interface{}) string { + hasher := fnv.New32a() + hashutil.DeepHashObject(hasher, obj) + return rand.SafeEncodeString(fmt.Sprint(hasher.Sum32())) +} + func isDevOpsProjectAdminNamespace(namespace *v1.Namespace) bool { _, ok := namespace.Labels[constants.DevOpsProjectLabelKey]