Skip to content

Commit 27c3020

Browse files
committed
refactor(project): restructure project layout for improved modularity
1 parent 979cb59 commit 27c3020

File tree

6 files changed

+42
-54
lines changed

6 files changed

+42
-54
lines changed

.goreleaser.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ builds:
66
- env:
77
- CGO_ENABLED=0
88
binary: zero
9+
main: ./cmd/zero
910
goos:
1011
- linux
1112
- darwin

main.go renamed to cmd/zero/main.go

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,17 @@ import (
44
"context"
55
"errors"
66
"fmt"
7+
"github.com/yarlson/zero/internal/acme"
8+
"github.com/yarlson/zero/internal/cert"
9+
"github.com/yarlson/zero/internal/server"
10+
"github.com/yarlson/zero/internal/task"
711
"log"
812
"os"
913
"os/signal"
1014
"syscall"
1115
"time"
1216

1317
"github.com/spf13/pflag"
14-
15-
"github.com/yarlson/zero/certificates"
16-
"github.com/yarlson/zero/cron"
17-
"github.com/yarlson/zero/server"
18-
"github.com/yarlson/zero/zerossl"
1918
)
2019

2120
const (
@@ -54,7 +53,7 @@ func parseFlags() (*Config, error) {
5453
return nil, errors.New("domain and email are required")
5554
}
5655

57-
if _, err := cron.ParseTime(cfg.Time); err != nil {
56+
if _, err := task.ParseTime(cfg.Time); err != nil {
5857
return nil, fmt.Errorf("invalid time format: %w", err)
5958
}
6059

@@ -72,11 +71,11 @@ func main() {
7271
}
7372

7473
// Setup services
75-
zeroSSLService := zerossl.New()
76-
certService := certificates.New(zeroSSLService)
74+
zeroSSL := acme.NewZeroSSL()
75+
certManager := cert.NewStore(zeroSSL)
7776

7877
// Start HTTP server
79-
srv := server.New(certService, cfg.Port)
78+
srv := server.New(certManager, cfg.Port)
8079
go func() {
8180
if err := srv.Start(); err != nil {
8281
log.Fatalf("HTTP server error: %v", err)
@@ -85,18 +84,18 @@ func main() {
8584

8685
// Start certificate checker
8786
checkCert := func(ctx context.Context) error {
88-
return certService.CheckCertificate(ctx, cfg.Domain, cfg.Email, cfg.CertDir)
87+
return certManager.CheckCertificate(ctx, cfg.Domain, cfg.Email, cfg.CertDir)
8988
}
9089

91-
cronService := cron.New(checkCert, cfg.Time)
92-
go cronService.Start()
90+
scheduler := task.NewScheduler(checkCert, cfg.Time)
91+
go scheduler.Start()
9392

9493
// Wait for shutdown signal
9594
sigChan := make(chan os.Signal, 1)
9695
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
9796
<-sigChan
9897

9998
log.Println("Shutting down...")
100-
cronService.Stop()
99+
scheduler.Stop()
101100
time.Sleep(time.Second)
102101
}
Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package zerossl
1+
package acme
22

33
import (
44
"bytes"
@@ -25,31 +25,19 @@ const (
2525
zeroSSLURL = "https://acme.zerossl.com/v2/DV90"
2626
)
2727

28-
type Service struct {
28+
type ZeroSSL struct {
2929
client *http.Client
3030
}
3131

32-
type Option func(*Service)
33-
34-
func WithClient(client *http.Client) Option {
35-
return func(s *Service) {
36-
s.client = client
37-
}
38-
}
39-
40-
func New(options ...Option) *Service {
41-
service := &Service{
32+
func NewZeroSSL() *ZeroSSL {
33+
service := &ZeroSSL{
4234
client: &http.Client{Timeout: 10 * time.Second},
4335
}
4436

45-
for _, option := range options {
46-
option(service)
47-
}
48-
4937
return service
5038
}
5139

52-
func (s *Service) FetchCredentials(ctx context.Context, email string) (kid, hmacKey string, err error) {
40+
func (s *ZeroSSL) FetchCredentials(ctx context.Context, email string) (kid, hmacKey string, err error) {
5341
data := []byte(fmt.Sprintf("email=%s", email))
5442
req, err := http.NewRequestWithContext(ctx, http.MethodPost, zeroSSLEABAPIURL, bytes.NewBuffer(data))
5543
if err != nil {
@@ -87,7 +75,7 @@ func (s *Service) FetchCredentials(ctx context.Context, email string) (kid, hmac
8775
return result.EABKID, result.EABHMACKey, nil
8876
}
8977

90-
func (s *Service) ObtainCertificate(ctx context.Context, domain, email string, challengeHandler func(token, response string)) ([][]byte, crypto.PrivateKey, error) {
78+
func (s *ZeroSSL) ObtainCertificate(ctx context.Context, domain, email string, challengeHandler func(token, response string)) ([][]byte, crypto.PrivateKey, error) {
9179
eabKID, eabHMACKey, err := s.FetchCredentials(ctx, email)
9280
if err != nil {
9381
return nil, nil, fmt.Errorf("fetch ZeroSSL credentials: %w", err)
Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package certificates
1+
package cert
22

33
import (
44
"context"
@@ -18,24 +18,24 @@ const (
1818
renewBeforeDays = 30
1919
)
2020

21-
type ZeroSSLService interface {
21+
type ZeroSSL interface {
2222
ObtainCertificate(ctx context.Context, domain, email string, challengeHandler func(token, response string)) ([][]byte, crypto.PrivateKey, error)
2323
}
2424

25-
type Service struct {
26-
zeroSSLService ZeroSSLService
25+
type Store struct {
26+
zeroSSLService ZeroSSL
2727
challenges map[string]string
2828
challengeMu sync.RWMutex
2929
}
3030

31-
func New(zeroSSLService ZeroSSLService) *Service {
32-
return &Service{
33-
zeroSSLService: zeroSSLService,
31+
func NewStore(zeroSSL ZeroSSL) *Store {
32+
return &Store{
33+
zeroSSLService: zeroSSL,
3434
challenges: make(map[string]string),
3535
}
3636
}
3737

38-
func (s *Service) saveCertificate(filename string, certBytes [][]byte) error {
38+
func (s *Store) saveCertificate(filename string, certBytes [][]byte) error {
3939
file, err := os.Create(filename)
4040
if err != nil {
4141
return fmt.Errorf("create certificate file: %w", err)
@@ -50,7 +50,7 @@ func (s *Service) saveCertificate(filename string, certBytes [][]byte) error {
5050
return nil
5151
}
5252

53-
func (s *Service) savePrivateKey(filename string, privateKey crypto.PrivateKey) error {
53+
func (s *Store) savePrivateKey(filename string, privateKey crypto.PrivateKey) error {
5454
file, err := os.Create(filename)
5555
if err != nil {
5656
return fmt.Errorf("create private key file: %w", err)
@@ -64,7 +64,7 @@ func (s *Service) savePrivateKey(filename string, privateKey crypto.PrivateKey)
6464
return pem.Encode(file, &pem.Block{Type: "PRIVATE KEY", Bytes: privateKeyBytes})
6565
}
6666

67-
func (s *Service) LoadCertificate(filename string) (*x509.Certificate, error) {
67+
func (s *Store) LoadCertificate(filename string) (*x509.Certificate, error) {
6868
data, err := os.ReadFile(filename)
6969
if err != nil {
7070
return nil, fmt.Errorf("read certificate file: %w", err)
@@ -83,11 +83,11 @@ func (s *Service) LoadCertificate(filename string) (*x509.Certificate, error) {
8383
return nil, fmt.Errorf("no certificate found in %s", filename)
8484
}
8585

86-
func (s *Service) CertificateNeedsRenewal(cert *x509.Certificate) bool {
86+
func (s *Store) CertificateNeedsRenewal(cert *x509.Certificate) bool {
8787
return time.Now().Add(renewBeforeDays * 24 * time.Hour).After(cert.NotAfter)
8888
}
8989

90-
func (s *Service) ObtainOrRenewCertificate(ctx context.Context, domain, email, certFile, keyFile string) error {
90+
func (s *Store) ObtainOrRenewCertificate(ctx context.Context, domain, email, certFile, keyFile string) error {
9191
certs, privateKey, err := s.zeroSSLService.ObtainCertificate(ctx, domain, email, s.StoreChallenge)
9292
if err != nil {
9393
return fmt.Errorf("obtain certificate: %w", err)
@@ -105,20 +105,20 @@ func (s *Service) ObtainOrRenewCertificate(ctx context.Context, domain, email, c
105105
return nil
106106
}
107107

108-
func (s *Service) StoreChallenge(token, response string) {
108+
func (s *Store) StoreChallenge(token, response string) {
109109
s.challengeMu.Lock()
110110
defer s.challengeMu.Unlock()
111111
s.challenges[token] = response
112112
}
113113

114-
func (s *Service) GetChallengeResponse(token string) (string, bool) {
114+
func (s *Store) GetChallengeResponse(token string) (string, bool) {
115115
s.challengeMu.RLock()
116116
defer s.challengeMu.RUnlock()
117117
response, exists := s.challenges[token]
118118
return response, exists
119119
}
120120

121-
func (s *Service) CheckCertificate(ctx context.Context, domain, email, certDir string) error {
121+
func (s *Store) CheckCertificate(ctx context.Context, domain, email, certDir string) error {
122122
certFile := filepath.Join(certDir, domain+".crt")
123123
keyFile := filepath.Join(certDir, domain+".key")
124124

cron/cron.go renamed to internal/task/scheduler.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package cron
1+
package task
22

33
import (
44
"context"
@@ -12,18 +12,18 @@ type Runner interface {
1212
Run() error
1313
}
1414

15-
// Service handles the scheduling and execution of periodic tasks
16-
type Service struct {
15+
// Scheduler handles the scheduling and execution of periodic tasks
16+
type Scheduler struct {
1717
task func(context.Context) error
1818
time string
1919
ctx context.Context
2020
cancel context.CancelFunc
2121
}
2222

23-
// New creates a new cron Service
24-
func New(task func(context.Context) error, time string) *Service {
23+
// NewScheduler creates a new cron Scheduler
24+
func NewScheduler(task func(context.Context) error, time string) *Scheduler {
2525
ctx, cancel := context.WithCancel(context.Background())
26-
return &Service{
26+
return &Scheduler{
2727
task: task,
2828
time: time,
2929
ctx: ctx,
@@ -32,7 +32,7 @@ func New(task func(context.Context) error, time string) *Service {
3232
}
3333

3434
// Start begins the cron service
35-
func (s *Service) Start() {
35+
func (s *Scheduler) Start() {
3636
renewalTime, err := ParseTime(s.time)
3737
if err != nil {
3838
log.Fatalf("Invalid time format: %v", err)
@@ -64,7 +64,7 @@ func (s *Service) Start() {
6464
}
6565

6666
// Stop gracefully stops the cron service
67-
func (s *Service) Stop() {
67+
func (s *Scheduler) Stop() {
6868
s.cancel()
6969
}
7070

0 commit comments

Comments
 (0)