Skip to content

Commit cfa8244

Browse files
committed
Remove KfConfig
Last effort to make pkg looks more like reusable packages: getting rid of the KfConfig we used to pass to every package. Also migrate observer & controller to the small logger interface, so it can easily be replaced or mocked.
1 parent b7d138e commit cfa8244

File tree

7 files changed

+128
-212
lines changed

7 files changed

+128
-212
lines changed

cmd/execute.go

+18-35
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,9 @@ import (
55
"os"
66
"os/signal"
77
"syscall"
8-
"time"
98

109
"github.com/spf13/cobra"
1110

12-
"github.com/bpineau/katafygio/config"
1311
"github.com/bpineau/katafygio/pkg/client"
1412
"github.com/bpineau/katafygio/pkg/controller"
1513
"github.com/bpineau/katafygio/pkg/event"
@@ -22,9 +20,21 @@ import (
2220

2321
const appName = "katafygio"
2422

25-
func runE(cmd *cobra.Command, args []string) (err error) {
23+
var (
24+
restcfg client.Interface
25+
26+
// RootCmd is our main entry point, launching runE()
27+
RootCmd = &cobra.Command{
28+
Use: appName,
29+
Short: "Backup Kubernetes cluster as yaml files",
30+
Long: "Backup Kubernetes cluster as yaml files in a git repository.\n" +
31+
"--exclude-kind (-x) and --exclude-object (-y) may be specified several times.",
32+
PreRun: bindConf,
33+
RunE: runE,
34+
}
35+
)
2636

27-
resync := time.Duration(resyncInt) * time.Second
37+
func runE(cmd *cobra.Command, args []string) (err error) {
2838
logger := log.New(logLevel, logServer, logOutput)
2939

3040
if restcfg == nil {
@@ -34,34 +44,21 @@ func runE(cmd *cobra.Command, args []string) (err error) {
3444
}
3545
}
3646

37-
conf := &config.KfConfig{
38-
DryRun: dryRun,
39-
DumpMode: dumpMode,
40-
Logger: logger,
41-
LocalDir: localDir,
42-
GitURL: gitURL,
43-
Filter: filter,
44-
ExcludeKind: exclkind,
45-
ExcludeObject: exclobj,
46-
HealthPort: healthP,
47-
Client: restcfg,
48-
ResyncIntv: resync,
49-
}
50-
5147
repo, err := git.New(logger, dryRun, localDir, gitURL).Start()
5248
if err != nil {
53-
conf.Logger.Fatalf("failed to start git repo handler: %v", err)
49+
return fmt.Errorf("failed to start git repo handler: %v", err)
5450
}
5551

5652
evts := event.New()
53+
fact := controller.NewFactory(logger, filter, resyncInt, exclobj)
5754
reco := recorder.New(logger, evts, localDir, resyncInt*2, dryRun).Start()
58-
obsv := observer.New(conf, evts, &controller.Factory{}).Start()
55+
obsv := observer.New(logger, restcfg, evts, fact, exclkind).Start()
5956
http := health.New(logger, healthP).Start()
6057

6158
sigterm := make(chan os.Signal, 1)
6259
signal.Notify(sigterm, syscall.SIGTERM)
6360
signal.Notify(sigterm, syscall.SIGINT)
64-
if !conf.DumpMode {
61+
if !dumpMode {
6562
<-sigterm
6663
}
6764

@@ -73,20 +70,6 @@ func runE(cmd *cobra.Command, args []string) (err error) {
7370
return nil
7471
}
7572

76-
var (
77-
restcfg client.Interface
78-
79-
// RootCmd is our main entry point, launching runE()
80-
RootCmd = &cobra.Command{
81-
Use: appName,
82-
Short: "Backup Kubernetes cluster as yaml files",
83-
Long: "Backup Kubernetes cluster as yaml files in a git repository.\n" +
84-
"--exclude-kind (-x) and --exclude-object (-y) may be specified several times.",
85-
PreRun: bindConf,
86-
RunE: runE,
87-
}
88-
)
89-
9073
// Execute adds all child commands to the root command and sets their flags.
9174
func Execute() error {
9275
return RootCmd.Execute()

config/config.go

-55
This file was deleted.

config/config_test.go

-30
This file was deleted.

pkg/controller/controller.go

+60-32
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010
"strings"
1111
"time"
1212

13-
"github.com/bpineau/katafygio/config"
1413
"github.com/bpineau/katafygio/pkg/event"
1514

1615
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -37,25 +36,44 @@ type Interface interface {
3736
Stop()
3837
}
3938

39+
type logger interface {
40+
Infof(format string, args ...interface{})
41+
Errorf(format string, args ...interface{})
42+
}
43+
4044
// Factory generate controllers
41-
type Factory struct{}
45+
type Factory struct {
46+
logger logger
47+
filter string
48+
resyncIntv time.Duration
49+
excluded []string
50+
}
4251

4352
// Controller is a generic kubernetes controller
4453
type Controller struct {
45-
name string
46-
stopCh chan struct{}
47-
doneCh chan struct{}
48-
syncCh chan struct{}
49-
notifier event.Notifier
50-
config *config.KfConfig
51-
queue workqueue.RateLimitingInterface
52-
informer cache.SharedIndexInformer
54+
name string
55+
stopCh chan struct{}
56+
doneCh chan struct{}
57+
syncCh chan struct{}
58+
notifier event.Notifier
59+
queue workqueue.RateLimitingInterface
60+
informer cache.SharedIndexInformer
61+
logger logger
62+
resyncIntv time.Duration
63+
excluded []string
5364
}
5465

5566
// New return a kubernetes controller using the provided client
56-
func New(client cache.ListerWatcher, notifier event.Notifier, name string, config *config.KfConfig) *Controller {
57-
58-
selector := metav1.ListOptions{LabelSelector: config.Filter}
67+
func New(client cache.ListerWatcher,
68+
notifier event.Notifier,
69+
log logger,
70+
name string,
71+
filter string,
72+
resync time.Duration,
73+
excluded []string,
74+
) *Controller {
75+
76+
selector := metav1.ListOptions{LabelSelector: filter}
5977
lw := &cache.ListWatch{
6078
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
6179
return client.List(selector)
@@ -68,7 +86,7 @@ func New(client cache.ListerWatcher, notifier event.Notifier, name string, confi
6886
informer := cache.NewSharedIndexInformer(
6987
lw,
7088
&unstructured.Unstructured{},
71-
config.ResyncIntv,
89+
resync,
7290
cache.Indexers{},
7391
)
7492

@@ -96,20 +114,22 @@ func New(client cache.ListerWatcher, notifier event.Notifier, name string, confi
96114
})
97115

98116
return &Controller{
99-
stopCh: make(chan struct{}),
100-
doneCh: make(chan struct{}),
101-
syncCh: make(chan struct{}, 1),
102-
notifier: notifier,
103-
name: name,
104-
config: config,
105-
queue: queue,
106-
informer: informer,
117+
stopCh: make(chan struct{}),
118+
doneCh: make(chan struct{}),
119+
syncCh: make(chan struct{}, 1),
120+
notifier: notifier,
121+
name: name,
122+
queue: queue,
123+
informer: informer,
124+
logger: log,
125+
resyncIntv: resync,
126+
excluded: excluded,
107127
}
108128
}
109129

110130
// Start launchs the controller in the background
111131
func (c *Controller) Start() {
112-
c.config.Logger.Infof("Starting %s controller", c.name)
132+
c.logger.Infof("Starting %s controller", c.name)
113133
defer utilruntime.HandleCrash()
114134

115135
go c.informer.Run(c.stopCh)
@@ -126,7 +146,7 @@ func (c *Controller) Start() {
126146

127147
// Stop halts the controller
128148
func (c *Controller) Stop() {
129-
c.config.Logger.Infof("Stopping %s controller", c.name)
149+
c.logger.Infof("Stopping %s controller", c.name)
130150
<-c.syncCh
131151
close(c.stopCh)
132152
c.queue.ShutDown()
@@ -148,7 +168,7 @@ func (c *Controller) processNextItem() bool {
148168
defer c.queue.Done(key)
149169

150170
if strings.Compare(key.(string), canaryKey) == 0 {
151-
c.config.Logger.Infof("Initial sync completed for %s controller", c.name)
171+
c.logger.Infof("Initial sync completed for %s controller", c.name)
152172
c.syncCh <- struct{}{}
153173
c.queue.Forget(key)
154174
return true
@@ -160,11 +180,11 @@ func (c *Controller) processNextItem() bool {
160180
// No error, reset the ratelimit counters
161181
c.queue.Forget(key)
162182
} else if c.queue.NumRequeues(key) < maxProcessRetry {
163-
c.config.Logger.Errorf("Error processing %s (will retry): %v", key, err)
183+
c.logger.Errorf("Error processing %s (will retry): %v", key, err)
164184
c.queue.AddRateLimited(key)
165185
} else {
166186
// err != nil and too many retries
167-
c.config.Logger.Errorf("Error processing %s (giving up): %v", key, err)
187+
c.logger.Errorf("Error processing %s (giving up): %v", key, err)
168188
c.queue.Forget(key)
169189
}
170190

@@ -178,7 +198,7 @@ func (c *Controller) processItem(key string) error {
178198
return fmt.Errorf("error fetching %s from store: %v", key, err)
179199
}
180200

181-
for _, obj := range c.config.ExcludeObject {
201+
for _, obj := range c.excluded {
182202
if strings.Compare(strings.ToLower(obj), strings.ToLower(c.name+":"+key)) == 0 {
183203
return nil
184204
}
@@ -200,8 +220,6 @@ func (c *Controller) processItem(key string) error {
200220
delete(md, attr)
201221
}
202222

203-
c.config.Logger.Debugf("Found %s/%s [%s]", obj.GetAPIVersion(), obj.GetKind(), key)
204-
205223
yml, err := yaml.Marshal(obj)
206224
if err != nil {
207225
return fmt.Errorf("failed to marshal %s: %v", key, err)
@@ -215,7 +233,17 @@ func (c *Controller) enqueue(notif *event.Notification) {
215233
c.notifier.Send(notif)
216234
}
217235

236+
// NewFactory create a controller factory
237+
func NewFactory(logger logger, filter string, resync int, excluded []string) *Factory {
238+
return &Factory{
239+
logger: logger,
240+
filter: filter,
241+
resyncIntv: time.Duration(resync) * time.Second,
242+
excluded: excluded,
243+
}
244+
}
245+
218246
// NewController create a controller.Controller
219-
func (f *Factory) NewController(client cache.ListerWatcher, notifier event.Notifier, name string, config *config.KfConfig) Interface {
220-
return New(client, notifier, name, config)
247+
func (f *Factory) NewController(client cache.ListerWatcher, notifier event.Notifier, name string) Interface {
248+
return New(client, notifier, f.logger, name, f.filter, f.resyncIntv, f.excluded)
221249
}

0 commit comments

Comments
 (0)