package certificaterequests import ( "context" "fmt" k8sErrors "k8s.io/apimachinery/pkg/api/errors" v1 "gitbucket.jerxie.com/yangyangxie/AnthosCertManager/pkg/apis/anthoscertmanager/v1" acmclient "gitbucket.jerxie.com/yangyangxie/AnthosCertManager/pkg/client/clientset/versioned" acmlisters "gitbucket.jerxie.com/yangyangxie/AnthosCertManager/pkg/client/listers/anthoscertmanager/v1" controllerpkg "gitbucket.jerxie.com/yangyangxie/AnthosCertManager/pkg/controller" "gitbucket.jerxie.com/yangyangxie/AnthosCertManager/pkg/issuer" logf "gitbucket.jerxie.com/yangyangxie/AnthosCertManager/pkg/logs" "github.com/go-logr/logr" "k8s.io/apimachinery/pkg/runtime/schema" corelisters "k8s.io/client-go/listers/core/v1" "k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/record" "k8s.io/client-go/util/workqueue" "k8s.io/utils/clock" ) var keyFunc = controllerpkg.KeyFunc // Issuer implements the funcationalitiy to sign a certificate request for a particular issue type. type Issuer interface { Sign(context.Context, *v1.CertificateRequest, v1.GenericIssuer) (*issuer.IssueResponse, error) } // Issuer Contractor builds a Issuer instance using the given controller // context. type IssuerConstructor func(*controllerpkg.Context) Issuer type controller struct { //helper issuer.Helper // clientset used to update cert-manager API resources acmClient acmclient.Interface // fieldManager is the manager name used for the Apply operations. fieldManager string certificateRequestLister acmlisters.CertificateRequestLister // we need to wait for Secrets to be synced to avoid a situation where CA issuer's Secret // is not yet in cached at a time when issuance is attempted, // more details at https://github.com/cert-manager/cert-manager/issues/5216 secretLister corelisters.SecretLister queue workqueue.RateLimitingInterface // logger to be used by this controller log logr.Logger // used to record Events about resources to the API recorder record.EventRecorder // the issuer kind to react to when a certificate request is synced issuerType string issuerLister acmlisters.IssuerLister clusterIssuerLister acmlisters.ClusterIssuerLister // extraInformerResources are the set of resources which should cause // reconciles if owned by a CertifcateRequest. extraInformerResources []schema.GroupVersionResource // Issuer to call sign function issuerConstructor IssuerConstructor issuer Issuer // used for testing clock clock.Clock // reporter *util.Reporter } // NewController will construct a new certificaterequest controller using the given // Issuer implementation. func NewController(issuerType string, issuerConstructor IssuerConstructor, extraInformerResources ...schema.GroupVersionResource) *controller { return &controller{ issuerType: issuerType, issuerConstructor: issuerConstructor, extraInformerResources: extraInformerResources, } } func (c *controller) Register(ctx *controllerpkg.Context) (workqueue.RateLimitingInterface, []cache.InformerSynced, error) { componentName := "certificaterequests-issuer-" + c.issuerType c.log = logf.FromContext(ctx.RootContext, componentName) // create a working queue c.queue = workqueue.NewNamedRateLimitingQueue(controllerpkg.DefaultItemBasedRateLimiter(), componentName) secretsInformer := ctx.KubeSharedInformerFactory.Core().V1().Secrets() issuerInformer := ctx.SharedInformerFactory.AnthosCertmanager().V1().Issuers() c.issuerLister = issuerInformer.Lister() c.secretLister = secretsInformer.Lister() // obtain references to all the informers used by this controller certificateRequestInformer := ctx.SharedInformerFactory.AnthosCertmanager().V1().CertificateRequests() mustSync := []cache.InformerSynced{ certificateRequestInformer.Informer().HasSynced, issuerInformer.Informer().HasSynced, secretsInformer.Informer().HasSynced, } // If the manger is scoped to all namespaces, we should also obtain a lister for clusterissuers. if ctx.Namespace == "" { clusterIssuerInformer := ctx.SharedInformerFactory.AnthosCertmanager().V1().ClusterIssuers() c.clusterIssuerLister = clusterIssuerInformer.Lister() // register handler function for cluster issuers resources clusterIssuerInformer.Informer().AddEventHandler(&controllerpkg.BlockingEventHandler{WorkFunc: c.handleGenericIssuer}) } c.certificateRequestLister = certificateRequestInformer.Lister() // register handler functions certificateRequestInformer.Informer().AddEventHandler(&controllerpkg.QueuingEventHandler{Queue: c.queue}) issuerInformer.Informer().AddEventHandler(&controllerpkg.BlockingEventHandler{WorkFunc: c.handleGenericIssuer}) // create an issuer helper for reading generic issuers // c.helper = issuer.NewHelper(c.issuerLister, c.clusterIssuerLister) // clock is used to set the FailureTime of failed CertificateRequests c.clock = ctx.Clock // recorder records events about resources to the Kubernetes api c.recorder = ctx.Recorder // c.reporter = util.NewReporter(c.clock, c.recorder) c.acmClient = ctx.ACMClient c.fieldManager = ctx.FieldManager // Construct the issuer implementation with the built component context. c.issuer = c.issuerConstructor(ctx) c.log.V(logf.DebugLevel).Info("new certificate request controller registered", "type", c.issuerType) return c.queue, mustSync, nil } // ProcessItem is the worker function that will be called with a new key from // the workqueue. A key corresponds to a certificate request object. func (c *controller) ProcessItem(ctx context.Context, key string) error { log := logf.FromContext(ctx) dbg := log.V(logf.DebugLevel) namespace, name, err := cache.SplitMetaNamespaceKey(key) if err != nil { log.Error(err, "invalid resource key") return nil } cr, err := c.certificateRequestLister.CertificateRequests(namespace).Get(name) if err != nil { if k8sErrors.IsNotFound(err) { dbg.Info(fmt.Sprintf("certificate request in work queue no longer exists: %s", err)) return nil } return err } ctx = logf.NewContext(ctx, logf.WithResource(log, cr)) return c.Sync(ctx, cr) } func certificateRequestGetter(lister acmlisters.CertificateRequestLister) func(namespace, name string) (interface{}, error) { return func(namespace, name string) (interface{}, error) { return lister.CertificateRequests(namespace).Get(name) } }