Skip to content

Commit 30a6f95

Browse files
committed
use zap for logging, previous log never outputted to kubectl logs
1 parent fd8858e commit 30a6f95

File tree

4 files changed

+102
-110
lines changed

4 files changed

+102
-110
lines changed

go.mod

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ module github.com/open-policy-agent/cert-controller
22

33
go 1.14
44

5-
require (
6-
github.com/onsi/gomega v1.10.1
7-
github.com/pkg/errors v0.9.1
8-
go.uber.org/atomic v1.4.0
9-
go.uber.org/zap v1.10.0
10-
k8s.io/api v0.18.6
11-
k8s.io/apimachinery v0.18.6
12-
k8s.io/client-go v0.18.6
13-
sigs.k8s.io/controller-runtime v0.6.3
14-
)
5+
require (
6+
github.com/go-logr/zapr v0.1.0
7+
github.com/onsi/gomega v1.10.1
8+
github.com/open-policy-agent/cert-controller v0.1.0
9+
github.com/pkg/errors v0.9.1
10+
go.uber.org/atomic v1.4.0
11+
go.uber.org/zap v1.10.0
12+
k8s.io/api v0.18.6
13+
k8s.io/apimachinery v0.18.6
14+
k8s.io/client-go v0.18.6
15+
sigs.k8s.io/controller-runtime v0.6.3
16+
)

main.go

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import (
1212
"k8s.io/client-go/tools/clientcmd/api"
1313
"os"
1414
ctrl "sigs.k8s.io/controller-runtime"
15+
logf "sigs.k8s.io/controller-runtime/pkg/log"
16+
"github.com/go-logr/zapr"
1517
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
1618
"time"
1719
)
@@ -27,6 +29,21 @@ var (
2729
webhookName = flag.String("webhook-name", "", "Your webhook name")
2830
)
2931

