cloudfoundry/cf-k8s-controllers

View on GitHub
controllers/cleanup/build_cleaner.go

Summary

Maintainability
A
0 mins
Test Coverage
package cleanup

import (
    "context"
    "fmt"
    "sort"

    korifiv1alpha1 "code.cloudfoundry.org/korifi/controllers/api/v1alpha1"
    "code.cloudfoundry.org/korifi/statefulset-runner/controllers"
    "github.com/go-logr/logr"
    "k8s.io/apimachinery/pkg/api/meta"
    "k8s.io/apimachinery/pkg/types"
    "sigs.k8s.io/controller-runtime/pkg/client"
)

type BuildCleaner struct {
    k8sClient      client.Client
    retainedBuilds int
}

func NewBuildCleaner(k8sClient client.Client, retainedBuilds int) BuildCleaner {
    return BuildCleaner{k8sClient: k8sClient, retainedBuilds: retainedBuilds}
}

func (c BuildCleaner) Clean(ctx context.Context, app types.NamespacedName) error {
    log := logr.FromContextOrDiscard(ctx).WithName("BuildCleaner").WithValues("app", app)

    var cfApp korifiv1alpha1.CFApp
    err := c.k8sClient.Get(ctx, app, &cfApp)
    if err != nil {
        return err
    }

    var cfBuilds korifiv1alpha1.CFBuildList
    err = c.k8sClient.List(ctx, &cfBuilds,
        client.InNamespace(app.Namespace),
        client.MatchingLabels{
            controllers.LabelAppGUID: app.Name,
        },
    )
    if err != nil {
        return err
    }

    var deletableBuilds []korifiv1alpha1.CFBuild
    log.Info("processing builds", "count", len(cfBuilds.Items))
    for _, cfBuild := range cfBuilds.Items {
        if cfBuild.Name == cfApp.Spec.CurrentDropletRef.Name {
            continue
        }
        if !meta.IsStatusConditionTrue(cfBuild.Status.Conditions, korifiv1alpha1.SucceededConditionType) {
            continue
        }
        log.Info("found deletable build",
            "buildGUID", cfBuild.Name,
            "appCurrentDroplet", cfApp.Spec.CurrentDropletRef.Name,
            "succeedCondition", fmt.Sprintf("%v", meta.FindStatusCondition(cfBuild.Status.Conditions, korifiv1alpha1.SucceededConditionType)))
        deletableBuilds = append(deletableBuilds, cfBuild)
    }

    sort.Slice(deletableBuilds, func(i, j int) bool {
        return deletableBuilds[j].CreationTimestamp.Before(&deletableBuilds[i].CreationTimestamp)
    })

    for i := c.retainedBuilds; i < len(deletableBuilds); i++ {
        log.Info("deleting deletable build", "buildGUID", deletableBuilds[i].Name)
        err = c.k8sClient.Delete(ctx, &deletableBuilds[i])
        if err != nil {
            return err
        }
    }

    return nil
}