-
Notifications
You must be signed in to change notification settings - Fork 91
/
main.go
182 lines (154 loc) · 7.46 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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
package main
import (
"flag"
"fmt"
"os"
"path/filepath"
"runtime"
"github.com/cloud66-oss/habitus/api"
"github.com/cloud66-oss/habitus/build"
"github.com/cloud66-oss/habitus/configuration"
"github.com/getsentry/raven-go"
"github.com/op/go-logging"
)
var prettyFormat = logging.MustStringFormatter(
"%{color}▶ %{message} %{color:reset}",
)
var plainFormat = logging.MustStringFormatter(
"[%{level}] - %{message}",
)
var (
flagLevel string
flagShowHelp bool
flagShowVersion bool
flagPrettyLog bool
VERSION string = "dev"
BUILD_DATE string = ""
)
func init() {
//sentry DSN setup
raven.SetDSN("https://c5b047b41b3f4de38fc93cb3df75fd43:[email protected]/187936")
}
const DEFAULT_DOCKER_HOST = "unix:///var/run/docker.sock"
func main() {
args := os.Args[1:]
defer recoverPanic()
var log = logging.MustGetLogger("habitus")
logging.SetFormatter(plainFormat)
config := configuration.CreateConfig()
flag.StringVar(&config.Buildfile, "f", "build.yml", "Build file path. Defaults to build.yml in the workdir")
flag.StringVar(&config.Workdir, "d", "", "Work directory for this build. Defaults to the current directory")
flag.BoolVar(&config.NoCache, "no-cache", false, "Don't use cache in build")
flag.BoolVar(&config.SuppressOutput, "suppress", false, "Suppress build output")
flag.BoolVar(&config.RmTmpContainers, "rm", true, "Remove intermediate containers")
flag.BoolVar(&config.ForceRmTmpContainer, "force-rm", false, "Force remove intermediate containers")
flag.StringVar(&config.UniqueID, "uid", "", "Unique ID for the build. Used only for multi-tenanted build environments")
flag.StringVar(&flagLevel, "level", "debug", "Log level: debug, info, notice, warning, error and critical")
flag.BoolVar(&flagPrettyLog, "pretty", true, "Display logs with color and formatting")
dockerhost, ok := os.LookupEnv("DOCKER_HOST")
if !ok {
dockerhost = DEFAULT_DOCKER_HOST
}
flag.StringVar(&config.DockerHost, "host", dockerhost, "Docker host link. Uses DOCKER_HOST if missing.")
flag.StringVar(&config.DockerCert, "certs", os.Getenv("DOCKER_CERT_PATH"), "Docker cert folder. Uses DOCKER_CERT_PATH if missing")
flag.Var(&config.EnvVars, "env", "Environment variables to be used in the build.yml. Uses parent process environment variables if empty")
flag.Var(&config.BuildArgs, "build", "Build arguments to be used during each Dockerfile build step.")
flag.StringVar(&config.Network, "network", "", "Set the networking mode for the RUN instructions during build. See `networkmode` in https://docs.docker.com/engine/api/v1.25/#operation/ImageBuild for available values. If omitted, the \"default\" bridge network is used, which is the same behavior as `docker build`.")
flag.BoolVar(&config.KeepSteps, "keep-all", false, "Overrides the keep flag for all steps. Used for debugging")
flag.BoolVar(&config.KeepArtifacts, "keep-artifacts", false, "Keep the temporary artifacts created on the host during build. Used for debugging")
flag.BoolVar(&config.UseTLS, "use-tls", os.Getenv("DOCKER_TLS_VERIFY") == "1", "Establish TLS connection with Docker daemon. Uses DOCKER_TLS_VERIFY if missing")
flag.BoolVar(&config.UseStatForPermissions, "use-stat", true, "Uses the stat command inside your container to get the arfifact permissions")
flag.BoolVar(&config.NoSquash, "no-cleanup", false, "Skip cleanup commands for this run. Used for debugging")
flag.BoolVar(&config.FroceRmImages, "force-rmi", false, "Force remove of unwanted images")
flag.BoolVar(&config.NoPruneRmImages, "noprune-rmi", false, "No pruning of unwanted images")
flag.StringVar(&config.OsType, "os", "debian", "Specify the OS that the build occurs in")
flag.BoolVar(&flagShowHelp, "help", false, "Display the help")
flag.BoolVar(&flagShowVersion, "version", false, "Display version information")
flag.IntVar(&config.ApiPort, "port", 8080, "Port to server the API")
flag.StringVar(&config.ApiBinding, "binding", "192.168.99.1", "Network address to bind the API to. (see documentation for more info)")
flag.BoolVar(&config.SecretService, "secrets", false, "Turn Secrets Service on or off")
flag.BoolVar(&config.AllowAfterBuildCommands, "after-build-commands", false, "Allow to run arbitrary commands on the host after build")
flag.StringVar(&config.SecretProviders, "sec-providers", "file,env", "All available secret providers. Comma separated")
flag.StringVar(&config.DockerMemory, "docker-memory", "", "Memory limits to apply to Docker build operations. More: https://docs.docker.com/engine/reference/commandline/build")
flag.StringVar(&config.DockerCPUSetCPUs, "docker-cpuset-cpus", "", "CPU binding limits to apply to Docker build operations. More: https://docs.docker.com/engine/reference/commandline/build")
flag.IntVar(&config.DockerCPUShares, "docker-cpu-shares", 1024, "CPU share weighting to apply to Docker build operations. More: https://docs.docker.com/engine/reference/commandline/build")
flag.BoolVar(&config.UseAuthenticatedSecretServer, "authentication-secret-server", false, "Enable basic authentication for secret server")
flag.StringVar(&config.AuthenticatedSecretServerPassword, "password-secret-server", "admin", "The password for basic authentication.")
flag.StringVar(&config.AuthenticatedSecretServerUser, "user-secret-server", "habitus", "The user for basic authentication.")
config.Logger = *log
flag.Parse()
if flagPrettyLog {
logging.SetFormatter(prettyFormat)
}
if flagShowHelp || (len(args) > 0 && args[0] == "help") {
fmt.Println("Habitus - (c) 2016 Cloud 66 Inc.")
flag.PrintDefaults()
return
}
if flagShowVersion || (len(args) > 0 && args[0] == "version") {
if BUILD_DATE == "" {
fmt.Printf("Habitus - v%s (c) 2017 Cloud 66 Inc.\n", VERSION)
} else {
fmt.Printf("Habitus - v%s (%s) (c) 2017 Cloud 66 Inc.\n", VERSION, BUILD_DATE)
}
return
}
// The -os flag allows free form text. Validate what was specified
if !config.ValidateOsType() {
fmt.Println("Invalid OS name")
fmt.Println("Please choose from ", configuration.OsTypes)
return
}
level, err := logging.LogLevel(flagLevel)
if err != nil {
fmt.Println("Invalid log level value. Falling back to debug")
level = logging.DEBUG
}
logging.SetLevel(level, "habitus")
if config.Workdir == "" {
if curr, err := os.Getwd(); err != nil {
log.Fatal("Failed to get the current directory")
os.Exit(1)
} else {
config.Workdir = curr
}
}
if config.Buildfile == "build.yml" {
config.Buildfile = filepath.Join(config.Workdir, "build.yml")
}
c, err := build.LoadBuildFromFile(&config)
if err != nil {
log.Fatalf("Failed: %s", err.Error())
}
if c.IsPrivileged && os.Getenv("SUDO_USER") == "" {
log.Fatal("Some of the build steps require admin privileges (sudo). Please run with sudo\nYou might want to use --certs=$DOCKER_CERT_PATH --host=$DOCKER_HOST params to make sure all environment variables are available to the process")
os.Exit(1)
}
b := build.NewBuilder(c, &config)
if config.SecretService {
// start the API
secret_service := &api.Server{Builder: b}
err = secret_service.StartServer(VERSION)
if err != nil {
log.Fatalf("Cannot start API server due to %s", err.Error())
os.Exit(2)
}
}
err = b.StartBuild()
if err != nil {
log.Errorf("Error during build %s", err.Error())
}
}
func recoverPanic() {
if VERSION != "dev" {
raven.CapturePanicAndWait(func() {
if rec := recover(); rec != nil {
panic(rec)
}
}, map[string]string{
"Version": VERSION,
"Platform": runtime.GOOS,
"Architecture": runtime.GOARCH,
"goversion": runtime.Version()})
}
}