forked from openshift/origin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
util.go
190 lines (169 loc) · 6.34 KB
/
util.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
183
184
185
186
187
188
189
190
package strategy
import (
"path/filepath"
kapi "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/golang/glog"
buildapi "github.com/openshift/origin/pkg/build/api"
imageapi "github.com/openshift/origin/pkg/image/api"
"github.com/openshift/origin/pkg/util/namer"
)
const (
// dockerSocketPath is the default path for the Docker socket inside the builder container
dockerSocketPath = "/var/run/docker.sock"
DockerPushSecretMountPath = "/var/run/secrets/openshift.io/push"
DockerPullSecretMountPath = "/var/run/secrets/openshift.io/pull"
sourceSecretMountPath = "/var/run/secrets/openshift.io/source"
)
var whitelistEnvVarNames = []string{"BUILD_LOGLEVEL"}
// setupDockerSocket configures the pod to support the host's Docker socket
func setupDockerSocket(podSpec *kapi.Pod) {
dockerSocketVolume := kapi.Volume{
Name: "docker-socket",
VolumeSource: kapi.VolumeSource{
HostPath: &kapi.HostPathVolumeSource{
Path: dockerSocketPath,
},
},
}
dockerSocketVolumeMount := kapi.VolumeMount{
Name: "docker-socket",
MountPath: dockerSocketPath,
}
podSpec.Spec.Volumes = append(podSpec.Spec.Volumes,
dockerSocketVolume)
podSpec.Spec.Containers[0].VolumeMounts =
append(podSpec.Spec.Containers[0].VolumeMounts,
dockerSocketVolumeMount)
}
// setupBuildEnv injects human-friendly environment variables which provides
// useful information about the current build.
func setupBuildEnv(build *buildapi.Build, pod *kapi.Pod) error {
vars := []kapi.EnvVar{}
switch build.Spec.Source.Type {
case buildapi.BuildSourceGit:
vars = append(vars, kapi.EnvVar{Name: "SOURCE_URI", Value: build.Spec.Source.Git.URI})
vars = append(vars, kapi.EnvVar{Name: "SOURCE_REF", Value: build.Spec.Source.Git.Ref})
default:
// Do nothing for unknown source types
}
if build.Spec.Output.To != nil {
// output much always be a DockerImage type reference at this point.
ref, err := imageapi.ParseDockerImageReference(build.Spec.Output.To.Name)
if err != nil {
return err
}
vars = append(vars, kapi.EnvVar{Name: "OUTPUT_REGISTRY", Value: ref.Registry})
ref.Registry = ""
vars = append(vars, kapi.EnvVar{Name: "OUTPUT_IMAGE", Value: ref.String()})
}
if len(pod.Spec.Containers) > 0 {
pod.Spec.Containers[0].Env = append(pod.Spec.Containers[0].Env, vars...)
}
return nil
}
// mountSecretVolume is a helper method responsible for actual mounting secret
// volumes into a pod.
func mountSecretVolume(pod *kapi.Pod, secretName, mountPath, volumePrefix string) {
volumeName := namer.GetName(secretName, volumePrefix, util.DNS1123SubdomainMaxLength)
volume := kapi.Volume{
Name: volumeName,
VolumeSource: kapi.VolumeSource{
Secret: &kapi.SecretVolumeSource{
SecretName: secretName,
},
},
}
volumeMount := kapi.VolumeMount{
Name: volumeName,
MountPath: mountPath,
ReadOnly: true,
}
pod.Spec.Volumes = append(pod.Spec.Volumes, volume)
pod.Spec.Containers[0].VolumeMounts = append(pod.Spec.Containers[0].VolumeMounts, volumeMount)
}
// setupDockerSecrets mounts Docker Registry secrets into Pod running the build,
// allowing Docker to authenticate against private registries or Docker Hub.
func setupDockerSecrets(pod *kapi.Pod, pushSecret, pullSecret *kapi.LocalObjectReference) {
if pushSecret != nil {
mountSecretVolume(pod, pushSecret.Name, DockerPushSecretMountPath, "push")
pod.Spec.Containers[0].Env = append(pod.Spec.Containers[0].Env, []kapi.EnvVar{
{Name: "PUSH_DOCKERCFG_PATH", Value: filepath.Join(DockerPushSecretMountPath, kapi.DockerConfigKey)},
}...)
glog.V(3).Infof("%s be used for docker push in %s", DockerPullSecretMountPath, pod.Name)
}
if pullSecret != nil {
mountSecretVolume(pod, pullSecret.Name, DockerPullSecretMountPath, "pull")
pod.Spec.Containers[0].Env = append(pod.Spec.Containers[0].Env, []kapi.EnvVar{
{Name: "PULL_DOCKERCFG_PATH", Value: filepath.Join(DockerPullSecretMountPath, kapi.DockerConfigKey)},
}...)
glog.V(3).Infof("%s be used for docker pull in %s", DockerPullSecretMountPath, pod.Name)
}
}
// setupSourceSecrets mounts SSH key used for accessing private SCM to clone
// application source code during build.
func setupSourceSecrets(pod *kapi.Pod, sourceSecret *kapi.LocalObjectReference) {
if sourceSecret == nil {
return
}
mountSecretVolume(pod, sourceSecret.Name, sourceSecretMountPath, "source")
glog.V(3).Infof("Installed source secrets in %s, in Pod %s/%s", sourceSecretMountPath, pod.Namespace, pod.Name)
pod.Spec.Containers[0].Env = append(pod.Spec.Containers[0].Env, []kapi.EnvVar{
{Name: "SOURCE_SECRET_PATH", Value: sourceSecretMountPath},
}...)
}
// mergeTrustedEnvWithoutDuplicates merges two environment lists without having
// duplicate items in the output list. Only trusted environment variables
// will be merged.
func mergeTrustedEnvWithoutDuplicates(source []kapi.EnvVar, output *[]kapi.EnvVar) {
// filter out all environment variables except trusted/well known
// values, because we do not want random environment variables being
// fed into the privileged STI container via the BuildConfig definition.
filteredSource := []kapi.EnvVar{}
for _, env := range source {
trusted := false
for _, acceptable := range whitelistEnvVarNames {
if env.Name == acceptable {
trusted = true
break
}
}
if !trusted {
continue
}
filteredSource = append(filteredSource, env)
}
type sourceMapItem struct {
index int
value string
}
// Convert source to Map for faster access
sourceMap := make(map[string]sourceMapItem)
for i, env := range filteredSource {
sourceMap[env.Name] = sourceMapItem{i, env.Value}
}
result := *output
for i, env := range result {
// If the value exists in output, override it and remove it
// from the source list
if v, found := sourceMap[env.Name]; found {
result[i].Value = v.value
filteredSource = append(filteredSource[:v.index], filteredSource[v.index+1:]...)
}
}
*output = append(result, filteredSource...)
}
// getContainerVerbosity returns the defined BUILD_LOGLEVEL value
func getContainerVerbosity(containerEnv []kapi.EnvVar) (verbosity string) {
for _, env := range containerEnv {
if env.Name == "BUILD_LOGLEVEL" {
verbosity = env.Value
break
}
}
return
}
// getPodLabels creates labels for the Build Pod
func getPodLabels(build *buildapi.Build) map[string]string {
return map[string]string{buildapi.BuildLabel: build.Name}
}