Skip to content

Commit 7d928d8

Browse files
committed
feat(podselector): add pod selector for builder job
1 parent 3b29d47 commit 7d928d8

5 files changed

Lines changed: 94 additions & 17 deletions

File tree

pkg/gitreceive/build.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package gitreceive
22

33
import (
4+
"bufio"
45
"bytes"
56
"encoding/json"
67
"fmt"
@@ -159,6 +160,12 @@ func build(
159160
var pod *api.Pod
160161
var buildPodName string
161162
image := appName
163+
164+
builderPodNodeSelector, err := buildBuilderPodNodeSelector(conf.BuilderPodNodeSelector)
165+
if err != nil {
166+
return fmt.Errorf("error build builder pod node selector %s", err)
167+
}
168+
162169
if usingDockerfile {
163170
buildPodName = dockerBuilderPodName(appName, gitSha.Short())
164171
registryLocation := conf.RegistryLocation
@@ -187,6 +194,7 @@ func build(
187194
conf.RegistryPort,
188195
registryEnv,
189196
dockerBuilderImagePullPolicy,
197+
builderPodNodeSelector,
190198
)
191199
} else {
192200
buildPodName = slugBuilderPodName(appName, gitSha.Short())
@@ -218,6 +226,7 @@ func build(
218226
conf.StorageType,
219227
conf.SlugBuilderImage,
220228
slugBuilderImagePullPolicy,
229+
builderPodNodeSelector,
221230
)
222231
}
223232

@@ -318,6 +327,21 @@ func build(
318327
return nil
319328
}
320329

330+
func buildBuilderPodNodeSelector(config string) (map[string]string, error) {
331+
selector := make(map[string]string)
332+
if config != "" {
333+
line := bufio.NewScanner(strings.NewReader(config))
334+
for line.Scan() {
335+
splits := strings.Split(line.Text(), "=")
336+
if len(splits) != 2 {
337+
return nil, fmt.Errorf("Invalid BuilderPodNodeSelector value format: %s", config)
338+
}
339+
selector[splits[0]] = splits[1]
340+
}
341+
}
342+
return selector, nil
343+
}
344+
321345
func prettyPrintJSON(data interface{}) (string, error) {
322346
output := &bytes.Buffer{}
323347
if err := json.NewEncoder(output).Encode(data); err != nil {

pkg/gitreceive/build_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ type testJSONStruct struct {
3131
Foo string `json:"foo,omitempty"`
3232
}
3333

34+
type podSelectorBuildCase struct {
35+
Config string
36+
Output map[string]string
37+
}
38+
3439
func TestBuild(t *testing.T) {
3540
config := &Config{}
3641
env := sys.NewFakeEnv()
@@ -226,3 +231,22 @@ func TestRunCmd(t *testing.T) {
226231
t.Errorf("expected '%s', got '%s'", expected, output)
227232
}
228233
}
234+
235+
func TestBuildBuilderPodNodeSelector(t *testing.T) {
236+
emptyNodeSelector := make(map[string]string)
237+
238+
cazes := []podSelectorBuildCase{
239+
{"", emptyNodeSelector},
240+
{"pool=worker", map[string]string{"pool": "worker"}},
241+
{"pool=worker\nnetwork=fast", map[string]string{"pool": "worker", "network": "fast"}},
242+
}
243+
244+
for _, caze := range cazes {
245+
output, err := buildBuilderPodNodeSelector(caze.Config)
246+
assert.Nil(t, err, "error")
247+
assert.Equal(t, output, caze.Output, "pod selector")
248+
}
249+
250+
_, err := buildBuilderPodNodeSelector("failtest")
251+
assert.ExistsErr(t, err, "fail test")
252+
}

pkg/gitreceive/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ type Config struct {
4141
SlugBuilderImagePullPolicy string `envconfig:"SLUG_BUILDER_IMAGE_PULL_POLICY" default:"Always"`
4242
DockerBuilderImagePullPolicy string `envconfig:"DOCKER_BUILDER_IMAGE_PULL_POLICY" default:"Always"`
4343
StorageType string `envconfig:"BUILDER_STORAGE" default:"minio"`
44+
BuilderPodNodeSelector string `envconfig:"BUILDER_POD_NODE_SELECTOR" default:""`
4445
}
4546

4647
// App returns the application name represented by c. The app name is the same as c.Repository

pkg/gitreceive/k8s_util.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,10 @@ func dockerBuilderPod(
5555
registryPort string,
5656
registryEnv map[string]string,
5757
pullPolicy api.PullPolicy,
58+
nodeSelector map[string]string,
5859
) *api.Pod {
5960

60-
pod := buildPod(debug, name, namespace, pullPolicy, env)
61+
pod := buildPod(debug, name, namespace, pullPolicy, nodeSelector, env)
6162

6263
// inject application envvars as a special envvar which will be handled by dockerbuilder to
6364
// inject them as build-time variables.
@@ -115,9 +116,10 @@ func slugbuilderPod(
115116
storageType,
116117
image string,
117118
pullPolicy api.PullPolicy,
119+
nodeSelector map[string]string,
118120
) *api.Pod {
119121

120-
pod := buildPod(debug, name, namespace, pullPolicy, nil)
122+
pod := buildPod(debug, name, namespace, pullPolicy, nodeSelector, nil)
121123

122124
pod.Spec.Volumes = append(pod.Spec.Volumes, api.Volume{
123125
Name: envSecretName,
@@ -159,6 +161,7 @@ func buildPod(
159161
name,
160162
namespace string,
161163
pullPolicy api.PullPolicy,
164+
nodeSelector map[string]string,
162165
env map[string]interface{}) api.Pod {
163166

164167
pod := api.Pod{
@@ -206,6 +209,10 @@ func buildPod(
206209
}
207210
}
208211

212+
if len(nodeSelector) > 0 {
213+
pod.Spec.NodeSelector = nodeSelector
214+
}
215+
209216
if debug {
210217
addEnvToPod(pod, debugKey, "1")
211218
}

pkg/gitreceive/k8s_util_test.go

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ type slugBuildCase struct {
3939
slugBuilderImage string
4040
slugBuilderImagePullPolicy api.PullPolicy
4141
storageType string
42+
builderPodNodeSelector map[string]string
4243
}
4344

4445
type dockerBuildCase struct {
@@ -52,6 +53,7 @@ type dockerBuildCase struct {
5253
dockerBuilderImage string
5354
dockerBuilderImagePullPolicy api.PullPolicy
5455
storageType string
56+
builderPodNodeSelector map[string]string
5557
}
5658

5759
func TestBuildPod(t *testing.T) {
@@ -62,15 +64,24 @@ func TestBuildPod(t *testing.T) {
6264
envSecretName := "test-build-env"
6365
var pod *api.Pod
6466

67+
emptyNodeSelector := make(map[string]string)
68+
69+
nodeSelector1 := make(map[string]string)
70+
nodeSelector1["disk"] = "ssd"
71+
72+
nodeSelector2 := make(map[string]string)
73+
nodeSelector2["disk"] = "magnetic"
74+
nodeSelector2["network"] = "fast"
75+
6576
slugBuilds := []slugBuildCase{
66-
{true, "test", "default", envSecretName, "tar", "put-url", "cache-url", "deadbeef", "", "", api.PullAlways, ""},
67-
{true, "test", "default", envSecretName, "tar", "put-url", "cache-url", "deadbeef", "", "", api.PullAlways, ""},
68-
{true, "test", "default", envSecretName, "tar", "put-url", "", "deadbeef", "", "", api.PullAlways, ""},
69-
{true, "test", "default", envSecretName, "tar", "put-url", "cache-url", "deadbeef", "buildpack", "", api.PullAlways, ""},
70-
{true, "test", "default", envSecretName, "tar", "put-url", "cache-url", "deadbeef", "buildpack", "", api.PullAlways, ""},
71-
{true, "test", "default", envSecretName, "tar", "put-url", "cache-url", "deadbeef", "buildpack", "customimage", api.PullAlways, ""},
72-
{true, "test", "default", envSecretName, "tar", "put-url", "cache-url", "deadbeef", "buildpack", "customimage", api.PullIfNotPresent, ""},
73-
{true, "test", "default", envSecretName, "tar", "put-url", "cache-url", "deadbeef", "buildpack", "customimage", api.PullNever, ""},
77+
{true, "test", "default", envSecretName, "tar", "put-url", "cache-url", "deadbeef", "", "", api.PullAlways, "", emptyNodeSelector},
78+
{true, "test", "default", envSecretName, "tar", "put-url", "cache-url", "deadbeef", "", "", api.PullAlways, "", emptyNodeSelector},
79+
{true, "test", "default", envSecretName, "tar", "put-url", "", "deadbeef", "", "", api.PullAlways, "", emptyNodeSelector},
80+
{true, "test", "default", envSecretName, "tar", "put-url", "cache-url", "deadbeef", "buildpack", "", api.PullAlways, "", emptyNodeSelector},
81+
{true, "test", "default", envSecretName, "tar", "put-url", "cache-url", "deadbeef", "buildpack", "", api.PullAlways, "", emptyNodeSelector},
82+
{true, "test", "default", envSecretName, "tar", "put-url", "cache-url", "deadbeef", "buildpack", "customimage", api.PullAlways, "", nil},
83+
{true, "test", "default", envSecretName, "tar", "put-url", "cache-url", "deadbeef", "buildpack", "customimage", api.PullIfNotPresent, "", nodeSelector1},
84+
{true, "test", "default", envSecretName, "tar", "put-url", "cache-url", "deadbeef", "buildpack", "customimage", api.PullNever, "", nodeSelector2},
7485
}
7586

7687
for _, build := range slugBuilds {
@@ -87,6 +98,7 @@ func TestBuildPod(t *testing.T) {
8798
build.storageType,
8899
build.slugBuilderImage,
89100
build.slugBuilderImagePullPolicy,
101+
build.builderPodNodeSelector,
90102
)
91103

92104
if pod.ObjectMeta.Name != build.name {
@@ -123,16 +135,20 @@ func TestBuildPod(t *testing.T) {
123135
t.Errorf("expected %v but returned %v", build.slugBuilderImagePullPolicy, pod.Spec.Containers[0].ImagePullPolicy)
124136
}
125137
}
138+
139+
if len(pod.Spec.NodeSelector) > 0 || len(build.builderPodNodeSelector) > 0 {
140+
assert.Equal(t, pod.Spec.NodeSelector, build.builderPodNodeSelector, "node selector")
141+
}
126142
}
127143

128144
dockerBuilds := []dockerBuildCase{
129-
{true, "test", "default", emptyEnv, "tar", "deadbeef", "", "", api.PullAlways, ""},
130-
{true, "test", "default", env, "tar", "deadbeef", "", "", api.PullAlways, ""},
131-
{true, "test", "default", emptyEnv, "tar", "deadbeef", "img", "", api.PullAlways, ""},
132-
{true, "test", "default", env, "tar", "deadbeef", "img", "", api.PullAlways, ""},
133-
{true, "test", "default", env, "tar", "deadbeef", "img", "customimage", api.PullAlways, ""},
134-
{true, "test", "default", env, "tar", "deadbeef", "img", "customimage", api.PullIfNotPresent, ""},
135-
{true, "test", "default", env, "tar", "deadbeef", "img", "customimage", api.PullNever, ""},
145+
{true, "test", "default", emptyEnv, "tar", "deadbeef", "", "", api.PullAlways, "", nodeSelector1},
146+
{true, "test", "default", env, "tar", "deadbeef", "", "", api.PullAlways, "", nodeSelector2},
147+
{true, "test", "default", emptyEnv, "tar", "deadbeef", "img", "", api.PullAlways, "", emptyNodeSelector},
148+
{true, "test", "default", env, "tar", "deadbeef", "img", "", api.PullAlways, "", emptyNodeSelector},
149+
{true, "test", "default", env, "tar", "deadbeef", "img", "customimage", api.PullAlways, "", emptyNodeSelector},
150+
{true, "test", "default", env, "tar", "deadbeef", "img", "customimage", api.PullIfNotPresent, "", emptyNodeSelector},
151+
{true, "test", "default", env, "tar", "deadbeef", "img", "customimage", api.PullNever, "", nil},
136152
}
137153
regEnv := map[string]string{"REG_LOC": "on-cluster"}
138154
for _, build := range dockerBuilds {
@@ -150,6 +166,7 @@ func TestBuildPod(t *testing.T) {
150166
"5555",
151167
regEnv,
152168
build.dockerBuilderImagePullPolicy,
169+
build.builderPodNodeSelector,
153170
)
154171

155172
if pod.ObjectMeta.Name != build.name {
@@ -175,6 +192,10 @@ func TestBuildPod(t *testing.T) {
175192
}
176193
}
177194
}
195+
196+
if len(pod.Spec.NodeSelector) > 0 || len(build.builderPodNodeSelector) > 0 {
197+
assert.Equal(t, pod.Spec.NodeSelector, build.builderPodNodeSelector, "node selector")
198+
}
178199
}
179200
}
180201

0 commit comments

Comments
 (0)