Skip to content

Commit 4d2ed90

Browse files
Merge pull request #16 from erikgb/refactor-controllers
Refactor package structure
2 parents 793c798 + 78bb40a commit 4d2ed90

15 files changed

+192
-153
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ _bin/
1313
*.bak
1414
/go.work.sum
1515
**/go.work
16+
*.test

pkg/authority/authority.go

Lines changed: 12 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -22,44 +22,26 @@ import (
2222
"time"
2323

2424
corev1 "k8s.io/api/core/v1"
25-
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2625
"k8s.io/apimachinery/pkg/fields"
2726
"k8s.io/apimachinery/pkg/labels"
2827
ctrl "sigs.k8s.io/controller-runtime"
2928
"sigs.k8s.io/controller-runtime/pkg/cache"
3029
"sigs.k8s.io/controller-runtime/pkg/client"
3130

3231
"github.com/cert-manager/webhook-cert-lib/pkg/authority/api"
33-
"github.com/cert-manager/webhook-cert-lib/pkg/authority/cert"
34-
leadercontrollers "github.com/cert-manager/webhook-cert-lib/pkg/authority/leader_controllers"
35-
"github.com/cert-manager/webhook-cert-lib/pkg/authority/leader_controllers/injectable"
32+
"github.com/cert-manager/webhook-cert-lib/pkg/authority/certificate"
33+
"github.com/cert-manager/webhook-cert-lib/pkg/authority/injectable"
3634
)
3735

38-
type LeafOptions struct {
39-
DNSNames []string
40-
41-
// The amount of time leaf certificates signed by this authority will be
42-
// valid for.
43-
// This must be less than CADuration.
44-
Duration time.Duration
45-
}
46-
47-
type Options struct {
48-
CAOptions leadercontrollers.CAOptions
49-
LeafOptions LeafOptions
50-
51-
Injectables []injectable.Injectable
52-
}
53-
5436
type Authority struct {
5537
Options Options
5638

57-
certificateHolder *cert.CertificateHolder
39+
certificateHolder *certificate.Holder
5840
}
5941

