-
Notifications
You must be signed in to change notification settings - Fork 53
Expand file tree
/
Copy pathbuild.go
More file actions
147 lines (120 loc) · 3.63 KB
/
Copy pathbuild.go
File metadata and controls
147 lines (120 loc) · 3.63 KB
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
package cloud
import (
"bytes"
"errors"
"fmt"
"kool-dev/kool/core/builder"
"kool-dev/kool/core/environment"
"kool-dev/kool/core/shell"
"kool-dev/kool/services/cloud/api"
"os"
"path/filepath"
"strings"
yaml "gopkg.in/yaml.v2"
)
func BuildPushImageForDeploy(service string, config *DeployConfigService, deploy *api.DeployCreateResponse, platform string) (err error) {
if config.Build == nil {
err = errors.New("service " + service + " has no build configuration")
return
}
var (
env = environment.NewEnvStorage()
isVerbose = env.IsTrue("KOOL_VERBOSE")
sh = shell.NewShell()
image = fmt.Sprintf("%s/%s:%s-%s", deploy.Config.ImagePrefix, deploy.Config.ImageRepository, service, deploy.Config.ImageTag)
output string
)
// create a default io.Reader for stdin
var in = bytes.NewBuffer([]byte{})
sh.SetInStream(in)
dockerBuild := builder.NewCommand("docker", "build", "-t", image, "--platform", platform)
if folder, isStr := (*config.Build).(string); isStr {
// this should be a simple build with a context folder
// docker build -t <image>:<tag> <folder>
dockerBuild.AppendArgs(parseContext(folder, env.Get("PWD")))
} else {
// it's not a string, so it should be a map...
var buildConfig *DeployConfigBuild
if buildConfig, err = parseBuild(*config.Build); err != nil {
return
}
if buildConfig.Dockerfile != nil {
dockerBuild.AppendArgs("-f", *buildConfig.Dockerfile)
}
if buildConfig.Args != nil {
for k, v := range *buildConfig.Args {
dockerBuild.AppendArgs("--build-arg", fmt.Sprintf("%s=%s", k, parseDeployEnvs(v, deploy.Deploy.Environment.Env)))
}
}
if buildConfig.Context != nil {
dockerBuild.AppendArgs(parseContext(*buildConfig.Context, env.Get("PWD")))
}
}
if err = sh.Interactive(dockerBuild); err != nil {
return
}
if _, err = in.Write([]byte(deploy.Docker.Password)); err != nil {
return
}
// login & push...
dockerLogin := builder.NewCommand("docker", "login", "-u", deploy.Docker.Login, "--password-stdin", deploy.Config.ImagePrefix)
if output, err = sh.Exec(dockerLogin); err != nil {
if isVerbose {
fmt.Println(output)
}
return
}
dockerPush := builder.NewCommand("docker", "push", image)
if err = sh.Interactive(dockerPush); err != nil {
return
}
dockerLogout := builder.NewCommand("docker", "logout")
if output, err = sh.Exec(dockerLogout); err != nil {
if isVerbose {
fmt.Println(output)
}
return
}
return
}
// parseContext parses the build context from the build configuration
// changing . to the current working directory
func parseContext(context string, cwd string) (parsed string) {
context = strings.Trim(context, " ")
parsed = context
if strings.HasPrefix(context, "..") {
// relative path
parsed = filepath.Join(cwd, context)
} else if strings.HasPrefix(context, ".") {
// relative path
parsed = filepath.Join(cwd, strings.TrimPrefix(context, "."))
}
return
}
func parseBuild(build interface{}) (config *DeployConfigBuild, err error) {
var (
b []byte
)
config = &DeployConfigBuild{}
if b, err = yaml.Marshal(build); err != nil {
return
}
err = yaml.Unmarshal(b, config)
return
}
func parseDeployEnvs(i interface{}, env interface{}) string {
// workaround to allow for escaping $ with a double $$
_ = os.Setenv("$", "$")
var value = os.ExpandEnv(fmt.Sprintf("%s", i))
if strings.Contains(value, "{{") && strings.Contains(value, "}}") {
// we have something to replace!
if recs, ok := env.(map[string]interface{}); ok {
for k, v := range recs {
if strings.Contains(value, "{{"+k+"}}") {
value = strings.ReplaceAll(value, "{{"+k+"}}", fmt.Sprintf("%v", v))
}
}
}
}
return value
}