Skip to content

Commit 4432145

Browse files
author
Victor
committed
add failure reasons
1 parent 0836881 commit 4432145

File tree

19 files changed

+441
-104
lines changed

19 files changed

+441
-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

+27-6
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ 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"
17+
utilruntime "k8s.io/kubernetes/pkg/util/runtime"
1618

1719
s2iapi "github.com/openshift/source-to-image/pkg/api"
1820
"github.com/openshift/source-to-image/pkg/tar"
@@ -69,12 +71,22 @@ func (d *DockerBuilder) Build() error {
6971
}
7072
sourceInfo, err := fetchSource(d.dockerClient, buildDir, d.build, d.urlTimeout, os.Stdin, d.gitClient)
7173
if err != nil {
74+
d.build.Status.Reason = api.StatusReasonFetchSourceFailed
75+
d.build.Status.Message = api.StatusMessageFetchSourceFailed
76+
if updateErr := retryBuildStatusUpdate(d.build, d.client, nil); updateErr != nil {
77+
utilruntime.HandleError(fmt.Errorf("error: An error occured while updating the build status: %v", updateErr))
78+
}
7279
return err
7380
}
81+
7482
if sourceInfo != nil {
75-
updateBuildRevision(d.client, d.build, sourceInfo)
83+
glog.V(4).Infof("Setting build revision with details %#v", sourceInfo)
84+
revision := updateBuildRevision(d.build, sourceInfo)
85+
if updateErr := retryBuildStatusUpdate(d.build, d.client, revision); updateErr != nil {
86+
utilruntime.HandleError(fmt.Errorf("error: An error occured while updating the build status: %v", updateErr))
87+
}
7688
}
77-
if err := d.addBuildParameters(buildDir); err != nil {
89+
if err = d.addBuildParameters(buildDir); err != nil {
7890
return err
7991
}
8092

@@ -91,14 +103,14 @@ func (d *DockerBuilder) Build() error {
91103
dockerfilePath := d.getDockerfilePath(buildDir)
92104
imageNames := getDockerfileFrom(dockerfilePath)
93105
if len(imageNames) == 0 {
94-
return fmt.Errorf("no from image in dockerfile.")
106+
return fmt.Errorf("no FROM image in Dockerfile")
95107
}
96108
for _, imageName := range imageNames {
97109
if imageName == "scratch" {
98110
glog.V(4).Infof("\nSkipping image \"scratch\"")
99111
continue
100112
}
101-
var imageExists bool = true
113+
imageExists := true
102114
_, err = d.dockerClient.InspectImage(imageName)
103115
if err != nil {
104116
if err != docker.ErrNoSuchImage {
@@ -113,18 +125,24 @@ func (d *DockerBuilder) Build() error {
113125
dockercfg.PullAuthType,
114126
)
115127
glog.V(0).Infof("\nPulling image %s ...", imageName)
116-
if err := pullImage(d.dockerClient, imageName, pullAuthConfig); err != nil {
128+
if err = pullImage(d.dockerClient, imageName, pullAuthConfig); err != nil {
129+
if updateErr := retryBuildStatusUpdate(d.build, d.client, nil); updateErr != nil {
130+
utilruntime.HandleError(fmt.Errorf("error: An error occured while updating the build status: %v", updateErr))
131+
}
117132
return fmt.Errorf("failed to pull image: %v", err)
118133
}
119134
}
120135
}
121136

122-
if err := d.dockerBuild(buildDir, buildTag, d.build.Spec.Source.Secrets); err != nil {
137+
if err = d.dockerBuild(buildDir, buildTag, d.build.Spec.Source.Secrets); err != nil {
123138
return err
124139
}
125140

126141
cname := containerName("docker", d.build.Name, d.build.Namespace, "post-commit")
127142
if err := execPostCommitHook(d.dockerClient, d.build.Spec.PostCommit, buildTag, cname); err != nil {
143+
if updateErr := retryBuildStatusUpdate(d.build, d.client, nil); updateErr != nil {
144+
utilruntime.HandleError(fmt.Errorf("error: An error occured while updating the build status: %v", updateErr))
145+
}
128146
return err
129147
}
130148

@@ -149,6 +167,9 @@ func (d *DockerBuilder) Build() error {
149167
}
150168
glog.V(0).Infof("\nPushing image %s ...", pushTag)
151169
if err := pushImage(d.dockerClient, pushTag, pushAuthConfig); err != nil {
170+
if updateErr := retryBuildStatusUpdate(d.build, d.client, nil); updateErr != nil {
171+
utilruntime.HandleError(fmt.Errorf("error: An error occured while updating the build status: %v", updateErr))
172+
}
152173
return reportPushFailure(err, authPresent, pushAuthConfig)
153174
}
154175
glog.V(0).Infof("Push successful")

0 commit comments

Comments
 (0)