diff --git a/pkg/logs/wait_for_image.go b/pkg/logs/wait_for_image.go index 76fd1114b..22e56fe81 100644 --- a/pkg/logs/wait_for_image.go +++ b/pkg/logs/wait_for_image.go @@ -5,15 +5,15 @@ import ( "fmt" "io" + "github.com/pivotal/kpack/pkg/apis/build/v1alpha1" + corev1alpha1 "github.com/pivotal/kpack/pkg/apis/core/v1alpha1" + "github.com/pivotal/kpack/pkg/client/clientset/versioned" "github.com/pkg/errors" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/watch" "k8s.io/client-go/tools/cache" watchTools "k8s.io/client-go/tools/watch" - - "github.com/pivotal/kpack/pkg/apis/build/v1alpha1" - corev1alpha1 "github.com/pivotal/kpack/pkg/apis/core/v1alpha1" - "github.com/pivotal/kpack/pkg/client/clientset/versioned" ) type imageWaiter struct { @@ -97,17 +97,22 @@ func imageFailure(name, statusMessage string) error { } func (w *imageWaiter) waitBuild(ctx context.Context, writer io.Writer, namespace, buildName string) (string, error) { - doneChan := make(chan struct{}) - defer func() { <-doneChan }() - - go func() { // tail logs - defer close(doneChan) - err := w.logTailer.TailBuildName(ctx, writer, namespace, buildName) - if err != nil { - fmt.Fprintf(writer, "error tailing logs %s", err) - } - }() - + err := w.imageBuildStarted(ctx, namespace, buildName) + if err != nil { + fmt.Fprintf(writer, "Build failed to start: %s", err) + return "", nil + } else { + doneChan := make(chan struct{}) + defer func() { <-doneChan }() + + go func() { // tail logs + defer close(doneChan) + err := w.logTailer.TailBuildName(ctx, writer, namespace, buildName) + if err != nil { + fmt.Fprintf(writer, "error tailing logs %s", err) + } + }() + } build, err := w.buildWatchUntil(ctx, namespace, buildName, filterErrors(buildHasResolved)) if err != nil { return "", err @@ -173,3 +178,16 @@ func filterErrors(condition watchTools.ConditionFunc) watchTools.ConditionFunc { return condition(event) } } + +func (w *imageWaiter) imageBuildStarted(ctx context.Context, namespace, buildName string) error { + build, err := w.KpackClient.KpackV1alpha1().Builds(namespace).Get(ctx, buildName, v1.GetOptions{}) + if err != nil { + return err + } + + condition := build.Status.GetCondition(corev1alpha1.ConditionSucceeded) + if condition.IsFalse() { + return errors.New(condition.Message) + } + return nil +} diff --git a/pkg/logs/wait_for_image_test.go b/pkg/logs/wait_for_image_test.go index 783820986..0ec879e55 100644 --- a/pkg/logs/wait_for_image_test.go +++ b/pkg/logs/wait_for_image_test.go @@ -6,6 +6,8 @@ import ( "io" "testing" + "k8s.io/apimachinery/pkg/runtime" + "github.com/sclevine/spec" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -96,9 +98,11 @@ func testWaitForImage(t *testing.T, when spec.G, it spec.S) { _, err := clientset.KpackV1alpha1().Images(namespace).Create(context.TODO(), image, metav1.CreateOptions{}) require.NoError(t, err) - _, err = clientset.KpackV1alpha1().Builds(namespace).Create(context.TODO(), successfulBuild, metav1.CreateOptions{}) + build, err := clientset.KpackV1alpha1().Builds(namespace).Create(context.TODO(), successfulBuild, metav1.CreateOptions{}) require.NoError(t, err) - + clientset.PrependReactor("get", "builds", func(action clientgotesting.Action) (handled bool, ret runtime.Object, err error) { + return true, build, nil + }) result, err := imageWaiter.Wait(context.TODO(), out, image) assert.NoError(t, err) assert.Equal(t, successfulBuild.Status.LatestImage, result)