Skip to content

Commit 4e94444

Browse files
author
Victor
committed
add failure reasons
1 parent 57fcd19 commit 4e94444

File tree

19 files changed

+438
-104
lines changed

19 files changed

+438
-104
lines changed

pkg/build/api/types.go

+35
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,41 @@ const (
286286
// secret for pushing the output image.
287287
// The build will stay in the pending state until the secret is created, or the build times out.
288288
StatusReasonMissingPushSecret StatusReason = "MissingPushSecret"
289+
290+
// StatusReasonPostCommitHookFailed indicates the post-commit hook failed.
291+
StatusReasonPostCommitHookFailed StatusReason = "PostCommitHookFailed"
292+
293+
// StatusReasonPushImageToRegistryFailed indicates that an image failed to be
294+
// pushed to the registry.
295+
StatusReasonPushImageToRegistryFailed StatusReason = "PushImageToRegistryFailed"
296+
297+
// StatusReasonPullBuilderImageFailed indicates that we failed to pull the
298+
// builder image.
299+
StatusReasonPullBuilderImageFailed StatusReason = "PullBuilderImageFailed"
300+
301+
// StatusReasonFetchSourceFailed indicates that fetching the source of the
302+
// build has failed.
303+
StatusReasonFetchSourceFailed StatusReason = "FetchSourceFailed"
304+
305+
// StatusReasonCancelledBuild indicates that the build was cancelled by the
306+
// user.
307+
StatusReasonCancelledBuild StatusReason = "CancelledBuild"
308+
)
309+
310+
// NOTE: These messages might change.
311+
const (
312+
StatusMessageCannotCreateBuildPodSpec = "Failed to create pod spec"
313+
StatusMessageCannotCreateBuildPod = "Failed creating build pod"
314+
StatusMessageInvalidOutputRef = "Output image could not be resolved"
315+
StatusMessageCancelBuildFailed = "Failed to cancel build"
316+
StatusMessageBuildPodDeleted = "The pod for this build was deleted before the build completed"
317+
StatusMessageExceededRetryTimeout = "Build did not complete and retrying timed out"
318+
StatusMessageMissingPushSecret = "Missing push secret"
319+
StatusMessagePostCommitHookFailed = "Build failed because of post commit hook"
320+
StatusMessagePushImageToRegistryFailed = "Failed to push the image to the registry"
321+
StatusMessagePullBuilderImageFailed = "Failed pulling builder image"
322+
StatusMessageFetchSourceFailed = "Failed to fetch the input source"
323+
StatusMessageCancelledBuild = "The build was cancelled by the user"
289324
)
290325

291326
// BuildSource is the input used for the build.

pkg/build/builder/common.go