6042
func (o *Authority) ServingCertificate() func(config *tls.Config) {
6143
if o.certificateHolder == nil {
62-
o.certificateHolder = &cert.CertificateHolder{}
44+
o.certificateHolder = &certificate.Holder{}
6345
}
6446
return func(config *tls.Config) {
6547
config.GetCertificate = func(info *tls.ClientHelloInfo) (*tls.Certificate, error) {
@@ -99,8 +81,8 @@ func (o *Authority) SetupWithManager(mgr ctrl.Manager) error {
9981
}),
10082
},
10183
}
102-
for _, injectable := range o.Options.Injectables {
103-
cacheByObject[newUnstructured(injectable)] = cache.ByObject{
84+
for _, i := range o.Options.Injectables {
85+
cacheByObject[injectable.NewUnstructured(i)] = cache.ByObject{
10486
Label: labels.SelectorFromSet(labels.Set{
10587
api.WantInjectFromSecretNameLabel: o.Options.CAOptions.Name,
10688
api.WantInjectFromSecretNamespaceLabel: o.Options.CAOptions.Namespace,
@@ -131,17 +113,17 @@ func (o *Authority) SetupWithManager(mgr ctrl.Manager) error {
131113
return err
132114
}
133115

134-
r := leadercontrollers.Reconciler{
116+
r := Reconciler{
135117
Patcher: controllerClient,
136118
Cache: controllerCache,
137-
Opts: o.Options.CAOptions,
119+
Options: o.Options,
138120
}
139121
controllers := []dynamicAuthorityController{
140-
&leadercontrollers.CASecretReconciler{Reconciler: r},
141-
&LeafCertReconciler{Options: o.Options, Cache: controllerCache, CertificateHolder: o.certificateHolder},
122+
&CASecretReconciler{Reconciler: r},
123+
&LeafCertReconciler{Reconciler: r, CertificateHolder: o.certificateHolder},
142124
}
143-
for _, injectable := range o.Options.Injectables {
144-
controllers = append(controllers, &leadercontrollers.InjectableReconciler{Reconciler: r, Injectable: injectable})
125+
for _, i := range o.Options.Injectables {
126+
controllers = append(controllers, &InjectableReconciler{Reconciler: r, Injectable: i})
145127
}
146128
for _, c := range controllers {
147129
if err := c.SetupWithManager(mgr); err != nil {
@@ -155,9 +137,3 @@ func (o *Authority) SetupWithManager(mgr ctrl.Manager) error {
155137
type dynamicAuthorityController interface {
156138
SetupWithManager(ctrl.Manager) error
157139
}
158-
159-
func newUnstructured(injectable injectable.Injectable) *unstructured.Unstructured {
160-
obj := &unstructured.Unstructured{}
161-
obj.SetGroupVersionKind(injectable.GroupVersionKind())
162-
return obj
163-
}

pkg/authority/leader_controllers/ca_secret_controller.go renamed to pkg/authority/ca_secret_controller.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
package leadercontrollers
17+
package authority
1818

1919
import (
2020
"context"
@@ -35,7 +35,8 @@ import (
3535

3636
"github.com/cert-manager/webhook-cert-lib/internal/pki"
3737
"github.com/cert-manager/webhook-cert-lib/pkg/authority/api"
38-
"github.com/cert-manager/webhook-cert-lib/pkg/authority/cert"
38+
"github.com/cert-manager/webhook-cert-lib/pkg/authority/certificate"
39+
"github.com/cert-manager/webhook-cert-lib/pkg/authority/internal/ssa"
3940
)
4041

4142
// CASecretReconciler reconciles a CA Secret object
@@ -49,8 +50,8 @@ func (r *CASecretReconciler) SetupWithManager(mgr ctrl.Manager) error {
4950
r.events = make(chan event.TypedGenericEvent[*corev1.Secret], 1)
5051
r.events <- event.TypedGenericEvent[*corev1.Secret]{Object: &corev1.Secret{
5152
ObjectMeta: metav1.ObjectMeta{
52-
Name: r.Opts.Name,
53-
Namespace: r.Opts.Namespace,
53+
Namespace: r.CAOptions.Namespace,
54+
Name: r.CAOptions.Name,
5455
},
5556
}}
5657

@@ -80,7 +81,7 @@ func (r *CASecretReconciler) reconcileSecret(ctx context.Context, req ctrl.Reque
8081

8182
if generate || secret.Annotations[api.RenewCertificateSecretAnnotation] != secret.Annotations[api.RenewHandledCertificateSecretAnnotation] {
8283
var err error
83-
caCert, caPk, err = cert.GenerateCA(r.Opts.Duration)
84+
caCert, caPk, err = certificate.GenerateCA(r.CAOptions.Duration)
8485
if err != nil {
8586
return err
8687
}
@@ -114,7 +115,7 @@ func (r *CASecretReconciler) reconcileSecret(ctx context.Context, req ctrl.Reque
114115
})
115116
}
116117

117-
return r.Patcher.Patch(ctx, secret, newApplyPatch(ac), client.ForceOwnership, fieldOwner)
118+
return r.Patcher.Patch(ctx, secret, ssa.NewApplyPatch(ac), client.ForceOwnership, ssa.FieldOwner)
118119
}
119120

120121
func addCertToCABundle(logger logr.Logger, caBundleBytes []byte, caCert *x509.Certificate) []byte {

pkg/authority/cert/tls.go renamed to pkg/authority/certificate/tls.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
package cert
17+
package certificate
1818

1919
import (
2020
"crypto"
@@ -102,18 +102,18 @@ var (
102102
ErrCertNotAvailable = errors.New("no tls.Certificate available")
103103
)
104104

105-
type CertificateHolder struct {
105+
type Holder struct {
106106
certP atomic.Pointer[tls.Certificate]
107107
}
108108

109-
func (h *CertificateHolder) GetCertificate(_ *tls.ClientHelloInfo) (*tls.Certificate, error) {
109+
func (h *Holder) GetCertificate(_ *tls.ClientHelloInfo) (*tls.Certificate, error) {
110110
cert := h.certP.Load()
111111
if cert == nil {
112112
return nil, ErrCertNotAvailable
113113
}
114114
return cert, nil
115115
}
116116

117-
func (h *CertificateHolder) SetCertificate(cert *tls.Certificate) {
117+
func (h *Holder) SetCertificate(cert *tls.Certificate) {
118118
h.certP.Store(cert)
119119
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
Copyright 2025 The cert-manager Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package injectable
18+
19+
import (
20+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
21+
"k8s.io/apimachinery/pkg/runtime/schema"
22+
23+
"github.com/cert-manager/webhook-cert-lib/pkg/runtime"
24+
)
25+
26+
type Injectable interface {
27+
GroupVersionKind() schema.GroupVersionKind
28+
InjectCA(obj *unstructured.Unstructured, caBundle []byte) (runtime.ApplyConfiguration, error)
29+
}
30+
31+
func NewUnstructured(injectable Injectable) *unstructured.Unstructured {
32+
obj := &unstructured.Unstructured{}
33+
obj.SetGroupVersionKind(injectable.GroupVersionKind())
34+
return obj
35+
}
36+
37+
func NewUnstructuredList(injectable Injectable) *unstructured.UnstructuredList {
38+
obj := &unstructured.UnstructuredList{}
39+
obj.SetGroupVersionKind(injectable.GroupVersionKind())
40+
return obj
41+
}

pkg/authority/leader_controllers/injectable/validating_webhook.go renamed to pkg/authority/injectable/validating_webhook.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import (
2020
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2121
"k8s.io/apimachinery/pkg/runtime/schema"
2222
admissionregistrationv1ac "k8s.io/client-go/applyconfigurations/admissionregistration/v1"
23+
24+
"github.com/cert-manager/webhook-cert-lib/pkg/runtime"
2325
)
2426

2527
type ValidatingWebhookCaBundleInject struct {
@@ -35,7 +37,7 @@ func (i *ValidatingWebhookCaBundleInject) GroupVersionKind() schema.GroupVersion
3537
}
3638
}
3739

38-
func (i *ValidatingWebhookCaBundleInject) InjectCA(obj *unstructured.Unstructured, caBundle []byte) (ApplyConfiguration, error) {
40+
func (i *ValidatingWebhookCaBundleInject) InjectCA(obj *unstructured.Unstructured, caBundle []byte) (runtime.ApplyConfiguration, error) {
3941
// TODO: Can we generalize this function for any resource based on a JSON path?
4042

4143
ac := admissionregistrationv1ac.ValidatingWebhookConfiguration(obj.GetName())

pkg/authority/leader_controllers/injectable_controller.go renamed to pkg/authority/injectable_controller.go

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
package leadercontrollers
17+
package authority
1818

1919
import (
2020
"context"
@@ -23,7 +23,6 @@ import (
2323
corev1 "k8s.io/api/core/v1"
2424
"k8s.io/apimachinery/pkg/api/errors"
2525
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
26-
"k8s.io/apimachinery/pkg/types"
2726
ctrl "sigs.k8s.io/controller-runtime"
2827
"sigs.k8s.io/controller-runtime/pkg/client"
2928
"sigs.k8s.io/controller-runtime/pkg/handler"
@@ -33,7 +32,8 @@ import (
3332
"sigs.k8s.io/controller-runtime/pkg/source"
3433

3534
"github.com/cert-manager/webhook-cert-lib/pkg/authority/api"
36-
"github.com/cert-manager/webhook-cert-lib/pkg/authority/leader_controllers/injectable"
35+
"github.com/cert-manager/webhook-cert-lib/pkg/authority/injectable"
36+
"github.com/cert-manager/webhook-cert-lib/pkg/authority/internal/ssa"
3737
)
3838

3939
// InjectableReconciler injects CA bundle into resources
@@ -49,21 +49,21 @@ func (r *InjectableReconciler) SetupWithManager(mgr ctrl.Manager) error {
4949
WatchesRawSource(
5050
source.Kind(
5151
r.Cache,
52-
newUnstructured(r.Injectable),
52+
injectable.NewUnstructured(r.Injectable),
5353
&handler.TypedEnqueueRequestForObject[*unstructured.Unstructured]{},
5454
predicate.NewTypedPredicateFuncs(func(obj *unstructured.Unstructured) bool {
55-
return obj.GetLabels()[api.WantInjectFromSecretNamespaceLabel] == r.Opts.Namespace &&
56-
obj.GetLabels()[api.WantInjectFromSecretNameLabel] == r.Opts.Name
55+
return obj.GetLabels()[api.WantInjectFromSecretNamespaceLabel] == r.CAOptions.Namespace &&
56+
obj.GetLabels()[api.WantInjectFromSecretNameLabel] == r.CAOptions.Name
5757
}),
5858
),
5959
).
6060
WatchesRawSource(
6161
r.caSecretSource(
6262
handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, _ *corev1.Secret) []reconcile.Request {
63-
objList := newUnstructuredList(r.Injectable)
63+
objList := injectable.NewUnstructuredList(r.Injectable)
6464
if err := r.Cache.List(ctx, objList, client.MatchingLabels(map[string]string{
65-
api.WantInjectFromSecretNamespaceLabel: r.Opts.Namespace,
66-
api.WantInjectFromSecretNameLabel: r.Opts.Name,
65+
api.WantInjectFromSecretNamespaceLabel: r.CAOptions.Namespace,
66+
api.WantInjectFromSecretNameLabel: r.CAOptions.Name,
6767
})); err != nil {
6868
log.FromContext(ctx).Error(err, "when listing injectables")
6969
return nil
@@ -83,23 +83,11 @@ func (r *InjectableReconciler) SetupWithManager(mgr ctrl.Manager) error {
8383
Complete(r)
8484
}
8585

86-
func newUnstructured(injectable injectable.Injectable) *unstructured.Unstructured {
87-
obj := &unstructured.Unstructured{}
88-
obj.SetGroupVersionKind(injectable.GroupVersionKind())
89-
return obj
90-
}
91-
92-
func newUnstructuredList(injectable injectable.Injectable) *unstructured.UnstructuredList {
93-
obj := &unstructured.UnstructuredList{}
94-
obj.SetGroupVersionKind(injectable.GroupVersionKind())
95-
return obj
96-
}
97-
9886
func (r *InjectableReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
9987
_ = log.FromContext(ctx)
10088

10189
secret := &corev1.Secret{}
102-
if err := r.Cache.Get(ctx, types.NamespacedName{Namespace: r.Opts.Namespace, Name: r.Opts.Name}, secret); err != nil {
90+
if err := r.Cache.Get(ctx, r.CAOptions.NamespacedName, secret); err != nil {
10391
if errors.IsNotFound(err) {
10492
log.FromContext(ctx).V(1).Info("CA secret not yet found, requeueing request...")
10593
return ctrl.Result{Requeue: true}, nil
@@ -111,7 +99,7 @@ func (r *InjectableReconciler) Reconcile(ctx context.Context, req ctrl.Request)
11199
}
112100

113101
func (r *InjectableReconciler) reconcileInjectable(ctx context.Context, req ctrl.Request, caBundle []byte) error {
114-
obj := newUnstructured(r.Injectable)
102+
obj := injectable.NewUnstructured(r.Injectable)
115103
if err := r.Cache.Get(ctx, req.NamespacedName, obj); err != nil {
116104
return err
117105
}
@@ -121,7 +109,7 @@ func (r *InjectableReconciler) reconcileInjectable(ctx context.Context, req ctrl
121109
return err
122110
}
123111

124-
if err := r.Patcher.Patch(ctx, obj, newApplyPatch(ac), client.ForceOwnership, fieldOwner); err != nil {
112+
if err := r.Patcher.Patch(ctx, obj, ssa.NewApplyPatch(ac), client.ForceOwnership, ssa.FieldOwner); err != nil {
125113
return err
126114
}
127115

pkg/authority/leader_controllers/ssa_client.go renamed to pkg/authority/internal/ssa/client.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,32 +14,32 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
package leadercontrollers
17+
package ssa
1818

1919
import (
2020
"k8s.io/apimachinery/pkg/types"
2121
"k8s.io/apimachinery/pkg/util/json"
2222
"sigs.k8s.io/controller-runtime/pkg/client"
2323

24-
"github.com/cert-manager/webhook-cert-lib/pkg/authority/leader_controllers/injectable"
24+
"github.com/cert-manager/webhook-cert-lib/pkg/runtime"
2525
)
2626

2727
const (
28-
fieldOwner = client.FieldOwner("cert-manager-dynamic-authority")
28+
FieldOwner = client.FieldOwner("cert-manager-dynamic-authority")
2929
)
3030

31-
func newApplyPatch(ac injectable.ApplyConfiguration) applyPatch {
32-
return applyPatch{ac: ac}
31+
func NewApplyPatch(ac runtime.ApplyConfiguration) ApplyPatch {
32+
return ApplyPatch{ac: ac}
3333
}
3434

35-
type applyPatch struct {
36-
ac injectable.ApplyConfiguration
35+
type ApplyPatch struct {
36+
ac runtime.ApplyConfiguration
3737
}
3838

39-
func (p applyPatch) Type() types.PatchType {
39+
func (p ApplyPatch) Type() types.PatchType {
4040
return types.ApplyPatchType
4141
}
4242

43-
func (p applyPatch) Data(_ client.Object) ([]byte, error) {
43+
func (p ApplyPatch) Data(_ client.Object) ([]byte, error) {
4444
return json.Marshal(p.ac)
4545
}

0 commit comments

Comments
 (0)