From 0d6c40c6413b90f62578874fe5559b932a2e687e Mon Sep 17 00:00:00 2001 From: Piyush Garg Date: Fri, 28 Jan 2022 14:10:30 +0530 Subject: [PATCH] Fix versioned clustertask getting deleted during upgrade This will fix the issue of versioned clustertask getting deleted during upgrade Now two installersets will be created for versioned and non version clustertask. There is new label getting added on versioned clustertask installerset having major and minor version details and the versioned clustertask installetset will only be deleted when there will be two of same minor and major version and installerset for latest operator version will be created. Eventually installerset will remain there of different operator minor version only ending in versioned clustertask to stay on cluster --- .../kubernetes/tektoninstallerset/const.go | 11 ++- pkg/reconciler/openshift/tektonaddon/const.go | 1 + .../openshift/tektonaddon/tektonaddon.go | 98 +++++++++++++++++-- 3 files changed, 99 insertions(+), 11 deletions(-) diff --git a/pkg/reconciler/kubernetes/tektoninstallerset/const.go b/pkg/reconciler/kubernetes/tektoninstallerset/const.go index fec53ec404..2bf1124691 100644 --- a/pkg/reconciler/kubernetes/tektoninstallerset/const.go +++ b/pkg/reconciler/kubernetes/tektoninstallerset/const.go @@ -17,9 +17,10 @@ limitations under the License. package tektoninstallerset const ( - LastAppliedHashKey = "operator.tekton.dev/last-applied-hash" - CreatedByKey = "operator.tekton.dev/created-by" - ReleaseVersionKey = "operator.tekton.dev/release-version" - TargetNamespaceKey = "operator.tekton.dev/target-namespace" - InstallerSetType = "operator.tekton.dev/type" + LastAppliedHashKey = "operator.tekton.dev/last-applied-hash" + CreatedByKey = "operator.tekton.dev/created-by" + ReleaseVersionKey = "operator.tekton.dev/release-version" + ReleaseMinorVersionKey = "operator.tekton.dev/release-minor-version" + TargetNamespaceKey = "operator.tekton.dev/target-namespace" + InstallerSetType = "operator.tekton.dev/type" ) diff --git a/pkg/reconciler/openshift/tektonaddon/const.go b/pkg/reconciler/openshift/tektonaddon/const.go index ab16071419..c82b9e19fb 100644 --- a/pkg/reconciler/openshift/tektonaddon/const.go +++ b/pkg/reconciler/openshift/tektonaddon/const.go @@ -18,6 +18,7 @@ package tektonaddon const ( ClusterTaskInstallerSet = "ClusterTask" + VersionedClusterTaskInstallerSet = "VersionedClusterTask" PipelinesTemplateInstallerSet = "PipelinesTemplate" TriggersResourcesInstallerSet = "TriggersResources" ConsoleCLIInstallerSet = "ConsoleCLI" diff --git a/pkg/reconciler/openshift/tektonaddon/tektonaddon.go b/pkg/reconciler/openshift/tektonaddon/tektonaddon.go index f5949a4f34..9fb2b9019e 100644 --- a/pkg/reconciler/openshift/tektonaddon/tektonaddon.go +++ b/pkg/reconciler/openshift/tektonaddon/tektonaddon.go @@ -35,6 +35,7 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "knative.dev/pkg/apis" "knative.dev/pkg/logging" pkgreconciler "knative.dev/pkg/reconciler" @@ -190,6 +191,35 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, ta *v1alpha1.TektonAddon return nil } + // If clusterTasks are enabled then create an InstallerSet + // with the versioned clustertask manifest + if ctVal == "true" { + + // here pass two labels one for type and other for minor release version to remove the previous minor release installerset only not all + exist, err := checkIfInstallerSetExist(ctx, r.operatorClientSet, r.version, + fmt.Sprintf("%s=%s,%s=%s", tektoninstallerset.InstallerSetType, VersionedClusterTaskInstallerSet, tektoninstallerset.ReleaseMinorVersionKey, getPatchVersionTrimmed(r.version)), + ) + if err != nil { + return err + } + + if !exist { + return r.ensureVersionedClusterTasks(ctx, ta) + } + } else { + // if disabled then delete the installer Set if exist + if err := r.deleteInstallerSet(ctx, + fmt.Sprintf("%s=%s", tektoninstallerset.InstallerSetType, VersionedClusterTaskInstallerSet)); err != nil { + return err + } + } + + // here pass two labels one for type and other for operator release version to get the latest installerset of current version + if err := r.checkComponentStatus(ctx, fmt.Sprintf("%s=%s,%s=%s", tektoninstallerset.InstallerSetType, VersionedClusterTaskInstallerSet, tektoninstallerset.ReleaseVersionKey, r.version)); err != nil { + ta.Status.MarkInstallerSetNotReady(err.Error()) + return nil + } + // If pipeline templates are enabled then create an InstallerSet // with their manifest if ptVal == "true" { @@ -319,6 +349,7 @@ func (r *Reconciler) ensurePipelineTemplates(ctx context.Context, ta *v1alpha1.T return nil } +// installerset for non versioned clustertask like buildah and community clustertask func (r *Reconciler) ensureClusterTasks(ctx context.Context, ta *v1alpha1.TektonAddon) error { clusterTaskManifest := r.manifest // Read clusterTasks from ko data @@ -330,8 +361,11 @@ func (r *Reconciler) ensureClusterTasks(ctx context.Context, ta *v1alpha1.Tekton return err } - communityClusterTaskManifest := r.manifest + clusterTaskManifest = clusterTaskManifest.Filter( + mf.Not(byContains(getFormattedVersion(r.version))), + ) + communityClusterTaskManifest := r.manifest if err := r.appendCommunityTarget(ctx, &communityClusterTaskManifest, ta); err != nil { // Continue if failed to resolve community task URL. // (Ex: on disconnected cluster community tasks won't be reachable because of proxy). @@ -351,6 +385,30 @@ func (r *Reconciler) ensureClusterTasks(ctx context.Context, ta *v1alpha1.Tekton return nil } +// installerset for versioned clustertask like buildah-1-6-0 +func (r *Reconciler) ensureVersionedClusterTasks(ctx context.Context, ta *v1alpha1.TektonAddon) error { + clusterTaskManifest := r.manifest + // Read clusterTasks from ko data + if err := applyAddons(&clusterTaskManifest, "02-clustertasks"); err != nil { + return err + } + // Run transformers + if err := r.addonTransform(ctx, &clusterTaskManifest, ta); err != nil { + return err + } + + clusterTaskManifest = clusterTaskManifest.Filter( + byContains(getFormattedVersion(r.version)), + ) + + if err := createInstallerSet(ctx, r.operatorClientSet, ta, clusterTaskManifest, + r.version, VersionedClusterTaskInstallerSet, "addon-versioned-clustertasks"); err != nil { + return err + } + + return nil +} + // checkIfInstallerSetExist checks if installer set exists for a component and return true/false based on it // and if installer set which already exist is of older version then it deletes and return false to create a new // installer set @@ -411,14 +469,20 @@ func createInstallerSet(ctx context.Context, oc clientset.Interface, ta *v1alpha func makeInstallerSet(ta *v1alpha1.TektonAddon, manifest mf.Manifest, prefix, releaseVersion, component, specHash string) *v1alpha1.TektonInstallerSet { ownerRef := *metav1.NewControllerRef(ta, ta.GetGroupVersionKind()) + labels := map[string]string{ + tektoninstallerset.CreatedByKey: CreatedByValue, + tektoninstallerset.InstallerSetType: component, + tektoninstallerset.ReleaseVersionKey: releaseVersion, + } + // special label to make sure no two versioned clustertask installerset exist + // for all patch releases + if component == VersionedClusterTaskInstallerSet { + labels[tektoninstallerset.ReleaseMinorVersionKey] = getPatchVersionTrimmed(releaseVersion) + } return &v1alpha1.TektonInstallerSet{ ObjectMeta: metav1.ObjectMeta{ GenerateName: fmt.Sprintf("%s-", prefix), - Labels: map[string]string{ - tektoninstallerset.CreatedByKey: CreatedByValue, - tektoninstallerset.InstallerSetType: component, - tektoninstallerset.ReleaseVersionKey: releaseVersion, - }, + Labels: labels, Annotations: map[string]string{ tektoninstallerset.TargetNamespaceKey: ta.Spec.TargetNamespace, tektoninstallerset.LastAppliedHashKey: specHash, @@ -500,3 +564,25 @@ func findValue(params []v1alpha1.Param, name string) (string, bool) { } return "", false } + +// byContains returns resources with specific string in name +func byContains(name string) mf.Predicate { + return func(u *unstructured.Unstructured) bool { + return strings.Contains(u.GetName(), name) + } +} + +// To get the version in the format as in clustertask name i.e. 1-6 +func getFormattedVersion(version string) string { + version = strings.TrimPrefix(getPatchVersionTrimmed(version), "v") + return strings.Replace(version, ".", "-", -1) +} + +// To get the minor major version for label i.e. v1.6 +func getPatchVersionTrimmed(version string) string { + endIndex := strings.LastIndex(version, ".") + if endIndex != -1 { + version = version[:endIndex] + } + return version +}