32+
func buildLogger() (*zap.Logger, error) {
33+
// build a logger:
34+
// - without timestamps because docker already logs with timestamps
35+
// - use "message" instead of "msg" for consistency with other services / datadog parsing
36+
// - remove caller since it points to shared methods most of the time anyway
37+
loggerConfig := zap.NewProductionConfig()
38+
loggerConfig.EncoderConfig.TimeKey = ""
39+
loggerConfig.EncoderConfig.MessageKey = "message"
40+
loggerConfig.DisableCaller = true
41+
if os.Getenv("DEBUG") == "1" {
42+
loggerConfig.Level.SetLevel(zap.DebugLevel)
43+
}
44+
return loggerConfig.Build()
45+
}
46+
3047
func main() {
3148
flag.Parse()
3249

@@ -38,7 +55,9 @@ func main() {
3855
}
3956

4057
// configure logging.
41-
logger, _ := zap.NewDevelopment()
58+
logger, _ := buildLogger()
59+
defer logger.Sync() // flush buffer
60+
logf.SetLogger(zapr.NewLogger(logger)) // Set logger for cert-controller or it sends to /dev/null
4261

4362
logger.Info("sleeping to demonstrate restart behavior")
4463
time.Sleep(5 * time.Second)
@@ -63,6 +82,7 @@ func main() {
6382
}
6483

6584
// Make sure certs are generated and valid if cert rotation is enabled.
85+
setupFinished := make(chan struct{})
6686
if err := rotator.AddRotator(mgr, &rotator.CertRotator{
6787
SecretKey: types.NamespacedName{
6888
Namespace: *nameSpace,
@@ -72,10 +92,10 @@ func main() {
7292
CAName: *caName,
7393
CAOrganization: *caOrganization,
7494
DNSName: *dnsName,
95+
IsReady: setupFinished,
7596
Webhooks: webhooks,
7697
}); err != nil {
7798
logger.Error("unable to set up cert rotation", zap.Error(err))
78-
7999
os.Exit(1)
80100
}
81101

pkg/rotator/rotator.go

Lines changed: 20 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ const (
4141
caCertName = "ca.crt"
4242
caKeyName = "ca.key"
4343
rotationCheckFrequency = 12 * time.Hour
44+
certValidityDuration = 10 * 365 * 24 * time.Hour
4445
lookaheadInterval = 90 * 24 * time.Hour
4546
)
4647

@@ -62,9 +63,6 @@ var _ manager.Runnable = &CertRotator{}
6263

6364
var restartOnSecretRefresh = false
6465

65-
var certValidityDuration = flag.Duration("cert-validity-duration", 10 * 365 * 24 * time.Hour, "Sets how long the cert is valid for, defaults to 10 years")
66-
67-
6866
//WebhookInfo is used by the rotator to receive info about resources to be updated with certificates
6967
type WebhookInfo struct {
7068
//Name is the name of the webhook for a validating or mutating webhook, or the CRD name in case of a CRD conversion webhook
@@ -73,7 +71,7 @@ type WebhookInfo struct {
7371
}
7472

7573
func init() {
76-
flag.BoolVar(&restartOnSecretRefresh, "cert-restart-on-secret-refresh", true, "Kills the process when secrets are refreshed so that the pod can be restarted (secrets take up to 60s to be updated by running pods)")
74+
flag.BoolVar(&restartOnSecretRefresh, "cert-restart-on-secret-refresh", false, "Kills the process when secrets are refreshed so that the pod can be restarted (secrets take up to 60s to be updated by running pods)")
7775
}
7876

7977
func (w WebhookInfo) gvk() schema.GroupVersionKind {
@@ -148,7 +146,7 @@ func addNamespacedCache(mgr manager.Manager, namespace string) (cache.Cache, err
148146
// SyncingSource is a reader that needs syncing prior to being usable.
149147
type SyncingReader interface {
150148
client.Reader
151-
WaitForCacheSync(stop <-chan struct{}) bool
149+
WaitForCacheSync(ctx context.Context) bool
152150
}
153151

154152
// CertRotator contains cert artifacts and a channel to close when the certs are ready.
@@ -169,11 +167,11 @@ type CertRotator struct {
169167
}
170168

171169
// Start starts the CertRotator runnable to rotate certs and ensure the certs are ready.
172-
func (cr *CertRotator) Start(stop <-chan struct{}) error {
170+
func (cr *CertRotator) Start(ctx context.Context) error {
173171
if cr.reader == nil {
174172
return errors.New("nil reader")
175173
}
176-
if !cr.reader.WaitForCacheSync(stop) {
174+
if !cr.reader.WaitForCacheSync(ctx) {
177175
return errors.New("failed waiting for reader to sync")
178176
}
179177

@@ -199,7 +197,7 @@ tickerLoop:
199197
if err := cr.refreshCertIfNeeded(); err != nil {
200198
crLog.Error(err, "error rotating certs")
201199
}
202-
case <-stop:
200+
case <-ctx.Done():
203201
break tickerLoop
204202
case <-cr.certsNotMounted:
205203
return errors.New("could not mount certs")
@@ -264,7 +262,7 @@ func (cr *CertRotator) refreshCerts(refreshCA bool, secret *corev1.Secret) error
264262
var caArtifacts *KeyPairArtifacts
265263
now := time.Now()
266264
begin := now.Add(-1 * time.Hour)
267-
end := now.Add(*certValidityDuration)
265+
end := now.Add(certValidityDuration)
268266
if refreshCA {
269267
var err error
270268
caArtifacts, err = cr.CreateCACert(begin, end)
@@ -539,43 +537,17 @@ func ValidCert(caCert, cert, key []byte, dnsName string, at time.Time) (bool, er
539537
return true, nil
540538
}
541539

542-
// controller code for making sure the CA cert on the
543-
// webhooks don't get clobbered
544-
545-
var _ handler.Mapper = &crdMapper{}
546-
547-
type crdMapper struct {
548-
secretKey types.NamespacedName
549-
crdNames []string
550-
}
551-
552-
func (m *crdMapper) Map(object handler.MapObject) []reconcile.Request {
553-
if object.Meta.GetNamespace() != "" {
554-
return nil
555-
}
556-
for _, crdName := range m.crdNames {
557-
if object.Meta.GetName() == crdName {
558-
return []reconcile.Request{{NamespacedName: m.secretKey}}
540+
func reconcileSecretAndWebhookMapFunc(webhook WebhookInfo, r *ReconcileWH) func(object client.Object) []reconcile.Request {
541+
return func(object client.Object) []reconcile.Request {
542+
whKey := types.NamespacedName{Name: webhook.Name}
543+
if object.GetNamespace() != whKey.Namespace {
544+
return nil
559545
}
546+
if object.GetName() != whKey.Name {
547+
return nil
548+
}
549+
return []reconcile.Request{{NamespacedName: r.secretKey}}
560550
}
561-
return nil
562-
}
563-
564-
var _ handler.Mapper = &mapper{}
565-
566-
type mapper struct {
567-
secretKey types.NamespacedName
568-
whKey types.NamespacedName
569-
}
570-
571-
func (m *mapper) Map(object handler.MapObject) []reconcile.Request {
572-
if object.Meta.GetNamespace() != m.whKey.Namespace {
573-
return nil
574-
}
575-
if object.Meta.GetName() != m.whKey.Name {
576-
return nil
577-
}
578-
return []reconcile.Request{{NamespacedName: m.secretKey}}
579551
}
580552

581553
// add adds a new Controller to mgr with r as the reconcile.Reconciler
@@ -599,10 +571,7 @@ func addController(mgr manager.Manager, r *ReconcileWH) error {
599571
wh.SetGroupVersionKind(webhook.gvk())
600572
err = c.Watch(
601573
source.NewKindWithCache(wh, r.cache),
602-
&handler.EnqueueRequestsFromMapFunc{ToRequests: &mapper{
603-
secretKey: r.secretKey,
604-
whKey: types.NamespacedName{Name: webhook.Name},
605-
}},
574+
handler.EnqueueRequestsFromMapFunc(reconcileSecretAndWebhookMapFunc(webhook, r)),
606575
)
607576
if err != nil {
608577
return fmt.Errorf("watching webhook %s: %w", webhook.Name, err)
@@ -628,13 +597,12 @@ type ReconcileWH struct {
628597

629598
// Reconcile reads that state of the cluster for a validatingwebhookconfiguration
630599
// object and makes sure the most recent CA cert is included
631-
func (r *ReconcileWH) Reconcile(request reconcile.Request) (reconcile.Result, error) {
600+
func (r *ReconcileWH) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
632601
if request.NamespacedName != r.secretKey {
633602
return reconcile.Result{}, nil
634603
}
635604

636-
stop := make(<-chan struct{})
637-
if !r.cache.WaitForCacheSync(stop) {
605+
if !r.cache.WaitForCacheSync(ctx) {
638606
return reconcile.Result{}, errors.New("cache not ready")
639607
}
640608

@@ -657,11 +625,9 @@ func (r *ReconcileWH) Reconcile(request reconcile.Request) (reconcile.Result, er
657625
}
658626

659627
// Ensure certs on webhooks
660-
fmt.Println("Starting cert injection")
661628
if err := r.ensureCerts(artifacts.CertPEM); err != nil {
662629
return reconcile.Result{}, err
663630
}
664-
fmt.Println("Finished cert injection")
665631

666632
// Set CAInjected if the reconciler has not exited early.
667633
r.wasCAInjected.Store(true)
@@ -690,32 +656,25 @@ func (r *ReconcileWH) ensureCerts(certPem []byte) error {
690656
updatedResource.SetGroupVersionKind(gvk)
691657
if err := r.cache.Get(r.ctx, types.NamespacedName{Name: webhook.Name}, updatedResource); err != nil {
692658
if k8sErrors.IsNotFound(err) {
693-
fmt.Println("Webhook not found. Unable to update certificate.", err)
694659
log.Error(err, "Webhook not found. Unable to update certificate.")
695660
continue
696661
}
697662
anyError = err
698663
log.Error(err, "Error getting webhook for certificate update.")
699-
fmt.Println("Error getting webhook for certificate update.", err)
700-
701664
continue
702665
}
703666
if !updatedResource.GetDeletionTimestamp().IsZero() {
704-
fmt.Println("Webhook is being deleted. Unable to update certificate")
705667
log.Info("Webhook is being deleted. Unable to update certificate")
706668
continue
707669
}
708670

709671
log.Info("Ensuring CA cert", "name", webhook.Name, "gvk", gvk)
710672
if err := injectCert(updatedResource, certPem, webhook.Type); err != nil {
711-
fmt.Println("Unable to inject cert to webhook.:", err)
712673
log.Error(err, "Unable to inject cert to webhook.")
713674
anyError = err
714675
continue
715676
}
716677
if err := r.writer.Update(r.ctx, updatedResource); err != nil {
717-
fmt.Println("Error updating webhook with certificate:", err)
718-
719678
log.Error(err, "Error updating webhook with certificate")
720679
anyError = err
721680
continue
@@ -766,4 +725,4 @@ func (cr *CertRotator) ensureReady() {
766725
}
767726
crLog.Info("CA certs are injected to webhooks")
768727
close(cr.IsReady)
769-
}
728+
}

test.yaml

Lines changed: 48 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -18,29 +18,40 @@ spec:
1818
foo: bar4
1919
spec:
2020
containers:
21-
- name: busybox
22-
image: busybox
23-
command: ["sh", "-c", "watch ls /certs"]
24-
volumeMounts:
25-
- name: certs
26-
mountPath: "/certs"
27-
readOnly: true
28-
- name: cert-controller
29-
args:
30-
- -cert-dir=/certs
31-
- -ca-name=foocaname
32-
- -secret-name=vpa-admission-controller-secret
33-
- -service-name=fooservice
34-
- -ca-organization=fooorg
35-
- -namespace=default
36-
- -dns-name=foo.bar.svc
37-
- -webhook-name=vpa-webhook-config
38-
imagePullPolicy: Never
39-
image: cert-controller
21+
- name: busybox
22+
image: busybox
23+
command: ["sh", "-c", "watch ls /certs"]
24+
volumeMounts:
25+
- name: certs
26+
mountPath: "/certs"
27+
readOnly: true
28+
- name: cert-controller
29+
args:
30+
- -cert-dir=/certs
31+
- -ca-name=foocaname
32+
- -secret-name=vpa-admission-controller-secret
33+
- -service-name=fooservice
34+
- -ca-organization=fooorg
35+
- -namespace=default
36+
- -dns-name=foo.bar.svc
37+
- -webhook-name=vpa-webhook-config
38+
imagePullPolicy: Never
39+
image: cert-controller
40+
resources:
41+
limits:
42+
cpu: 200m
43+
memory: 500Mi
44+
requests:
45+
cpu: 50m
46+
memory: 200Mi
47+
volumeMounts:
48+
- name: certs
49+
mountPath: "/certs"
50+
readOnly: true
4051
volumes:
41-
- name: certs
42-
secret:
43-
secretName: vpa-admission-controller-secret
52+
- name: certs
53+
secret:
54+
secretName: vpa-admission-controller-secret
4455
---
4556
apiVersion: admissionregistration.k8s.io/v1
4657
kind: MutatingWebhookConfiguration
@@ -54,21 +65,21 @@ metadata:
5465
annotations:
5566
samson/server_side_apply: 'true'
5667
webhooks:
57-
- name: vpa.k8s.io
58-
failurePolicy: Ignore
59-
admissionReviewVersions: ["v1beta1"]
60-
rules:
61-
- apiGroups: [""]
62-
apiVersions: ["v1"]
63-
operations: ["CREATE"]
64-
resources: ["pods"]
65-
clientConfig:
66-
caBundle: Cg==
67-
service:
68-
namespace: default
69-
name: vpa-webhook
70-
sideEffects: None
71-
timeoutSeconds: 30
68+
- name: vpa.k8s.io
69+
failurePolicy: Ignore
70+
admissionReviewVersions: ["v1beta1"]
71+
rules:
72+
- apiGroups: [""]
73+
apiVersions: ["v1"]
74+
operations: ["CREATE"]
75+
resources: ["pods"]
76+
clientConfig:
77+
caBundle: Cg==
78+
service:
79+
namespace: default
80+
name: vpa-webhook
81+
sideEffects: None
82+
timeoutSeconds: 30
7283

7384
# We need to create a bogus secret for the updater to fill
7485
---

0 commit comments

Comments
 (0)