2022-11-14 12:00:40 +01:00
|
|
|
package main
|
|
|
|
|
2022-11-14 18:30:12 +01:00
|
|
|
import (
|
2022-12-12 19:39:29 +01:00
|
|
|
"context"
|
|
|
|
"errors"
|
2022-12-07 11:30:47 +01:00
|
|
|
"flag"
|
2022-11-14 18:30:12 +01:00
|
|
|
"os"
|
2022-11-25 15:29:45 +05:30
|
|
|
"sync"
|
2022-11-14 18:30:12 +01:00
|
|
|
"time"
|
|
|
|
|
2022-12-07 11:30:47 +01:00
|
|
|
admissionhandlers "github.com/kyverno/kyverno/cmd/cleanup-controller/handlers/admission"
|
|
|
|
cleanuphandlers "github.com/kyverno/kyverno/cmd/cleanup-controller/handlers/cleanup"
|
2022-11-18 15:21:15 +01:00
|
|
|
"github.com/kyverno/kyverno/cmd/internal"
|
2022-11-25 15:29:45 +05:30
|
|
|
kyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions"
|
2022-11-22 14:37:27 +01:00
|
|
|
dynamicclient "github.com/kyverno/kyverno/pkg/clients/dynamic"
|
2022-11-21 18:16:25 +01:00
|
|
|
kubeclient "github.com/kyverno/kyverno/pkg/clients/kube"
|
2022-11-25 15:29:45 +05:30
|
|
|
kyvernoclient "github.com/kyverno/kyverno/pkg/clients/kyverno"
|
2022-11-14 18:30:12 +01:00
|
|
|
"github.com/kyverno/kyverno/pkg/config"
|
2022-11-25 15:29:45 +05:30
|
|
|
"github.com/kyverno/kyverno/pkg/controllers/cleanup"
|
2022-12-12 19:39:29 +01:00
|
|
|
"github.com/kyverno/kyverno/pkg/leaderelection"
|
2022-11-16 18:41:33 +05:30
|
|
|
"github.com/kyverno/kyverno/pkg/metrics"
|
2022-12-12 19:39:29 +01:00
|
|
|
"github.com/kyverno/kyverno/pkg/tls"
|
2022-12-09 18:12:37 +01:00
|
|
|
"github.com/kyverno/kyverno/pkg/webhooks"
|
2022-11-14 18:30:12 +01:00
|
|
|
corev1 "k8s.io/api/core/v1"
|
|
|
|
kubeinformers "k8s.io/client-go/informers"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
2022-11-18 15:21:15 +01:00
|
|
|
resyncPeriod = 15 * time.Minute
|
2022-11-14 18:30:12 +01:00
|
|
|
)
|
|
|
|
|
2022-12-09 18:12:37 +01:00
|
|
|
// TODO:
|
2022-12-12 19:39:29 +01:00
|
|
|
// - helm review labels / selectors
|
2022-12-09 18:12:37 +01:00
|
|
|
// - implement probes
|
|
|
|
// - better certs management
|
|
|
|
// - supports certs in cronjob
|
|
|
|
|
|
|
|
type probes struct{}
|
|
|
|
|
|
|
|
func (probes) IsReady() bool {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func (probes) IsLive() bool {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2022-11-14 12:00:40 +01:00
|
|
|
func main() {
|
2022-12-09 18:12:37 +01:00
|
|
|
var (
|
2022-12-12 19:39:29 +01:00
|
|
|
leaderElectionRetryPeriod time.Duration
|
|
|
|
dumpPayload bool
|
2022-12-09 18:12:37 +01:00
|
|
|
)
|
2022-12-07 11:30:47 +01:00
|
|
|
flagset := flag.NewFlagSet("cleanup-controller", flag.ExitOnError)
|
2022-12-09 18:12:37 +01:00
|
|
|
flagset.BoolVar(&dumpPayload, "dumpPayload", false, "Set this flag to activate/deactivate debug mode.")
|
2022-12-12 19:39:29 +01:00
|
|
|
flagset.DurationVar(&leaderElectionRetryPeriod, "leaderElectionRetryPeriod", leaderelection.DefaultRetryPeriod, "Configure leader election retry period.")
|
2022-11-18 15:21:15 +01:00
|
|
|
// config
|
2022-11-23 11:36:15 +01:00
|
|
|
appConfig := internal.NewConfiguration(
|
|
|
|
internal.WithProfiling(),
|
2022-11-29 10:16:07 +01:00
|
|
|
internal.WithMetrics(),
|
2022-11-23 11:36:15 +01:00
|
|
|
internal.WithTracing(),
|
|
|
|
internal.WithKubeconfig(),
|
2022-12-07 11:30:47 +01:00
|
|
|
internal.WithFlagSets(flagset),
|
2022-11-23 11:36:15 +01:00
|
|
|
)
|
2022-11-14 18:30:12 +01:00
|
|
|
// parse flags
|
2022-11-24 20:57:01 +01:00
|
|
|
internal.ParseFlags(appConfig)
|
2022-11-14 18:30:12 +01:00
|
|
|
// setup logger
|
2022-11-18 15:21:15 +01:00
|
|
|
// show version
|
|
|
|
// start profiling
|
2022-11-24 20:57:01 +01:00
|
|
|
// setup signals
|
|
|
|
// setup maxprocs
|
2022-11-17 17:01:30 +01:00
|
|
|
// setup metrics
|
2022-11-29 10:16:07 +01:00
|
|
|
ctx, logger, metricsConfig, sdown := internal.Setup()
|
|
|
|
defer sdown()
|
2022-11-17 17:01:30 +01:00
|
|
|
// create instrumented clients
|
2022-11-23 11:36:15 +01:00
|
|
|
kubeClient := internal.CreateKubernetesClient(logger, kubeclient.WithMetrics(metricsConfig, metrics.KubeClient), kubeclient.WithTracing())
|
2022-12-12 19:39:29 +01:00
|
|
|
leaderElectionClient := internal.CreateKubernetesClient(logger, kubeclient.WithMetrics(metricsConfig, metrics.KubeClient), kubeclient.WithTracing())
|
2022-11-29 10:16:07 +01:00
|
|
|
kyvernoClient := internal.CreateKyvernoClient(logger, kyvernoclient.WithMetrics(metricsConfig, metrics.KubeClient), kyvernoclient.WithTracing())
|
2022-12-12 19:39:29 +01:00
|
|
|
// setup leader election
|
|
|
|
le, err := leaderelection.New(
|
|
|
|
logger.WithName("leader-election"),
|
|
|
|
"kyverno-cleanup-controller",
|
|
|
|
config.KyvernoNamespace(),
|
|
|
|
leaderElectionClient,
|
|
|
|
config.KyvernoPodName(),
|
|
|
|
leaderElectionRetryPeriod,
|
|
|
|
func(ctx context.Context) {
|
|
|
|
logger := logger.WithName("leader")
|
|
|
|
// informer factories
|
|
|
|
kubeInformer := kubeinformers.NewSharedInformerFactoryWithOptions(kubeClient, resyncPeriod)
|
|
|
|
kyvernoInformer := kyvernoinformer.NewSharedInformerFactory(kyvernoClient, resyncPeriod)
|
|
|
|
// controllers
|
|
|
|
controller := internal.NewController(
|
|
|
|
cleanup.ControllerName,
|
|
|
|
cleanup.NewController(
|
|
|
|
kubeClient,
|
|
|
|
kyvernoInformer.Kyverno().V2alpha1().ClusterCleanupPolicies(),
|
|
|
|
kyvernoInformer.Kyverno().V2alpha1().CleanupPolicies(),
|
|
|
|
kubeInformer.Batch().V1().CronJobs(),
|
|
|
|
"https://"+config.KyvernoServiceName()+"."+config.KyvernoNamespace()+".svc",
|
|
|
|
),
|
|
|
|
cleanup.Workers,
|
|
|
|
)
|
|
|
|
// start informers and wait for cache sync
|
|
|
|
if !internal.StartInformersAndWaitForCacheSync(ctx, kyvernoInformer, kubeInformer) {
|
|
|
|
logger.Error(errors.New("failed to wait for cache sync"), "failed to wait for cache sync")
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
// start leader controllers
|
|
|
|
var wg sync.WaitGroup
|
|
|
|
controller.Run(ctx, logger.WithName("cleanup-controller"), &wg)
|
|
|
|
// wait all controllers shut down
|
|
|
|
wg.Wait()
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
logger.Error(err, "failed to initialize leader election")
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
dynamicClient := internal.CreateDynamicClient(logger, dynamicclient.WithMetrics(metricsConfig, metrics.KyvernoClient), dynamicclient.WithTracing())
|
2022-11-29 10:16:07 +01:00
|
|
|
dClient := internal.CreateDClient(logger, ctx, dynamicClient, kubeClient, 15*time.Minute)
|
|
|
|
// informer factories
|
2022-11-25 15:29:45 +05:30
|
|
|
kubeInformer := kubeinformers.NewSharedInformerFactoryWithOptions(kubeClient, resyncPeriod)
|
2022-11-17 17:01:30 +01:00
|
|
|
kubeKyvernoInformer := kubeinformers.NewSharedInformerFactoryWithOptions(kubeClient, resyncPeriod, kubeinformers.WithNamespace(config.KyvernoNamespace()))
|
2022-11-25 15:29:45 +05:30
|
|
|
kyvernoInformer := kyvernoinformer.NewSharedInformerFactory(kyvernoClient, resyncPeriod)
|
2022-12-12 19:39:29 +01:00
|
|
|
// listers
|
|
|
|
secretLister := kubeKyvernoInformer.Core().V1().Secrets().Lister().Secrets(config.KyvernoNamespace())
|
2022-12-08 12:45:47 +01:00
|
|
|
cpolLister := kyvernoInformer.Kyverno().V2alpha1().ClusterCleanupPolicies().Lister()
|
|
|
|
polLister := kyvernoInformer.Kyverno().V2alpha1().CleanupPolicies().Lister()
|
2022-12-08 11:31:28 +01:00
|
|
|
nsLister := kubeInformer.Core().V1().Namespaces().Lister()
|
2022-11-16 18:41:33 +05:30
|
|
|
// start informers and wait for cache sync
|
2022-11-29 10:16:07 +01:00
|
|
|
if !internal.StartInformersAndWaitForCacheSync(ctx, kubeKyvernoInformer, kubeInformer, kyvernoInformer) {
|
2022-11-16 18:41:33 +05:30
|
|
|
os.Exit(1)
|
|
|
|
}
|
2022-12-07 11:30:47 +01:00
|
|
|
// create handlers
|
|
|
|
admissionHandlers := admissionhandlers.New(dClient)
|
2022-12-08 11:31:28 +01:00
|
|
|
cleanupHandlers := cleanuphandlers.New(dClient, cpolLister, polLister, nsLister)
|
2022-12-07 11:30:47 +01:00
|
|
|
// create server
|
2022-11-14 18:30:12 +01:00
|
|
|
server := NewServer(
|
|
|
|
func() ([]byte, []byte, error) {
|
2022-12-12 19:39:29 +01:00
|
|
|
secret, err := secretLister.Get(tls.GenerateTLSPairSecretName())
|
2022-11-14 18:30:12 +01:00
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
return secret.Data[corev1.TLSCertKey], secret.Data[corev1.TLSPrivateKeyKey], nil
|
|
|
|
},
|
2022-12-07 11:30:47 +01:00
|
|
|
admissionHandlers.Validate,
|
|
|
|
cleanupHandlers.Cleanup,
|
2022-12-09 18:12:37 +01:00
|
|
|
metricsConfig,
|
|
|
|
webhooks.DebugModeOptions{
|
|
|
|
DumpPayload: dumpPayload,
|
|
|
|
},
|
|
|
|
probes{},
|
2022-11-14 18:30:12 +01:00
|
|
|
)
|
2022-12-07 11:30:47 +01:00
|
|
|
// start server
|
2022-11-24 20:57:01 +01:00
|
|
|
server.Run(ctx.Done())
|
2022-12-12 19:39:29 +01:00
|
|
|
// wait for termination signal and run leader election loop
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-ctx.Done():
|
|
|
|
return
|
|
|
|
default:
|
|
|
|
le.Run(ctx)
|
|
|
|
}
|
|
|
|
}
|
2022-11-14 12:00:40 +01:00
|
|
|
}
|