diff --git a/api/v1alpha1/component_types.go b/api/v1alpha1/component_types.go index f576cbc7..329e1508 100644 --- a/api/v1alpha1/component_types.go +++ b/api/v1alpha1/component_types.go @@ -35,7 +35,7 @@ type ComponentStatus struct { // DisplayName of the component that comes from the helm chart's latest annotation DisplayName string `json:"displayName,omitempty"` // versions contains all version of one component. - Versions []ComponentVersion `json:"versions"` + Versions []ComponentVersion `json:"versions,omitempty"` // FIXME: some fields(like description) may change when version update, how to deal with it? // A one-sentence description of the chart Description string `json:"description,omitempty"` diff --git a/config/crd/bases/core.kubebb.k8s.com.cn_components.yaml b/config/crd/bases/core.kubebb.k8s.com.cn_components.yaml index 1311ae97..ada22110 100644 --- a/config/crd/bases/core.kubebb.k8s.com.cn_components.yaml +++ b/config/crd/bases/core.kubebb.k8s.com.cn_components.yaml @@ -180,7 +180,6 @@ spec: required: - name - repository - - versions type: object type: object served: true diff --git a/controllers/component_controller.go b/controllers/component_controller.go index 92cf9cd5..0129f227 100644 --- a/controllers/component_controller.go +++ b/controllers/component_controller.go @@ -21,15 +21,18 @@ import ( "fmt" "reflect" "strings" + "sync" "time" "github.com/go-logr/logr" - "k8s.io/api/core/v1" + corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/client-go/tools/record" + "k8s.io/client-go/util/retry" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" @@ -83,6 +86,10 @@ func (r *ComponentReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( return reconcile.Result{}, nil } + if instance.Status.Deprecated { + return reconcile.Result{}, nil + } + done, err := r.UpdateComponent(ctx, logger, instance) if err != nil { return reconcile.Result{}, err @@ -153,21 +160,25 @@ func (r *ComponentReconciler) OnComponentUpdate(event event.UpdateEvent) bool { newObj := event.ObjectNew.(*corev1alpha1.Component) added, deleted, deprecated := corev1alpha1.ComponentVersionDiff(*oldObj, *newObj) if len(added) > 0 || len(deleted) > 0 || len(deprecated) > 0 { - r.Recorder.Event(newObj, v1.EventTypeNormal, "Update", + r.Recorder.Event(newObj, corev1.EventTypeNormal, "Update", fmt.Sprintf(corev1alpha1.UpdateEventMsgTemplate, newObj.GetName(), len(added), len(deleted), len(deprecated))) } + if len(deleted) > 0 { + logger, _ := logr.FromContext(context.Background()) + go r.DeleteComponentConfigMaps(context.TODO(), newObj.Name, newObj.Namespace, deleted, logger) + } return oldObj.ResourceVersion != newObj.ResourceVersion || !reflect.DeepEqual(oldObj.Status, newObj.Status) } func (r *ComponentReconciler) OnComponentCreate(event event.CreateEvent) bool { o := event.Object.(*corev1alpha1.Component) - r.Recorder.Event(o, v1.EventTypeNormal, "Create", fmt.Sprintf(corev1alpha1.AddEventMsgTemplate, o.GetName())) + r.Recorder.Event(o, corev1.EventTypeNormal, "Create", fmt.Sprintf(corev1alpha1.AddEventMsgTemplate, o.GetName())) return true } func (r *ComponentReconciler) OnComponentDel(event event.DeleteEvent) bool { o := event.Object.(*corev1alpha1.Component) - r.Recorder.Event(o, v1.EventTypeNormal, "Delete", fmt.Sprintf(corev1alpha1.DelEventMsgTemplate, o.GetName())) + r.Recorder.Event(o, corev1.EventTypeNormal, "Delete", fmt.Sprintf(corev1alpha1.DelEventMsgTemplate, o.GetName())) return true } @@ -230,3 +241,43 @@ func (r *ComponentReconciler) UpdateValuesConfigmap(ctx context.Context, logger } return nil } + +func (r *ComponentReconciler) DeleteComponentConfigMaps(ctx context.Context, name, namespace string, versions []string, logger logr.Logger) bool { + logger.Info(fmt.Sprintf("delete component %s/%s deleted versions..", namespace, name)) + + limit := make(chan struct{}, 5) + needReconcile := false + lock := make(chan struct{}, 1) + var wg sync.WaitGroup + for _, version := range versions { + wg.Add(1) + go func(versionStr string) { + defer wg.Done() + limit <- struct{}{} + defer func() { <-limit }() + cmName := corev1alpha1.GetComponentChartValuesConfigmapName(name, versionStr) + logger.Info(fmt.Sprintf("start to delete cm %s for component %s...", cmName, name)) + + cm := &corev1.ConfigMap{ + ObjectMeta: v1.ObjectMeta{ + Name: cmName, + Namespace: namespace, + }, + } + if err := retry.OnError(retry.DefaultBackoff, func(err error) bool { + return !errors.IsNotFound(err) + }, func() error { + return r.Client.Delete(ctx, cm) + }); err != nil { + logger.Error(err, fmt.Sprintf("delete cm %s for component %s failed.", cmName, name)) + lock <- struct{}{} + needReconcile = true + <-lock + } + }(version) + } + wg.Wait() + logger.Info(fmt.Sprintf("delete component %s/%s deleted versions done!!", namespace, name)) + + return needReconcile +} diff --git a/pkg/repository/http_watcher.go b/pkg/repository/http_watcher.go index 20d799ac..2426bbf5 100644 --- a/pkg/repository/http_watcher.go +++ b/pkg/repository/http_watcher.go @@ -318,6 +318,7 @@ func (c *HTTPWatcher) diff(indexFile *hrepo.IndexFile) ([3][]v1alpha1.Component, if !ok { c.logger.Info("should mark component as deleted", "Component.Name", key) component.Status.Deprecated = true + component.Status.Versions = nil delComponent = append(delComponent, component) continue }