Update cainjector inejctable setup
To work with latest controller runtime Signed-off-by: irbekrm <irbekrm@gmail.com>
This commit is contained in:
parent
b52ed6303d
commit
3d1134a975
@ -26,21 +26,42 @@ import (
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/handler"
|
||||
|
||||
cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
|
||||
)
|
||||
|
||||
// setup for indexers used to trigger reconciliation on injected CA data.
|
||||
const (
|
||||
// injectFromPath is the index key used to look up the value of inject-ca-from on targeted objects
|
||||
injectFromPath = ".metadata.annotations.inject-ca-from"
|
||||
|
||||
// certificateToInjectableFunc converts a given certificate to the reconcile requests for the corresponding injectables
|
||||
// (webhooks, api services, etc) that reference it.
|
||||
type certificateToInjectableFunc func(log logr.Logger, cl client.Reader, certName types.NamespacedName) []ctrl.Request
|
||||
// injectFromSecretPath is the index key used to look up the value of
|
||||
// inject-ca-from-secret on targeted objects
|
||||
injectFromSecretPath = ".metadata.annotations.inject-ca-from-secret"
|
||||
)
|
||||
|
||||
// buildCertToInjectableFunc creates a certificateToInjectableFunc that maps from certificates to the given type of injectable.
|
||||
func buildCertToInjectableFunc(listTyp runtime.Object, resourceName string) certificateToInjectableFunc {
|
||||
return func(log logr.Logger, cl client.Reader, certName types.NamespacedName) []ctrl.Request {
|
||||
log = log.WithValues("type", resourceName)
|
||||
objs := listTyp.DeepCopyObject().(client.ObjectList)
|
||||
// certFromSecretToInjectableMapFuncBuilder returns a handler.MapFunc that, for
|
||||
// a Secret change, ensures that if this Secret is a Certificate Secret of
|
||||
// Certificate that is configured as a CA source for an injectable via
|
||||
// inject-ca-from annotation, a reconcile loop will be triggered for this
|
||||
// injectable
|
||||
func certFromSecretToInjectableMapFuncBuilder(cl client.Reader, log logr.Logger, config setup) handler.MapFunc {
|
||||
return func(ctx context.Context, obj client.Object) []ctrl.Request {
|
||||
secretName := types.NamespacedName{Name: obj.GetName(), Namespace: obj.GetNamespace()}
|
||||
certName := owningCertForSecret(obj.(*corev1.Secret))
|
||||
if certName == nil {
|
||||
return nil
|
||||
}
|
||||
log = log.WithValues("type", config.resourceName, "secret", secretName, "certificate", *certName)
|
||||
|
||||
var cert cmapi.Certificate
|
||||
// confirm that a service owns this cert
|
||||
if err := cl.Get(context.Background(), *certName, &cert); err != nil {
|
||||
// TODO(directxman12): check for not found error?
|
||||
log.Error(err, "unable to fetch certificate that owns the secret")
|
||||
return nil
|
||||
}
|
||||
objs := config.listType.DeepCopyObject().(client.ObjectList)
|
||||
if err := cl.List(context.Background(), objs, client.MatchingFields{injectFromPath: certName.String()}); err != nil {
|
||||
log.Error(err, "unable to fetch injectables associated with certificate")
|
||||
return nil
|
||||
@ -68,82 +89,52 @@ func buildCertToInjectableFunc(listTyp runtime.Object, resourceName string) cert
|
||||
}
|
||||
}
|
||||
|
||||
// secretForCertificateMapper is a Mapper that converts secrets up to injectables, through certificates.
|
||||
type secretForCertificateMapper struct {
|
||||
Client client.Reader
|
||||
log logr.Logger
|
||||
certificateToInjectable certificateToInjectableFunc
|
||||
// certFromSecretToInjectableMapFuncBuilder returns a handler.MapFunc that, for
|
||||
// a Certificate change, ensures that if this Certificate that is configured as
|
||||
// a CA source for an injectable via inject-ca-from annotation, a reconcile loop
|
||||
// will be triggered for this injectable
|
||||
func certToInjectableMapFuncBuilder(cl client.Reader, log logr.Logger, config setup) handler.MapFunc {
|
||||
return func(ctx context.Context, obj client.Object) []ctrl.Request {
|
||||
certName := types.NamespacedName{Namespace: obj.GetNamespace(), Name: obj.GetName()}
|
||||
log = log.WithValues("type", config.resourceName, "certificate", certName)
|
||||
objs := config.listType.DeepCopyObject().(client.ObjectList)
|
||||
if err := cl.List(context.Background(), objs, client.MatchingFields{injectFromPath: certName.String()}); err != nil {
|
||||
log.Error(err, "unable to fetch injectables associated with certificate")
|
||||
return nil
|
||||
}
|
||||
|
||||
var reqs []ctrl.Request
|
||||
if err := meta.EachListItem(objs, func(obj runtime.Object) error {
|
||||
metaInfo, err := meta.Accessor(obj)
|
||||
if err != nil {
|
||||
log.Error(err, "unable to get metadata from list item")
|
||||
// continue on error
|
||||
return nil
|
||||
}
|
||||
reqs = append(reqs, ctrl.Request{NamespacedName: types.NamespacedName{
|
||||
Name: metaInfo.GetName(),
|
||||
Namespace: metaInfo.GetNamespace(),
|
||||
}})
|
||||
return nil
|
||||
}); err != nil {
|
||||
log.Error(err, "unable get items from list")
|
||||
return nil
|
||||
}
|
||||
|
||||
return reqs
|
||||
}
|
||||
}
|
||||
|
||||
func (m *secretForCertificateMapper) Map(obj client.Object) []ctrl.Request {
|
||||
// grab the certificate, if it exists
|
||||
certName := owningCertForSecret(obj.(*corev1.Secret))
|
||||
if certName == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
secretName := types.NamespacedName{Name: obj.GetName(), Namespace: obj.GetNamespace()}
|
||||
log := m.log.WithValues("secret", secretName, "certificate", *certName)
|
||||
|
||||
var cert cmapi.Certificate
|
||||
// confirm that a service owns this cert
|
||||
if err := m.Client.Get(context.Background(), *certName, &cert); err != nil {
|
||||
// TODO(directxman12): check for not found error?
|
||||
log.Error(err, "unable to fetch certificate that owns the secret")
|
||||
return nil
|
||||
}
|
||||
|
||||
return m.certificateToInjectable(log, m.Client, *certName)
|
||||
}
|
||||
|
||||
// certMapper is a mapper that converts Certificates up to injectables
|
||||
type certMapper struct {
|
||||
Client client.Reader
|
||||
log logr.Logger
|
||||
toInjectable certificateToInjectableFunc
|
||||
}
|
||||
|
||||
func (m *certMapper) Map(obj client.Object) []ctrl.Request {
|
||||
certName := types.NamespacedName{Name: obj.GetName(), Namespace: obj.GetNamespace()}
|
||||
log := m.log.WithValues("certificate", certName)
|
||||
return m.toInjectable(log, m.Client, certName)
|
||||
}
|
||||
|
||||
var (
|
||||
// injectFromPath is the index key used to look up the value of inject-ca-from on targeted objects
|
||||
injectFromPath = ".metadata.annotations.inject-ca-from"
|
||||
)
|
||||
|
||||
// injectableCAFromIndexer is an IndexerFunc indexing on certificates
|
||||
// referenced by injectables.
|
||||
func injectableCAFromIndexer(rawObj client.Object) []string {
|
||||
metaInfo, err := meta.Accessor(rawObj)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// skip invalid certificate names
|
||||
certNameRaw := metaInfo.GetAnnotations()[cmapi.WantInjectAnnotation]
|
||||
if certNameRaw == "" {
|
||||
return nil
|
||||
}
|
||||
certName := splitNamespacedName(certNameRaw)
|
||||
if certName.Namespace == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
return []string{certNameRaw}
|
||||
}
|
||||
|
||||
// secretToInjectableFunc converts a given certificate to the reconcile requests for the corresponding injectables
|
||||
// (webhooks, api services, etc) that reference it.
|
||||
type secretToInjectableFunc func(log logr.Logger, cl client.Reader, certName types.NamespacedName) []ctrl.Request
|
||||
|
||||
// buildSecretToInjectableFunc creates a certificateToInjectableFunc that maps from secrets to the given type of injectable.
|
||||
func buildSecretToInjectableFunc(listTyp runtime.Object, resourceName string) secretToInjectableFunc {
|
||||
return func(log logr.Logger, cl client.Reader, secretName types.NamespacedName) []ctrl.Request {
|
||||
log = log.WithValues("type", resourceName)
|
||||
objs := listTyp.DeepCopyObject().(client.ObjectList)
|
||||
// secretForInjectableMapFuncBuilder returns a handler.MapFunc that, for a
|
||||
// config for particular injectable type (i.e CRD, APIService) and a Secret,
|
||||
// returns all injectables that have the inject-ca-from-secret annotion with the
|
||||
// given secret name. This will be used in an event handler to ensure that
|
||||
// changes to a Secret triggers a reconcile loop for the relevant injectable.
|
||||
func secretForInjectableMapFuncBuilder(cl client.Reader, log logr.Logger, config setup) handler.MapFunc {
|
||||
return func(ctx context.Context, obj client.Object) []ctrl.Request {
|
||||
secretName := types.NamespacedName{Namespace: obj.GetNamespace(), Name: obj.GetName()}
|
||||
log = log.WithValues("type", config.resourceName, "secret", secretName)
|
||||
objs := config.listType.DeepCopyObject().(client.ObjectList)
|
||||
// TODO: ensure that this is cache lister, not a direct client
|
||||
if err := cl.List(context.Background(), objs, client.MatchingFields{injectFromSecretPath: secretName.String()}); err != nil {
|
||||
log.Error(err, "unable to fetch injectables associated with secret")
|
||||
@ -172,25 +163,26 @@ func buildSecretToInjectableFunc(listTyp runtime.Object, resourceName string) se
|
||||
}
|
||||
}
|
||||
|
||||
// secretForInjectableMapper is a Mapper that converts secrets to injectables
|
||||
// via the 'inject-ca-from-secret' annotation
|
||||
type secretForInjectableMapper struct {
|
||||
Client client.Reader
|
||||
log logr.Logger
|
||||
secretToInjectable secretToInjectableFunc
|
||||
}
|
||||
// injectableCAFromIndexer is an IndexerFunc indexing on certificates
|
||||
// referenced by injectables.
|
||||
func injectableCAFromIndexer(rawObj client.Object) []string {
|
||||
metaInfo, err := meta.Accessor(rawObj)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *secretForInjectableMapper) Map(obj client.Object) []ctrl.Request {
|
||||
secretName := types.NamespacedName{Namespace: obj.GetNamespace(), Name: obj.GetName()}
|
||||
log := m.log.WithValues("secret", secretName)
|
||||
return m.secretToInjectable(log, m.Client, secretName)
|
||||
}
|
||||
// skip invalid certificate names
|
||||
certNameRaw := metaInfo.GetAnnotations()[cmapi.WantInjectAnnotation]
|
||||
if certNameRaw == "" {
|
||||
return nil
|
||||
}
|
||||
certName := splitNamespacedName(certNameRaw)
|
||||
if certName.Namespace == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
// injectFromSecretPath is the index key used to look up the value of
|
||||
// inject-ca-from-secret on targeted objects
|
||||
injectFromSecretPath = ".metadata.annotations.inject-ca-from-secret"
|
||||
)
|
||||
return []string{certNameRaw}
|
||||
}
|
||||
|
||||
// injectableCAFromSecretIndexer is an IndexerFunc indexing on secrets
|
||||
// referenced by injectables.
|
||||
|
||||
@ -32,7 +32,6 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/event"
|
||||
"sigs.k8s.io/controller-runtime/pkg/handler"
|
||||
"sigs.k8s.io/controller-runtime/pkg/predicate"
|
||||
"sigs.k8s.io/controller-runtime/pkg/source"
|
||||
|
||||
cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
|
||||
"github.com/cert-manager/cert-manager/pkg/util"
|
||||
@ -93,10 +92,8 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
// registerAllInjectors registers all injectors and based on the
|
||||
// graduation state of the injector decides how to log no kind/resource match errors
|
||||
// RegisterAllInjectors sets up watches for all injectable and injector types that cainjector should watch
|
||||
func RegisterAllInjectors(ctx context.Context, mgr ctrl.Manager, opts SetupOptions) error {
|
||||
// TODO: refactor
|
||||
sds := &secretDataSource{
|
||||
client: mgr.GetClient(),
|
||||
}
|
||||
@ -113,7 +110,6 @@ func RegisterAllInjectors(ctx context.Context, mgr ctrl.Manager, opts SetupOptio
|
||||
}
|
||||
injectorSetups := []setup{MutatingWebhookSetup, ValidatingWebhookSetup, APIServiceSetup, CRDSetup}
|
||||
// Registers a c/r controller for each of APIService, CustomResourceDefinition, Mutating/ValidatingWebhookConfiguration
|
||||
// TODO: add a flag to allow users to configure which of these controllers should be registered
|
||||
for _, setup := range injectorSetups {
|
||||
log := ctrl.Log.WithValues("kind", setup.resourceName)
|
||||
if !opts.EnabledReconcilersFor[setup.resourceName] {
|
||||
@ -169,11 +165,7 @@ func RegisterAllInjectors(ctx context.Context, mgr ctrl.Manager, opts SetupOptio
|
||||
// injectables is here where we define which
|
||||
// objects' events should trigger a reconcile.
|
||||
builder.WithPredicates(predicates)).
|
||||
Watches(&source.Kind{Type: new(corev1.Secret)}, handler.EnqueueRequestsFromMapFunc((&secretForInjectableMapper{
|
||||
Client: mgr.GetClient(),
|
||||
log: log,
|
||||
secretToInjectable: buildSecretToInjectableFunc(setup.listType, setup.resourceName),
|
||||
}).Map))
|
||||
Watches(new(corev1.Secret), handler.EnqueueRequestsFromMapFunc(secretForInjectableMapFuncBuilder(mgr.GetClient(), log, setup)))
|
||||
if opts.EnableCertificatesDataSource {
|
||||
// Index injectable with a new field. If the injectable's CA is
|
||||
// to be sourced from a Certificate's Secret, the field's value will be the
|
||||
@ -184,17 +176,10 @@ func RegisterAllInjectors(ctx context.Context, mgr ctrl.Manager, opts SetupOptio
|
||||
err := fmt.Errorf("error making injectable indexable by inject-ca-from path: %w", err)
|
||||
return err
|
||||
}
|
||||
b.Watches(&source.Kind{Type: new(corev1.Secret)}, handler.EnqueueRequestsFromMapFunc((&secretForCertificateMapper{
|
||||
Client: mgr.GetClient(),
|
||||
log: log,
|
||||
certificateToInjectable: buildCertToInjectableFunc(setup.listType, setup.resourceName),
|
||||
}).Map)).
|
||||
Watches(&source.Kind{Type: new(cmapi.Certificate)},
|
||||
handler.EnqueueRequestsFromMapFunc((&certMapper{
|
||||
Client: mgr.GetClient(),
|
||||
log: log,
|
||||
toInjectable: buildCertToInjectableFunc(setup.listType, setup.resourceName),
|
||||
}).Map))
|
||||
b.Watches(new(corev1.Secret), handler.EnqueueRequestsFromMapFunc(
|
||||
certFromSecretToInjectableMapFuncBuilder(mgr.GetClient(), log, setup))).
|
||||
Watches(new(cmapi.Certificate),
|
||||
handler.EnqueueRequestsFromMapFunc(certToInjectableMapFuncBuilder(mgr.GetClient(), log, setup)))
|
||||
}
|
||||
if err := b.Complete(r); err != nil {
|
||||
return fmt.Errorf("error registering controller for %s: %w", setup.objType.GetName(), err)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user