+54-35
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import (
1010
"github.com/docker/distribution/reference"
1111
"github.com/fsouza/go-dockerclient"
1212

13+
kclient "k8s.io/kubernetes/pkg/client/unversioned"
14+
1315
"github.com/openshift/origin/pkg/build/api"
1416
"github.com/openshift/origin/pkg/client"
1517
"github.com/openshift/origin/pkg/generate/git"
@@ -20,7 +22,14 @@ import (
2022
// client facing libraries should not be using glog
2123
var glog = utilglog.ToFile(os.Stderr, 2)
2224

23-
const OriginalSourceURLAnnotationKey = "openshift.io/original-source-url"
25+
const (
26+
OriginalSourceURLAnnotationKey = "openshift.io/original-source-url"
27+
28+
// containerNamePrefix prefixes the name of containers launched by a build.
29+
// We cannot reuse the prefix "k8s" because we don't want the containers to
30+
// be managed by a kubelet.
31+
containerNamePrefix = "openshift"
32+
)
2433

2534
// KeyValue can be used to build ordered lists of key-value pairs.
2635
type KeyValue struct {
@@ -66,35 +75,6 @@ func buildInfo(build *api.Build) []KeyValue {
6675
return kv
6776
}
6877

69-
func updateBuildRevision(c client.BuildInterface, build *api.Build, sourceInfo *git.SourceInfo) {
70-
if build.Spec.Revision != nil {
71-
return
72-
}
73-
build.Spec.Revision = &api.SourceRevision{
74-
Git: &api.GitSourceRevision{
75-
Commit: sourceInfo.CommitID,
76-
Message: sourceInfo.Message,
77-
Author: api.SourceControlUser{
78-
Name: sourceInfo.AuthorName,
79-
Email: sourceInfo.AuthorEmail,
80-
},
81-
Committer: api.SourceControlUser{
82-
Name: sourceInfo.CommitterName,
83-
Email: sourceInfo.CommitterEmail,
84-
},
85-
},
86-
}
87-
88-
// Reset ResourceVersion to avoid a conflict with other updates to the build
89-
build.ResourceVersion = ""
90-
91-
glog.V(4).Infof("Setting build revision to %#v", build.Spec.Revision.Git)
92-
_, err := c.UpdateDetails(build)
93-
if err != nil {
94-
glog.V(0).Infof("error: An error occurred saving build revision: %v", err)
95-
}
96-
}
97-
9878
// randomBuildTag generates a random tag used for building images in such a way
9979
// that the built image can be referred to unambiguously even in the face of
10080
// concurrent builds with the same name in the same namespace.
@@ -108,11 +88,6 @@ func randomBuildTag(namespace, name string) string {
10888
return fmt.Sprintf("%s:%s", repo, randomTag)
10989
}
11090

111-
// containerNamePrefix prefixes the name of containers launched by a build. We
112-
// cannot reuse the prefix "k8s" because we don't want the containers to be
113-
// managed by a kubelet.
114-
const containerNamePrefix = "openshift"
115-
11691
// containerName creates names for Docker containers launched by a build. It is
11792
// meant to resemble Kubernetes' pkg/kubelet/dockertools.BuildDockerName.
11893
func containerName(strategyName, buildName, namespace, containerPurpose string) string {
@@ -180,3 +155,47 @@ func execPostCommitHook(client DockerClient, postCommitSpec api.BuildPostCommitS
180155
Stderr: true,
181156
})
182157
}
158+
159+
func updateBuildRevision(build *api.Build, sourceInfo *git.SourceInfo) *api.SourceRevision {
160+
if build.Spec.Revision != nil {
161+
return build.Spec.Revision
162+
}
163+
return &api.SourceRevision{
164+
Git: &api.GitSourceRevision{
165+
Commit: sourceInfo.CommitID,
166+
Message: sourceInfo.Message,
167+
Author: api.SourceControlUser{
168+
Name: sourceInfo.AuthorName,
169+
Email: sourceInfo.AuthorEmail,
170+
},
171+
Committer: api.SourceControlUser{
172+
Name: sourceInfo.CommitterName,
173+
Email: sourceInfo.CommitterEmail,
174+
},
175+
},
176+
}
177+
}
178+
179+
func retryBuildStatusUpdate(build *api.Build, client client.BuildInterface, sourceRev *api.SourceRevision) error {
180+
return kclient.RetryOnConflict(kclient.DefaultBackoff, func() error {
181+
// before updating, make sure we are using the latest version of the build
182+
latestBuild, err := client.Get(build.Name)
183+
if err != nil {
184+
// usually this means we failed to get resources due to the missing
185+
// privilleges
186+
return err
187+
}
188+
if sourceRev != nil {
189+
latestBuild.Spec.Revision = sourceRev
190+
latestBuild.ResourceVersion = ""
191+
}
192+
193+
latestBuild.Status.Reason = build.Status.Reason
194+
latestBuild.Status.Message = build.Status.Message
195+
196+
if _, err := client.UpdateDetails(latestBuild); err != nil {
197+
return err
198+
}
199+
return nil
200+
})
201+
}

pkg/build/builder/docker.go

+26-6
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
dockercmd "github.com/docker/docker/builder/dockerfile/command"
1313
"github.com/docker/docker/builder/dockerfile/parser"
1414
docker "github.com/fsouza/go-dockerclient"
15+
1516
kapi "k8s.io/kubernetes/pkg/api"
1617

1718
s2iapi "github.com/openshift/source-to-image/pkg/api"
@@ -69,12 +70,22 @@ func (d *DockerBuilder) Build() error {
6970
}
7071
sourceInfo, err := fetchSource(d.dockerClient, buildDir, d.build, d.urlTimeout, os.Stdin, d.gitClient)
7172
if err != nil {
73+
d.build.Status.Reason = api.StatusReasonFetchSourceFailed
74+
d.build.Status.Message = api.StatusMessageFetchSourceFailed
75+
if updateErr := retryBuildStatusUpdate(d.build, d.client, nil); updateErr != nil {
76+
glog.V(0).Infof("error: An error occured while updating the build status: %v", updateErr)
77+
}
7278
return err
7379
}
80+
7481
if sourceInfo != nil {
75-
updateBuildRevision(d.client, d.build, sourceInfo)
82+
glog.V(4).Infof("Setting build revision with details %#v", sourceInfo)
83+
revision := updateBuildRevision(d.build, sourceInfo)
84+
if updateErr := retryBuildStatusUpdate(d.build, d.client, revision); updateErr != nil {
85+
glog.V(0).Infof("error: An error occured while updating the build status: %v", updateErr)
86+
}
7687
}
77-
if err := d.addBuildParameters(buildDir); err != nil {
88+
if err = d.addBuildParameters(buildDir); err != nil {
7889
return err
7990
}
8091

@@ -91,14 +102,14 @@ func (d *DockerBuilder) Build() error {
91102
dockerfilePath := d.getDockerfilePath(buildDir)
92103
imageNames := getDockerfileFrom(dockerfilePath)
93104
if len(imageNames) == 0 {
94-
return fmt.Errorf("no from image in dockerfile.")
105+
return fmt.Errorf("no FROM image in Dockerfile")
95106
}
96107
for _, imageName := range imageNames {
97108
if imageName == "scratch" {
98109
glog.V(4).Infof("\nSkipping image \"scratch\"")
99110
continue
100111
}
101-
var imageExists bool = true
112+
imageExists := true
102113
_, err = d.dockerClient.InspectImage(imageName)
103114
if err != nil {
104115
if err != docker.ErrNoSuchImage {
@@ -113,18 +124,24 @@ func (d *DockerBuilder) Build() error {
113124
dockercfg.PullAuthType,
114125
)
115126
glog.V(0).Infof("\nPulling image %s ...", imageName)
116-
if err := pullImage(d.dockerClient, imageName, pullAuthConfig); err != nil {
127+
if err = pullImage(d.dockerClient, imageName, pullAuthConfig); err != nil {
128+
if updateErr := retryBuildStatusUpdate(d.build, d.client, nil); updateErr != nil {
129+
glog.V(0).Infof("error: An error occured while updating the build status: %v", updateErr)
130+
}
117131
return fmt.Errorf("failed to pull image: %v", err)
118132
}
119133
}
120134
}
121135

122-
if err := d.dockerBuild(buildDir, buildTag, d.build.Spec.Source.Secrets); err != nil {
136+
if err = d.dockerBuild(buildDir, buildTag, d.build.Spec.Source.Secrets); err != nil {
123137
return err
124138
}
125139

126140
cname := containerName("docker", d.build.Name, d.build.Namespace, "post-commit")
127141
if err := execPostCommitHook(d.dockerClient, d.build.Spec.PostCommit, buildTag, cname); err != nil {
142+
if updateErr := retryBuildStatusUpdate(d.build, d.client, nil); updateErr != nil {
143+
glog.V(0).Infof("error: An error occured while updating the build status: %v", updateErr)
144+
}
128145
return err
129146
}
130147

@@ -149,6 +166,9 @@ func (d *DockerBuilder) Build() error {
149166
}
150167
glog.V(0).Infof("\nPushing image %s ...", pushTag)
151168
if err := pushImage(d.dockerClient, pushTag, pushAuthConfig); err != nil {
169+
if updateErr := retryBuildStatusUpdate(d.build, d.client, nil); updateErr != nil {
170+
glog.V(0).Infof("error: An error occured while updating the build status: %v", updateErr)
171+
}
152172
return reportPushFailure(err, authPresent, pushAuthConfig)
153173
}
154174
glog.V(0).Infof("Push successful")

0 commit comments

Comments
 (0)