forked from openshift/origin
/
builder.go
146 lines (130 loc) · 4.25 KB
/
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
package cmd
import (
"fmt"
"io/ioutil"
"net/url"
"os"
"os/exec"
"path/filepath"
"github.com/golang/glog"
"github.com/openshift/origin/pkg/api/latest"
"github.com/openshift/origin/pkg/build/api"
bld "github.com/openshift/origin/pkg/build/builder"
"github.com/openshift/origin/pkg/build/builder/cmd/scmauth"
dockerutil "github.com/openshift/origin/pkg/cmd/util/docker"
"github.com/openshift/origin/pkg/generate/git"
)
type builder interface {
Build() error
}
type factoryFunc func(
client bld.DockerClient,
dockerSocket string,
build *api.Build) builder
// run is responsible for preparing environment for actual build.
// It accepts factoryFunc and an ordered array of SCMAuths.
func run(builderFactory factoryFunc) {
client, endpoint, err := dockerutil.NewHelper().GetClient()
if err != nil {
glog.Fatalf("Error obtaining docker client: %v", err)
}
buildStr := os.Getenv("BUILD")
glog.V(4).Infof("$BUILD env var is %s \n", buildStr)
build := api.Build{}
if err := latest.Codec.DecodeInto([]byte(buildStr), &build); err != nil {
glog.Fatalf("Unable to parse build: %v", err)
}
if build.Spec.Source.SourceSecret != nil {
sourceURL, err := git.ParseRepository(build.Spec.Source.Git.URI)
if err != nil {
glog.Fatalf("Cannot parse build URL: %s", build.Spec.Source.Git.URI)
}
scmAuths := auths(sourceURL)
if err := setupSourceSecret(build.Spec.Source.SourceSecret.Name, scmAuths); err != nil {
glog.Fatalf("Cannot setup secret file for accessing private repository: %v", err)
}
}
b := builderFactory(client, endpoint, &build)
if err = b.Build(); err != nil {
glog.Fatalf("Build error: %v", err)
}
if build.Spec.Output.To == nil || len(build.Spec.Output.To.Name) == 0 {
glog.Warning("Build does not have an Output defined, no output image was pushed to a registry.")
}
}
// fixSecretPermissions loweres access permissions to very low acceptable level
// TODO: this method should be removed as soon as secrets permissions are fixed upstream
func fixSecretPermissions() error {
secretTmpDir, err := ioutil.TempDir("", "tmpsecret")
if err != nil {
return err
}
cmd := exec.Command("cp", "-R", ".", secretTmpDir)
cmd.Dir = os.Getenv("SOURCE_SECRET_PATH")
if err := cmd.Run(); err != nil {
return err
}
secretFiles, err := ioutil.ReadDir(secretTmpDir)
if err != nil {
return err
}
for _, file := range secretFiles {
if err := os.Chmod(filepath.Join(secretTmpDir, file.Name()), 0600); err != nil {
return err
}
}
os.Setenv("SOURCE_SECRET_PATH", secretTmpDir)
return nil
}
func setupSourceSecret(sourceSecretName string, scmAuths []scmauth.SCMAuth) error {
fixSecretPermissions()
sourceSecretDir := os.Getenv("SOURCE_SECRET_PATH")
files, err := ioutil.ReadDir(sourceSecretDir)
if err != nil {
return err
}
// Filter the list of SCMAuths based on the secret files that are present
scmAuthsPresent := map[string]scmauth.SCMAuth{}
for _, file := range files {
glog.V(3).Infof("Finding auth for %q in secret %q", file.Name(), sourceSecretName)
for _, scmAuth := range scmAuths {
if scmAuth.Handles(file.Name()) {
glog.V(3).Infof("Found SCMAuth %q to handle %q", scmAuth.Name(), file.Name())
scmAuthsPresent[scmAuth.Name()] = scmAuth
}
}
}
if len(scmAuthsPresent) == 0 {
return fmt.Errorf("no auth handler was found for the provided secret %q",
sourceSecretName)
}
for name, auth := range scmAuthsPresent {
glog.V(3).Infof("Setting up SCMAuth %q", name)
if err := auth.Setup(sourceSecretDir); err != nil {
// If an error occurs during setup, fail the build
return fmt.Errorf("cannot set up source authentication method %q: %v", name, err)
}
}
return nil
}
func auths(sourceURL *url.URL) []scmauth.SCMAuth {
auths := []scmauth.SCMAuth{
&scmauth.SSHPrivateKey{},
&scmauth.UsernamePassword{SourceURL: *sourceURL},
&scmauth.CACert{SourceURL: *sourceURL},
&scmauth.GitConfig{},
}
return auths
}
// RunDockerBuild creates a docker builder and runs its build
func RunDockerBuild() {
run(func(client bld.DockerClient, sock string, build *api.Build) builder {
return bld.NewDockerBuilder(client, build)
})
}
// RunSTIBuild creates a STI builder and runs its build
func RunSTIBuild() {
run(func(client bld.DockerClient, sock string, build *api.Build) builder {
return bld.NewSTIBuilder(client, sock, build)
})
}