-
Notifications
You must be signed in to change notification settings - Fork 221
/
builtin_builder.go
149 lines (124 loc) · 3.95 KB
/
builtin_builder.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
package imgsrc
import (
"fmt"
"context"
"github.com/pkg/errors"
"github.com/superfly/flyctl/internal/build/imgsrc/builtins"
"github.com/superfly/flyctl/internal/cmdfmt"
"github.com/superfly/flyctl/internal/metrics"
"github.com/superfly/flyctl/iostreams"
"github.com/superfly/flyctl/terminal"
)
type builtinBuilder struct{}
func (*builtinBuilder) Name() string {
return "Builtin"
}
func (*builtinBuilder) Run(ctx context.Context, dockerFactory *dockerClientFactory, streams *iostreams.IOStreams, opts ImageOptions, build *build) (*DeploymentImage, string, error) {
build.BuildStart()
if !dockerFactory.mode.IsAvailable() {
note := "docker daemon not available, skipping"
terminal.Debug(note)
build.BuildFinish()
return nil, note, nil
}
if opts.BuiltIn == "" {
note := "fly.toml does not include a builtin config"
terminal.Debug(note)
build.BuildFinish()
return nil, note, nil
}
builtin, err := builtins.GetBuiltin(opts.BuiltIn)
if err != nil {
build.BuildFinish()
return nil, "", err
}
// Expand args
vdockerfile, err := builtin.GetVDockerfile(opts.BuiltInSettings)
if err != nil {
build.BuildFinish()
return nil, "", err
}
build.BuilderInitStart()
docker, err := dockerFactory.buildFn(ctx, build)
if err != nil {
build.BuilderInitFinish()
build.BuildFinish()
return nil, "", errors.Wrap(err, "error connecting to docker")
}
defer docker.Close() // skipcq: GO-S2307
build.BuilderInitFinish()
defer clearDeploymentTags(ctx, docker, opts.Tag)
build.ContextBuildStart()
cmdfmt.PrintBegin(streams.ErrOut, "Creating build context")
archiveOpts := archiveOptions{
sourcePath: opts.WorkingDir,
compressed: dockerFactory.IsRemote(),
}
excludes, err := readDockerignore(opts.WorkingDir, opts.IgnorefilePath, "")
if err != nil {
build.BuildFinish()
return nil, "", errors.Wrap(err, "error reading .dockerignore")
}
archiveOpts.exclusions = excludes
// copy dockerfile into the archive if it's outside the context dir
archiveOpts.additions = map[string][]byte{
"Dockerfile": []byte(vdockerfile),
}
r, err := archiveDirectory(archiveOpts)
if err != nil {
build.ContextBuildFinish()
build.BuildFinish()
return nil, "", errors.Wrap(err, "error archiving build context")
}
build.ContextBuildFinish()
cmdfmt.PrintDone(streams.ErrOut, "Creating build context done")
build.ImageBuildStart()
var imageID string
serverInfo, err := docker.Info(ctx)
if err != nil {
terminal.Debug("error fetching docker server info:", err)
} else {
build.SetBuilderMetaPart2(false, serverInfo.ServerVersion, fmt.Sprintf("%s/%s/%s", serverInfo.OSType, serverInfo.Architecture, serverInfo.OSVersion))
}
cmdfmt.PrintBegin(streams.ErrOut, "Building image with Docker")
msg := fmt.Sprintf("docker host: %s %s %s", serverInfo.ServerVersion, serverInfo.OSType, serverInfo.Architecture)
cmdfmt.PrintDone(streams.ErrOut, msg)
buildArgs, err := normalizeBuildArgsForDocker(opts.BuildArgs)
if err != nil {
build.ImageBuildFinish()
build.BuildFinish()
return nil, "", fmt.Errorf("error parsing build args: %w", err)
}
imageID, err = runClassicBuild(ctx, streams, docker, r, opts, "", buildArgs)
if err != nil {
if dockerFactory.IsRemote() {
metrics.SendNoData(ctx, "remote_builder_failure")
}
build.ImageBuildFinish()
build.BuildFinish()
return nil, "", errors.Wrap(err, "error building")
}
build.ImageBuildFinish()
build.BuildFinish()
cmdfmt.PrintDone(streams.ErrOut, "Building image done")
if opts.Publish {
build.PushStart()
cmdfmt.PrintBegin(streams.ErrOut, "Pushing image to fly")
if err := pushToFly(ctx, docker, streams, opts.Tag); err != nil {
build.PushFinish()
return nil, "", err
}
build.PushFinish()
cmdfmt.PrintDone(streams.ErrOut, "Pushing image done")
}
img, _, err := docker.ImageInspectWithRaw(ctx, imageID)
if err != nil {
return nil, "", errors.Wrap(err, "count not find built image")
}
fmt.Println(img)
return &DeploymentImage{
ID: img.ID,
Tag: opts.Tag,
Size: img.Size,
}, "", nil
}