Fix conflict and cherry-pick (cherry-pick from #0e8c6d5) (#6413)

Fix conflict and cherry-pick (cherry-pick from #0e8c6d5)

Co-authored-by: inksnw <inksnw@gmail.com>
This commit is contained in:
KubeSphere CI Bot
2025-03-11 11:22:58 +08:00
committed by GitHub
parent bb4c67f624
commit c9c856dfda
5 changed files with 143 additions and 44 deletions

View File

@@ -94,7 +94,7 @@ func (r *AppReleaseReconciler) SetupWithManager(mgr *controller.Manager) error {
Watches(
&clusterv1alpha1.Cluster{},
handler.EnqueueRequestsFromMapFunc(r.mapper),
builder.WithPredicates(ClusterDeletePredicate{}),
builder.WithPredicates(DeletePredicate{}),
).
WithEventFilter(IgnoreAnnotationChangePredicate{AnnotationKey: appv2.TimeoutRecheck}).
For(&appv2.ApplicationRelease{}).Complete(r)

View File

@@ -1,31 +0,0 @@
/*
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
package application
import (
"sigs.k8s.io/controller-runtime/pkg/event"
"sigs.k8s.io/controller-runtime/pkg/predicate"
)
type ClusterDeletePredicate struct {
predicate.Funcs
}
func (ClusterDeletePredicate) Update(e event.UpdateEvent) bool {
return false
}
func (ClusterDeletePredicate) Create(_ event.CreateEvent) bool {
return false
}
func (ClusterDeletePredicate) Delete(_ event.DeleteEvent) bool {
return true
}
func (ClusterDeletePredicate) Generic(_ event.GenericEvent) bool {
return false
}

View File

@@ -0,0 +1,26 @@
package application
import (
"sigs.k8s.io/controller-runtime/pkg/event"
"sigs.k8s.io/controller-runtime/pkg/predicate"
)
type DeletePredicate struct {
predicate.Funcs
}
func (DeletePredicate) Update(e event.UpdateEvent) bool {
return false
}
func (DeletePredicate) Create(_ event.CreateEvent) bool {
return false
}
func (DeletePredicate) Delete(_ event.DeleteEvent) bool {
return true
}
func (DeletePredicate) Generic(_ event.GenericEvent) bool {
return false
}

View File

@@ -1,7 +1,18 @@
/*
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
Copyright 2023 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package application
@@ -13,6 +24,13 @@ import (
"strings"
"time"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
"kubesphere.io/api/constants"
tenantv1beta1 "kubesphere.io/api/tenant/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/handler"
"kubesphere.io/utils/s3"
clusterv1alpha1 "kubesphere.io/api/cluster/v1alpha1"
@@ -53,6 +71,22 @@ func (r *RepoReconciler) Enabled(clusterRole string) bool {
return strings.EqualFold(clusterRole, string(clusterv1alpha1.ClusterRoleHost))
}
func (r *RepoReconciler) mapper(ctx context.Context, o client.Object) (requests []reconcile.Request) {
workspace := o.(*tenantv1beta1.WorkspaceTemplate)
klog.Infof("workspace %s has been deleted", workspace.Name)
repoList := &appv2.RepoList{}
opts := &client.ListOptions{LabelSelector: labels.SelectorFromSet(labels.Set{constants.WorkspaceLabelKey: workspace.Name})}
if err := r.List(ctx, repoList, opts); err != nil {
klog.Errorf("failed to list repo: %v", err)
return requests
}
for _, repo := range repoList.Items {
requests = append(requests, reconcile.Request{NamespacedName: types.NamespacedName{Name: repo.Name}})
}
return requests
}
func (r *RepoReconciler) SetupWithManager(mgr *kscontroller.Manager) (err error) {
r.Client = mgr.GetClient()
r.recorder = mgr.GetEventRecorderFor(helmRepoController)
@@ -64,6 +98,11 @@ func (r *RepoReconciler) SetupWithManager(mgr *kscontroller.Manager) (err error)
}
return ctrl.NewControllerManagedBy(mgr).
Watches(
&tenantv1beta1.WorkspaceTemplate{},
handler.EnqueueRequestsFromMapFunc(r.mapper),
builder.WithPredicates(DeletePredicate{}),
).
For(&appv2.Repo{}).
Complete(r)
}
@@ -133,8 +172,23 @@ func (r *RepoReconciler) Reconcile(ctx context.Context, request reconcile.Reques
klog.Errorf("get helm repo failed, error: %s", err)
return reconcile.Result{}, client.IgnoreNotFound(err)
}
requeueAfter := time.Duration(helmRepo.Spec.SyncPeriod) * time.Second
workspaceTemplate := &tenantv1beta1.WorkspaceTemplate{}
workspaceName := helmRepo.Labels[constants.WorkspaceLabelKey]
if workspaceName != "" {
err := r.Get(ctx, types.NamespacedName{Name: workspaceName}, workspaceTemplate)
if apierrors.IsNotFound(err) || (err == nil && !workspaceTemplate.DeletionTimestamp.IsZero()) {
klog.Infof("workspace not found or deleting %s %s", workspaceName, err)
err = r.Delete(ctx, helmRepo)
if err != nil {
klog.Errorf("delete helm repo failed, error: %s", err)
return ctrl.Result{}, err
}
return ctrl.Result{}, nil
}
}
requeueAfter := time.Duration(helmRepo.Spec.SyncPeriod) * time.Second
noSync, err := r.noNeedSync(ctx, helmRepo)
if err != nil {
return reconcile.Result{}, err
@@ -156,6 +210,33 @@ func (r *RepoReconciler) Reconcile(ctx context.Context, request reconcile.Reques
klog.Errorf("load index failed, repo: %s, url: %s, err: %s", helmRepo.GetName(), helmRepo.Spec.Url, err)
return reconcile.Result{}, err
}
appList := &appv2.ApplicationList{}
opts := client.ListOptions{
LabelSelector: labels.SelectorFromSet(labels.Set{appv2.RepoIDLabelKey: helmRepo.Name}),
}
err = r.Client.List(ctx, appList, &opts)
if err != nil {
klog.Errorf("list appversion failed, error: %s", err)
return reconcile.Result{}, err
}
indexMap := make(map[string]struct{})
for appName := range index.Entries {
shortName := application.GenerateShortNameMD5Hash(appName)
key := fmt.Sprintf("%s-%s", helmRepo.Name, shortName)
indexMap[key] = struct{}{}
}
for _, i := range appList.Items {
if _, exists := indexMap[i.Name]; !exists {
klog.Infof("app %s has been removed from the repo", i.Name)
err = r.Client.Delete(ctx, &i)
if err != nil {
klog.Errorf("delete app %s failed, error: %s", i.Name, err)
return reconcile.Result{}, err
}
}
}
for appName, versions := range index.Entries {
if len(versions) == 0 {
klog.Infof("no version found for %s", appName)
@@ -163,20 +244,18 @@ func (r *RepoReconciler) Reconcile(ctx context.Context, request reconcile.Reques
}
versions = filterVersions(versions)
if len(versions) > appv2.MaxNumOfVersions {
versions = versions[:appv2.MaxNumOfVersions]
}
vRequests, err := repoParseRequest(r.Client, versions, helmRepo, appName)
if err != nil {
klog.Errorf("parse request failed, error: %s", err)
return reconcile.Result{}, err
}
klog.Infof("found %d/%d versions for %s need to upgrade", len(vRequests), len(versions), appName)
if len(vRequests) == 0 {
continue
}
klog.Infof("found %d/%d versions for %s need to upgrade", len(vRequests), len(versions), appName)
own := metav1.OwnerReference{
APIVersion: appv2.SchemeGroupVersion.String(),
Kind: "Repo",
@@ -204,8 +283,12 @@ func (r *RepoReconciler) Reconcile(ctx context.Context, request reconcile.Reques
func repoParseRequest(cli client.Client, versions helmrepo.ChartVersions, helmRepo *appv2.Repo, appName string) (result []application.AppRequest, err error) {
appVersionList := &appv2.ApplicationVersionList{}
appID := fmt.Sprintf("%s-%s", helmRepo.Name, application.GenerateShortNameMD5Hash(appName))
opts := client.ListOptions{
LabelSelector: labels.SelectorFromSet(labels.Set{appv2.RepoIDLabelKey: helmRepo.Name}),
LabelSelector: labels.SelectorFromSet(labels.Set{
appv2.RepoIDLabelKey: helmRepo.Name,
appv2.AppIDLabelKey: appID,
}),
}
err = cli.List(context.Background(), appVersionList, &opts)
if err != nil {
@@ -214,21 +297,43 @@ func repoParseRequest(cli client.Client, versions helmrepo.ChartVersions, helmRe
}
appVersionDigestMap := make(map[string]string)
versionMap := make(map[string]struct{})
for _, ver := range versions {
v := application.FormatVersion(ver.Version)
shortName := application.GenerateShortNameMD5Hash(ver.Name)
key := fmt.Sprintf("%s-%s-%s", helmRepo.Name, shortName, v)
versionMap[key] = struct{}{}
}
for _, i := range appVersionList.Items {
LegalVersion := application.FormatVersion(i.Spec.VersionName)
key := fmt.Sprintf("%s-%s", i.GetLabels()[appv2.AppIDLabelKey], LegalVersion)
appVersionDigestMap[key] = i.Spec.Digest
_, exists := versionMap[key]
if !exists {
klog.Infof("delete appversion %s", i.GetName())
err = cli.Delete(context.Background(), &i)
if err != nil {
klog.Errorf("delete appversion failed, error: %s", err)
return nil, err
}
} else {
appVersionDigestMap[key] = i.Spec.Digest
}
}
for _, ver := range versions {
legalVersion := application.FormatVersion(ver.Version)
shortName := application.GenerateShortNameMD5Hash(ver.Name)
key := fmt.Sprintf("%s-%s-%s", helmRepo.Name, shortName, legalVersion)
dig := appVersionDigestMap[key]
if dig == ver.Digest {
continue
} else {
}
if dig != "" {
klog.Infof("digest not match, key: %s, digest: %s, ver.Digest: %s", key, dig, ver.Digest)
}
vRequest := application.AppRequest{
RepoName: helmRepo.Name,
VersionName: ver.Version,

View File

@@ -576,7 +576,6 @@ func FormatVersion(input string) string {
}
hash := sha1.Sum([]byte(input))
formattedVersion := hex.EncodeToString(hash[:])[:12]
klog.Warningf("Version: %s does not meet the Kubernetes naming standard, replacing with SHA-1 hash: %s", input, formattedVersion)
return formattedVersion
}