gitjob/pkg/git/poll/handler.go

88 lines
2.4 KiB
Go

package poll
import (
"context"
"fmt"
"strings"
v1 "github.com/rancher/gitjob/pkg/apis/gitjob.cattle.io/v1"
"github.com/go-logr/logr"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
)
type Watcher interface {
StartBackgroundSync(ctx context.Context)
Finish()
Restart(ctx context.Context)
UpdateGitJob(gitJob v1.GitJob)
GetSyncInterval() int
}
// Handler handles all the watches for the git repositories. These watches are pulling the latest commit every syncPeriod.
type Handler struct {
client client.Client
watches map[string]Watcher
createWatch func(gitJob v1.GitJob, client client.Client) Watcher // this func creates a watch. It's a struct field, so it can be replaced for a mock in unit tests.
log logr.Logger
}
func NewHandler(client client.Client) *Handler {
return &Handler{
client: client,
watches: make(map[string]Watcher),
createWatch: NewWatch,
log: ctrl.Log.WithName("git-latest-commit-poll-handler"),
}
}
// AddOrModifyGitRepoWatch adds a new watch for the gitjob if no watch was already present.
// It updates the existing watch for this gitjob if present.
func (h *Handler) AddOrModifyGitRepoWatch(ctx context.Context, gitJob v1.GitJob) {
key := getKey(gitJob)
watch, found := h.watches[key]
if !found {
h.watches[key] = h.createWatch(gitJob, h.client)
h.watches[key].StartBackgroundSync(ctx)
} else {
oldSyncInterval := watch.GetSyncInterval()
watch.UpdateGitJob(gitJob)
if oldSyncInterval != gitJob.Spec.SyncInterval {
watch.Restart(ctx)
}
}
}
// CleanUpWatches removes all watches whose gitjob is not present in the cluster.
func (h *Handler) CleanUpWatches(ctx context.Context) {
var gitJob v1.GitJob
for key, watch := range h.watches {
namespacedName, err := getTypeNamespaceFromKey(key)
if err != nil {
h.log.Error(err, "can't get namespacedName", key)
}
if err = h.client.Get(ctx, namespacedName, &gitJob); errors.IsNotFound(err) {
watch.Finish()
delete(h.watches, key)
}
}
}
func getTypeNamespaceFromKey(key string) (types.NamespacedName, error) {
split := strings.Split(key, "-")
if len(split) < 2 {
return types.NamespacedName{}, fmt.Errorf("invalid key")
}
return types.NamespacedName{
Namespace: split[1],
Name: split[0],
}, nil
}
func getKey(gitJob v1.GitJob) string {
return gitJob.Name + "-" + gitJob.Namespace
}