Skip to content

Commit b9572f3

Browse files
committed
feat(builder): unified build model
1 parent ccd7e99 commit b9572f3

12 files changed

Lines changed: 78 additions & 99 deletions

File tree

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ The builder is primarily a git server that responds to `git push`es by executing
2323
- If the `BUILDER_STORAGE` environment variable is other than `minio`, attempts to create the appropriate storage driver and saves using this driver.
2424
- Otherwise, if `BUILDER_STORAGE` is `minio` and the `DRYCC_MINIO_SERVICE_HOST` and `DRYCC_MINIO_SERVICE_PORT` environment variables exist (these are standard [Kubernetes service discovery environment variables](http://kubernetes.io/docs/user-guide/services/#environment-variables)), saves to the [S3 API][s3-api-ref] compatible server at `http://$DRYCC_MINIO_SERVICE_HOST:$DRYCC_MINIO_SERVICE_HOST`
2525
3. Starts a new [Kubernetes Pod](http://kubernetes.io/docs/user-guide/pods/) to build the code, according to the following rules:
26-
- If a `Dockerfile` is present in the codebase, starts a [`imagebuilder`](https://github.com/drycc/imagebuilder) pod, configured to download the code to build from the URL computed in the previous step.
27-
- Otherwise, starts a [`buildpacker`](https://github.com/drycc/buildpacker) pod, configured to download the code to build from the URL computed in the previous step.
26+
- If there is a `Dockerfile`, build the container with imagebuilder
27+
- Otherwise, use imagebuilder to build CNCF native buildpack
28+
- You can use `DRYCC_STACK` specifies the build type. Currently, it supports two types: `buildpack` and `container`
2829

2930
# Supported Off-Cluster Storage Backends
3031

charts/builder/templates/builder-deployment.yaml

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,6 @@ spec:
5858
# Set GIT_LOCK_TIMEOUT to number of minutes you want to wait to git push again to the same repository
5959
- name: "GIT_LOCK_TIMEOUT"
6060
value: "30"
61-
- name: buildpackER_IMAGE_PULL_POLICY
62-
valueFrom:
63-
configMapKeyRef:
64-
name: build pa c ker-config
65-
key: image_pull_policy
6661
- name: IMAGEBUILDER_IMAGE_PULL_POLICY
6762
valueFrom:
6863
configMapKeyRef:
@@ -108,9 +103,6 @@ spec:
108103
- name: objectstore-creds
109104
mountPath: /var/run/secrets/drycc/objectstore/creds
110105
readOnly: true
111-
- name: buildpacker-config
112-
mountPath: /etc/buildpacker
113-
readOnly: true
114106
- name: imagebuilder-config
115107
mountPath: /etc/imagebuilder
116108
readOnly: true
@@ -124,9 +116,6 @@ spec:
124116
- name: objectstore-creds
125117
secret:
126118
secretName: objectstorage-keyfile
127-
- name: buildpacker-config
128-
configMap:
129-
name: buildpacker-config
130119
- name: imagebuilder-config
131120
configMap:
132121
name: imagebuilder-config

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ require (
88
github.com/codegangsta/cli v1.9.0
99
github.com/docker/distribution v2.7.1+incompatible
1010
github.com/docker/go-metrics v0.0.1 // indirect
11-
github.com/drycc/controller-sdk-go v0.0.0-20201015065118-cb8f4f5e9745
11+
github.com/drycc/controller-sdk-go v0.0.0-20210629042308-95dbca4156e7
1212
github.com/drycc/pkg v0.0.0-20200811173146-1f2b2781a852
1313
github.com/gorilla/mux v1.7.4 // indirect
1414
github.com/kelseyhightower/envconfig v1.2.0

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ github.com/drycc/controller-sdk-go v0.0.0-20200829135849-1d24c6efe272 h1:ez+63Rq
5151
github.com/drycc/controller-sdk-go v0.0.0-20200829135849-1d24c6efe272/go.mod h1:mF8/kZ/E4oDHCtfUVS790Frm8oVzZkoCGCKYT2eWQro=
5252
github.com/drycc/controller-sdk-go v0.0.0-20201015065118-cb8f4f5e9745 h1:C3Byx1KvZtzuilCp5aikRa5hbXCUhiy8u4Iv6ATyDcI=
5353
github.com/drycc/controller-sdk-go v0.0.0-20201015065118-cb8f4f5e9745/go.mod h1:mF8/kZ/E4oDHCtfUVS790Frm8oVzZkoCGCKYT2eWQro=
54+
github.com/drycc/controller-sdk-go v0.0.0-20210629042308-95dbca4156e7 h1:Ujpe0wvzPBGd/IoBOwqNoS4XSYziw1vF0U9Jr2MjrCk=
55+
github.com/drycc/controller-sdk-go v0.0.0-20210629042308-95dbca4156e7/go.mod h1:mF8/kZ/E4oDHCtfUVS790Frm8oVzZkoCGCKYT2eWQro=
5456
github.com/drycc/pkg v0.0.0-20200730070607-a183b894cef1 h1:k8fWNiR7LVmy3lYFDuAuOw+ATJNkTjChaE3AeU0B6u8=
5557
github.com/drycc/pkg v0.0.0-20200730070607-a183b894cef1/go.mod h1:H6rDYnCiVX4k0B8T57myWlRMQoTx3hsvyAQV9//4T2Q=
5658
github.com/drycc/pkg v0.0.0-20200811173146-1f2b2781a852 h1:OsWH7jrv2i32rkvHFuj3yVpGMR+A6heRge9tm01XR/U=

pkg/gitreceive/build.go

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import (
1818
"github.com/drycc/builder/pkg/controller"
1919
"github.com/drycc/builder/pkg/git"
2020
"github.com/drycc/builder/pkg/k8s"
21-
"github.com/drycc/builder/pkg/storage"
2221
"github.com/drycc/builder/pkg/sys"
2322
dryccAPI "github.com/drycc/controller-sdk-go/api"
2423
"github.com/drycc/controller-sdk-go/hooks"
@@ -141,35 +140,25 @@ func build(
141140
if err != nil {
142141
return fmt.Errorf("error build builder pod node selector %s", err)
143142
}
144-
145-
var builderName string
146-
var imagePullPolicy corev1.PullPolicy
147-
var securityContext corev1.SecurityContext
148-
if strings.Contains(stack["name"], "container") {
149-
builderName = "drycc-imagebuilder"
150-
imagePullPolicy, err = k8s.PullPolicyFromString(conf.ImagebuilderImagePullPolicy)
151-
securityContext = k8s.SecurityContextFromPrivileged(false)
152-
153-
} else {
154-
builderName = "drycc-buildpacker"
155-
imagePullPolicy, err = k8s.PullPolicyFromString(conf.BuildpackerImagePullPolicy)
156-
securityContext = k8s.SecurityContextFromPrivileged(true)
157-
}
143+
builderName := "drycc-imagebuilder"
144+
imagePullPolicy, err := k8s.PullPolicyFromString(conf.ImagebuilderImagePullPolicy)
158145
if err != nil {
159146
return err
160147
}
148+
securityContext := k8s.SecurityContextFromPrivileged(true)
161149

162150
imageName := fmt.Sprintf("%s:git-%s", appName, gitSha.Short())
163151
buildPodName := imagebuilderPodName(appName, gitSha.Short())
164152
registryLocation := conf.RegistryLocation
165-
registryEnv := make(map[string]string)
153+
builderImageEnv := make(map[string]string)
166154
if registryLocation != "on-cluster" {
167-
registryEnv, err = getRegistryDetails(kubeClient.CoreV1(), &imageName, registryLocation, conf.PodNamespace)
155+
builderImageEnv, err = getRegistryDetails(kubeClient.CoreV1(), &imageName, registryLocation, conf.PodNamespace)
168156
if err != nil {
169157
return fmt.Errorf("error getting private registry details %s", err)
170158
}
171159
}
172-
registryEnv["DRYCC_REGISTRY_LOCATION"] = registryLocation
160+
builderImageEnv["DRYCC_STACK"] = stack["name"]
161+
builderImageEnv["DRYCC_REGISTRY_LOCATION"] = registryLocation
173162

174163
pod := createBuilderPod(
175164
conf.Debug,
@@ -184,7 +173,7 @@ func build(
184173
stack["image"],
185174
conf.RegistryHost,
186175
conf.RegistryPort,
187-
registryEnv,
176+
builderImageEnv,
188177
imagePullPolicy,
189178
securityContext,
190179
builderPodNodeSelector,
@@ -260,16 +249,19 @@ func build(
260249
}
261250
log.Debug("Done")
262251

263-
procType, err := getProcfile(storageDriver, tmpDir, stack)
252+
procfile, err := getProcfile(tmpDir, stack)
253+
if err != nil {
254+
return err
255+
}
256+
dockerfile, err := getDockerfile(tmpDir, stack)
264257
if err != nil {
265258
return err
266259
}
267-
268260
log.Info("Build complete.")
269261

270262
quit := progress("...", conf.SessionIdleInterval())
271263
log.Info("Launching App...")
272-
release, err := hooks.CreateBuild(client, conf.Username, conf.App(), imageName, stack["name"], gitSha.Short(), procType, stack["name"] == "container")
264+
release, err := hooks.CreateBuild(client, conf.Username, conf.App(), imageName, stack["name"], gitSha.Short(), procfile, dockerfile)
273265
quit <- true
274266
<-quit
275267
if controller.CheckAPICompat(client, err) != nil {
@@ -311,21 +303,34 @@ func prettyPrintJSON(data interface{}) (string, error) {
311303
return formatted.String(), nil
312304
}
313305

314-
func getProcfile(getter storage.ObjectGetter, dirName string, stack map[string]string) (dryccAPI.ProcessType, error) {
315-
procType := dryccAPI.ProcessType{}
306+
func getProcfile(dirName string, stack map[string]string) (dryccAPI.ProcessType, error) {
307+
procfile := dryccAPI.ProcessType{}
316308
_, err := os.Stat(fmt.Sprintf("%s/project.toml", dirName))
317309
if err == nil || stack["name"] == "container" {
318-
return procType, nil
310+
return procfile, nil
319311
}
320312
if _, err := os.Stat(fmt.Sprintf("%s/Procfile", dirName)); err == nil {
321313
rawProcFile, err := ioutil.ReadFile(fmt.Sprintf("%s/Procfile", dirName))
322314
if err != nil {
323315
return nil, fmt.Errorf("error in reading %s/Procfile (%s)", dirName, err)
324316
}
325-
if err := yaml.Unmarshal(rawProcFile, &procType); err != nil {
317+
if err := yaml.Unmarshal(rawProcFile, &procfile); err != nil {
326318
return nil, fmt.Errorf("procfile %s/ProcFile is malformed (%s)", dirName, err)
327319
}
328-
return procType, nil
320+
return procfile, nil
329321
}
330322
return nil, fmt.Errorf("no Procfile can be matched in (%s)", dirName)
331323
}
324+
325+
func getDockerfile(dirName string, stack map[string]string) (string, error) {
326+
if stack["name"] == "container" {
327+
if _, err := os.Stat(fmt.Sprintf("%s/Dockerfile", dirName)); err == nil {
328+
rawDockerfile, err := ioutil.ReadFile(fmt.Sprintf("%s/Dockerfile", dirName))
329+
if err != nil {
330+
return "", fmt.Errorf("error in reading %s/Dockerfile (%s)", dirName, err)
331+
}
332+
return string(rawDockerfile), nil
333+
}
334+
}
335+
return "", nil
336+
}

pkg/gitreceive/build_test.go

Lines changed: 5 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ package gitreceive
22

33
import (
44
"bytes"
5-
"context"
6-
"errors"
75
"fmt"
86
"io/ioutil"
97
"os"
@@ -17,17 +15,12 @@ import (
1715
"github.com/docker/distribution/registry/storage/driver/factory"
1816
_ "github.com/docker/distribution/registry/storage/driver/inmemory"
1917
builderconf "github.com/drycc/builder/pkg/conf"
20-
"github.com/drycc/builder/pkg/storage"
2118
"github.com/drycc/builder/pkg/sys"
2219
"github.com/drycc/controller-sdk-go/api"
2320
"github.com/drycc/pkg/log"
2421
"gopkg.in/yaml.v2"
2522
)
2623

27-
const (
28-
objKey = "myobj"
29-
)
30-
3124
type testJSONStruct struct {
3225
Foo string `json:"foo,omitempty"`
3326
}
@@ -68,11 +61,9 @@ func TestBuild(t *testing.T) {
6861

6962
config.ImagebuilderImagePullPolicy = "Always"
7063
if err := build(config, storageDriver, nil, fs, env, "foo", sha); err == nil {
71-
t.Error("expected running build() without setting config.BuildpackerImagePullPolicy to fail")
64+
t.Error("expected running build() without setting config.ImagebuilderImagePullPolicy to fail")
7265
}
7366

74-
config.BuildpackerImagePullPolicy = "Always"
75-
7667
err = build(config, storageDriver, nil, fs, env, "foo", "abc123")
7768
expected := "git sha abc123 was invalid"
7869
if err.Error() != expected {
@@ -122,12 +113,11 @@ func TestGetProcfileFromRepoSuccess(t *testing.T) {
122113
t.Fatalf("failed to remove Procfile from %s (%s)", tmpDir, err)
123114
}
124115
}()
125-
getter := &storage.FakeObjectGetter{}
126116
config := api.Config{}
127117
config.Values = map[string]interface{}{
128118
"DRYCC_STACK": "buildpack",
129119
}
130-
procType, err := getProcfile(getter, tmpDir, getStack(tmpDir, config))
120+
procType, err := getProcfile(tmpDir, getStack(tmpDir, config))
131121
actualData := api.ProcessType{}
132122
yaml.Unmarshal(data, &actualData)
133123
assert.NoErr(t, err)
@@ -148,48 +138,36 @@ func TestGetProcfileFromRepoFailure(t *testing.T) {
148138
t.Fatalf("failed to remove Procfile from %s (%s)", tmpDir, err)
149139
}
150140
}()
151-
getter := &storage.FakeObjectGetter{}
152141
config := api.Config{}
153142
config.Values = map[string]interface{}{
154143
"DRYCC_STACK": "buildpack",
155144
}
156-
_, err = getProcfile(getter, tmpDir, getStack(tmpDir, config))
145+
_, err = getProcfile(tmpDir, getStack(tmpDir, config))
157146

158147
assert.True(t, err != nil, "no error received when there should have been")
159148
}
160149

161150
func TestGetProcfileFromServerSuccess(t *testing.T) {
162151
data := []byte("web: example-go")
163-
getter := &storage.FakeObjectGetter{
164-
Fn: func(context.Context, string) ([]byte, error) {
165-
return data, nil
166-
},
167-
}
168152
tmpDir := os.TempDir()
169153
config := api.Config{}
170154
config.Values = map[string]interface{}{
171155
"DRYCC_STACK": "buildpack",
172156
}
173157

174-
_, err := getProcfile(getter, "", getStack(tmpDir, config))
158+
_, err := getProcfile("", getStack(tmpDir, config))
175159
actualData := api.ProcessType{}
176160
yaml.Unmarshal(data, &actualData)
177161
assert.Err(t, err, fmt.Errorf("no Procfile can be matched in (%s)", ""))
178162
}
179163

180164
func TestGetProcfileFromServerFailure(t *testing.T) {
181-
expectedErr := errors.New("test error")
182-
getter := &storage.FakeObjectGetter{
183-
Fn: func(context.Context, string) ([]byte, error) {
184-
return []byte("web: example-go"), expectedErr
185-
},
186-
}
187165
tmpDir := os.TempDir()
188166
config := api.Config{}
189167
config.Values = map[string]interface{}{
190168
"DRYCC_STACK": "buildpack",
191169
}
192-
_, err := getProcfile(getter, "", getStack(tmpDir, config))
170+
_, err := getProcfile("", getStack(tmpDir, config))
193171
assert.Err(t, err, fmt.Errorf("no Procfile can be matched in (%s)", ""))
194172
assert.True(t, err != nil, "no error received when there should have been")
195173
}

pkg/gitreceive/build_type.go

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import (
1414
var defaultStacks = `[
1515
{
1616
"name": "buildpack",
17-
"image": "drycc/buildpacker:canary"
17+
"image": "drycc/imagebuilder:canary"
1818
},
1919
{
2020
"name": "container",
@@ -28,24 +28,11 @@ var Stacks []map[string]string
2828

2929
// initStack load stack by config
3030
func initStack() error {
31-
data, err := ioutil.ReadFile("/etc/buildpacker/images.json")
31+
data, err := ioutil.ReadFile("/etc/imagebuilder/images.json")
3232
if err == nil {
33-
var stacksBuildpacker []map[string]string
34-
err = json.Unmarshal(data, &stacksBuildpacker)
35-
if err == nil {
36-
data, err = ioutil.ReadFile("/etc/imagebuilder/images.json")
37-
if err == nil {
38-
var stacksImagebuilder []map[string]string
39-
err = json.Unmarshal(data, &stacksImagebuilder)
40-
if err == nil {
41-
// Stacks order represents priority
42-
Stacks = stacksImagebuilder
43-
Stacks = append(Stacks, stacksBuildpacker...)
44-
}
45-
return nil
46-
}
47-
}
33+
return json.Unmarshal(data, &Stacks)
4834
}
35+
4936
return json.Unmarshal([]byte(defaultStacks), &Stacks)
5037
}
5138

pkg/gitreceive/config.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ type Config struct {
3434
ObjectStorageTickDurationMSec int `envconfig:"OBJECT_STORAGE_TICK_DURATION" default:"500"`
3535
ObjectStorageWaitDurationMSec int `envconfig:"OBJECT_STORAGE_WAIT_DURATION" default:"300000"` // 5 minutes
3636
SessionIdleIntervalMsec int `envconfig:"SESSION_IDLE_INTERVAL" default:"10000"` // 10 seconds
37-
BuildpackerImagePullPolicy string `envconfig:"BUILDPACKER_IMAGE_PULL_POLICY" default:"Always"`
3837
ImagebuilderImagePullPolicy string `envconfig:"IMAGEBUILDER_IMAGE_PULL_POLICY" default:"Always"`
3938
StorageType string `envconfig:"BUILDER_STORAGE" default:"minio"`
4039
BuilderPodNodeSelector string `envconfig:"BUILDER_POD_NODE_SELECTOR" default:""`

pkg/gitreceive/k8s_util.go

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,14 @@ import (
1717
)
1818

1919
const (
20-
tarPath = "TAR_PATH"
21-
debugKey = "DRYCC_DEBUG"
22-
sourceVersion = "SOURCE_VERSION"
23-
objectStore = "objectstorage-keyfile"
24-
builderStorage = "BUILDER_STORAGE"
25-
objectStorePath = "/var/run/secrets/drycc/objectstore/creds"
20+
tarPath = "TAR_PATH"
21+
debugKey = "DRYCC_DEBUG"
22+
sourceVersion = "SOURCE_VERSION"
23+
objectStore = "objectstorage-keyfile"
24+
builderStorage = "BUILDER_STORAGE"
25+
objectStorePath = "/var/run/secrets/drycc/objectstore/creds"
26+
imagebuilderConfig = "imagebuilder-config"
27+
imagebuilderConfigPath = "/etc/imagebuilder"
2628
)
2729

2830
func imagebuilderPodName(appName, shortSha string) string {
@@ -48,7 +50,7 @@ func createBuilderPod(
4850
builderImage,
4951
registryHost,
5052
registryPort string,
51-
registryEnv map[string]string,
53+
builderImageEnv map[string]string,
5254
pullPolicy corev1.PullPolicy,
5355
securityContext corev1.SecurityContext,
5456
nodeSelector map[string]string,
@@ -80,7 +82,7 @@ func createBuilderPod(
8082
addEnvToPod(pod, "DRYCC_REGISTRY_PROXY_HOST", registryHost)
8183
addEnvToPod(pod, "DRYCC_REGISTRY_PROXY_PORT", registryPort)
8284

83-
for key, value := range registryEnv {
85+
for key, value := range builderImageEnv {
8486
addEnvToPod(pod, key, value)
8587
}
8688

@@ -132,6 +134,24 @@ func buildPod(
132134
ReadOnly: true,
133135
},
134136
}
137+
pod.Spec.Volumes = append(pod.Spec.Volumes, corev1.Volume{
138+
Name: objectStore,
139+
VolumeSource: corev1.VolumeSource{
140+
ConfigMap: &corev1.ConfigMapVolumeSource{
141+
LocalObjectReference: corev1.LocalObjectReference{
142+
Name: imagebuilderConfig,
143+
},
144+
},
145+
},
146+
})
147+
148+
pod.Spec.Containers[0].VolumeMounts = []corev1.VolumeMount{
149+
{
150+
Name: imagebuilderConfig,
151+
MountPath: imagebuilderConfigPath,
152+
ReadOnly: true,
153+
},
154+
}
135155

136156
if len(pod.Spec.Containers) > 0 {
137157
for k, v := range env {

0 commit comments

Comments
 (0)