-
Notifications
You must be signed in to change notification settings - Fork 4
/
main.go
123 lines (101 loc) · 3.1 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 (
"context"
"errors"
"flag"
"fmt"
"os"
"time"
"github.com/docker/docker/client"
"github.com/operator-framework/operator-sdk/pkg/log/zap"
"github.com/spf13/pflag"
"github.com/supremind/container-snapshot/pkg/constants"
"github.com/supremind/container-snapshot/pkg/worker"
"github.com/supremind/container-snapshot/version"
"github.com/supremind/pkg/shutdown"
corev1 "k8s.io/api/core/v1"
logf "sigs.k8s.io/controller-runtime/pkg/log"
)
const (
defaultConfigRoot = "/config"
defaultTimeout = 30 * time.Minute
envTimeout = "TIMEOUT"
envNamespace = "NAMESPACE"
)
var log = logf.Log.WithName("container snapshot worker").WithValues("version", version.Version)
func main() {
// Add the zap logger flag set to the CLI. The flag set must
// be added before calling pflag.Parse().
pflag.CommandLine.AddFlagSet(zap.FlagSet())
// Add flags registered by imported packages (e.g. glog and
// controller-runtime)
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
logf.SetLogger(zap.Logger())
go func() {
shutdown.BornToDie(context.Background())
log.Info("shutdown by signals")
os.Exit(1)
}()
e := run()
if e != nil {
log.Error(e, "snapshot worker failed")
os.Exit(1)
}
}
func run() error {
opt := &worker.SnapshotOptions{}
pflag.StringVarP(&opt.Container, "container", "c", "", "required, docker name of the container going to take a snapshot")
pflag.StringVarP(&opt.Image, "image", "i", "", "required, name of the snapshot image")
pflag.StringVar(&opt.Author, "author", "", "snapshot author")
pflag.StringVar(&opt.Comment, "comment", "", "comment")
var configRoot string
var snapshot string
pflag.StringVar(&configRoot, "config", defaultConfigRoot, "root path of docker config files, default is /config")
pflag.StringVar(&snapshot, "snapshot", "", "required, snapshot name")
pflag.Parse()
namespace := os.Getenv(envNamespace)
if opt.Container == "" || opt.Image == "" || snapshot == "" || namespace == "" {
return errors.New("invalid arguments")
}
cli, e := client.NewEnvClient()
if e != nil {
return fmt.Errorf("create docker client: %w", e)
}
log = log.WithValues("namespace", namespace, "snapshot", snapshot, "container", opt.Container, "image", opt.Image)
c, e := worker.New(cli, configRoot)
if e != nil {
return e
}
timeout := defaultTimeout
if t := os.Getenv(envTimeout); t != "" {
d, _ := time.ParseDuration(t)
if d > 0 {
timeout = d
}
}
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
e = c.TakeSnapshot(ctx, opt)
if e != nil {
log.Error(e, "take snapshot failed")
var code int32 = 127
if errors.Is(e, worker.ErrInvalidImage) {
code = constants.ExitCodeInvalidImage
} else if errors.Is(e, worker.ErrCommit) {
code = constants.ExitCodeDockerCommit
} else if errors.Is(e, worker.ErrPush) {
code = constants.ExitCodeDockerPush
}
os.Exit(int(code))
}
return e
}
func writeTerminationLog(e error) error {
f, e := os.Create(corev1.TerminationMessagePathDefault)
if e != nil {
return fmt.Errorf("open ternination message file: %w", e)
}
defer f.Close()
_, e = f.WriteString(e.Error())
return e
}