11package main
22
33import (
4+ "context"
45 "fmt"
56 "net"
67 "net/http"
@@ -34,6 +35,56 @@ func (e *executor) Run(cmd *exec.Cmd) error {
3435 return cmd .Run ()
3536}
3637
38+ //go:generate mockery --name=Ticker --filename=ticker.go
39+ type Ticker interface {
40+ // Init creates a new [time.Ticker] internally with [time.Duration] defined.
41+ Init (context.Context , time.Duration )
42+ // Tick waits for a ticker's tick and return the value. If ticker wasn't initialized, a [time.Time] with zero-value
43+ // will be returned.
44+ Tick () chan time.Time
45+ // Stop stops the ticker initialized. If ticker wasn't initialized, nothing happens.
46+ Stop ()
47+ }
48+
49+ type ticker struct {
50+ ticker * time.Ticker
51+ tick chan time.Time
52+ }
53+
54+ func (t * ticker ) Init (ctx context.Context , duration time.Duration ) {
55+ t .ticker = time .NewTicker (duration )
56+ t .tick = make (chan time.Time )
57+
58+ go func () {
59+ defer close (t .tick )
60+
61+ for {
62+ select {
63+ case <- ctx .Done ():
64+ return
65+ case ticked , ok := <- t .ticker .C :
66+ if ! ok {
67+ return
68+ }
69+
70+ t .tick <- ticked
71+ }
72+ }
73+ }()
74+ }
75+
76+ func (t * ticker ) Tick () chan time.Time {
77+ return t .tick
78+ }
79+
80+ func (t * ticker ) Stop () {
81+ if t .ticker == nil {
82+ return
83+ }
84+
85+ t .ticker .Stop ()
86+ }
87+
3788// DNSProvider represents a DNS provider to generate certificates.
3889type DNSProvider string
3990
@@ -67,6 +118,7 @@ type CertBot struct {
67118 Config * Config
68119
69120 ex Executor
121+ tk Ticker
70122 fs afero.Fs
71123}
72124
@@ -75,6 +127,7 @@ func newCertBot(config *Config) *CertBot {
75127 Config : config ,
76128
77129 ex : new (executor ),
130+ tk : new (ticker ),
78131 fs : afero .NewOsFs (),
79132 }
80133}
@@ -265,21 +318,30 @@ func (cb *CertBot) executeRenewCertificates() error {
265318}
266319
267320// renewCertificates periodically renews the SSL certificates.
268- func (cb * CertBot ) renewCertificates () {
321+ func (cb * CertBot ) renewCertificates (ctx context. Context , duration time. Duration ) {
269322 log .Info ("starting SSL certificate renewal process" )
270323
271- ticker := time . NewTicker ( 24 * time . Hour )
272- defer ticker .Stop ()
324+ cb . tk . Init ( ctx , duration )
325+ defer cb . tk .Stop ()
273326
274- for range ticker .C {
275- log .Info ("checking if SSL certificate needs to be renewed" )
276- if err := cb .executeRenewCertificates (); err != nil {
277- log .WithError (err ).Error ("failed to renew SSL certificate" )
327+ ticker := cb .tk .Tick ()
278328
279- continue
280- }
329+ for {
330+ select {
331+ case <- ctx .Done ():
332+ log .Info ("renew certificates loop was closed due context cancellation" )
333+
334+ return
335+ case <- ticker :
336+ log .Info ("checking if SSL certificate needs to be renewed" )
337+ if err := cb .executeRenewCertificates (); err != nil {
338+ log .WithError (err ).Error ("failed to renew SSL certificate" )
281339
282- log .Info ("ssl certificate successfully renewed" )
283- cb .Config .RenewedCallback ()
340+ continue
341+ }
342+
343+ log .Info ("ssl certificate successfully renewed" )
344+ cb .Config .RenewedCallback ()
345+ }
284346 }
285347}
0 commit comments