-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathmain.go
123 lines (101 loc) · 3.44 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package main
import (
"flag"
"fmt"
"io/ioutil"
"log"
"sync"
"time"
"gopkg.in/yaml.v2"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/tools/clientcmd"
"github.com/grafana/kubernetes-diff-logger/pkg/differ"
"github.com/grafana/kubernetes-diff-logger/pkg/signals"
"github.com/grafana/kubernetes-diff-logger/pkg/wrapper"
"github.com/pkg/errors"
)
var (
masterURL string
kubeconfig string
resyncPeriod time.Duration
namespace string
logAdded bool
logDeleted bool
configFile string
)
func init() {
flag.StringVar(&kubeconfig, "kubeconfig", "", "Path to a kubeconfig. Only required if out-of-cluster.")
flag.StringVar(&masterURL, "master", "", "The address of the Kubernetes API server. Overrides any value in kubeconfig. Only required if out-of-cluster.")
flag.DurationVar(&resyncPeriod, "resync", time.Second*30, "Periodic interval in which to force resync objects.")
flag.StringVar(&namespace, "namespace", "", "Filter updates by namespace. Leave empty to watch all.")
flag.BoolVar(&logAdded, "log-added", false, "Log when deployments are added.")
flag.BoolVar(&logDeleted, "log-deleted", false, "Log when deployments are deleted.")
flag.StringVar(&configFile, "config", "", "Path to config file. Required.")
}
func main() {
flag.Parse()
// build k8s client
config, err := clientcmd.BuildConfigFromFlags(masterURL, kubeconfig)
if err != nil {
log.Fatalf("Error building kubeconfig: %s", err.Error())
}
client, err := kubernetes.NewForConfig(config)
if err != nil {
log.Fatalf("kubernetes.NewForConfig failed: %v", err)
}
// build shared informer
var informerFactory informers.SharedInformerFactory
if namespace == "" {
informerFactory = informers.NewSharedInformerFactory(client, resyncPeriod)
} else {
informerFactory = informers.NewSharedInformerFactoryWithOptions(client, resyncPeriod, informers.WithNamespace(namespace))
}
stopCh := signals.SetupSignalHandler()
// load config
cfg := DefaultConfig()
err = loadConfig(configFile, &cfg)
if err != nil {
log.Fatalf("loadConfig failed: %v", err)
}
// build differs
var wg sync.WaitGroup
for _, cfgDiffer := range cfg.Differs {
informer, wrap, err := informerForName(cfgDiffer.Type, informerFactory)
if err != nil {
log.Fatalf("informerForName failed: %v", err)
}
output := differ.NewOutput(differ.JSON, logAdded, logDeleted)
d := differ.NewDiffer(cfgDiffer.NameFilter, wrap, informer, output)
wg.Add(1)
go func(differ *differ.Differ) {
defer wg.Done()
if err := d.Run(stopCh); err != nil {
log.Fatalf("Error running differ %v", err)
}
}(d)
}
informerFactory.Start(stopCh)
wg.Wait()
}
func informerForName(name string, i informers.SharedInformerFactory) (cache.SharedInformer, wrapper.Wrap, error) {
switch name {
case "deployment":
return i.Apps().V1().Deployments().Informer(), wrapper.WrapDeployment, nil
case "statefulset":
return i.Apps().V1().StatefulSets().Informer(), wrapper.WrapStatefulSet, nil
case "daemonset":
return i.Apps().V1().DaemonSets().Informer(), wrapper.WrapDaemonSet, nil
case "cronjob":
return i.Batch().V1().CronJobs().Informer(), wrapper.WrapCronJob, nil
}
return nil, nil, fmt.Errorf("Unsupported informer name %s", name)
}
func loadConfig(filename string, cfg *Config) error {
buf, err := ioutil.ReadFile(filename)
if err != nil {
return errors.Wrap(err, "Error reading config file")
}
return yaml.UnmarshalStrict(buf, &cfg)
}