diff --git a/client/build.go b/client/build.go index a8743f6..2d3b3aa 100644 --- a/client/build.go +++ b/client/build.go @@ -138,12 +138,15 @@ func (c *BuildClient) ListForAppAll(ctx context.Context, appGUID string, opts *B // PollStaged waits until the build is staged, fails, or times out func (c *BuildClient) PollStaged(ctx context.Context, guid string, opts *PollingOptions) error { - return PollForStateOrTimeout(func() (string, error) { + return PollForStateOrTimeout(func() (string, string, error) { build, err := c.Get(ctx, guid) if build != nil { - return string(build.State), err + if build.Error != nil { + return string(build.State), *build.Error, err + } + return string(build.State), "", err } - return "", err + return "", "", err }, string(resource.BuildStateStaged), opts) } diff --git a/client/job.go b/client/job.go index bf7bfb7..3cdb295 100644 --- a/client/job.go +++ b/client/job.go @@ -21,12 +21,16 @@ func (c *JobClient) Get(ctx context.Context, guid string) (*resource.Job, error) // PollComplete waits until the job completes, fails, or times out func (c *JobClient) PollComplete(ctx context.Context, jobGUID string, opts *PollingOptions) error { - err := PollForStateOrTimeout(func() (string, error) { + err := PollForStateOrTimeout(func() (string, string, error) { job, err := c.Get(ctx, jobGUID) if job != nil { - return string(job.State), err + var cfErrors string + for _, error := range job.Errors { + cfErrors = cfErrors + "\n" + error.Error() + } + return string(job.State), cfErrors, err } - return "", err + return "", "", err }, string(resource.JobStateComplete), opts) // attempt to return the underlying saved job error diff --git a/client/package.go b/client/package.go index 5743d1a..14b5561 100644 --- a/client/package.go +++ b/client/package.go @@ -143,12 +143,12 @@ func (c *PackageClient) ListForAppAll(ctx context.Context, appGUID string, opts // PollReady waits until the package is ready, fails, or times out func (c *PackageClient) PollReady(ctx context.Context, guid string, opts *PollingOptions) error { - return PollForStateOrTimeout(func() (string, error) { + return PollForStateOrTimeout(func() (string, string, error) { pkg, err := c.Get(ctx, guid) if pkg != nil { - return string(pkg.State), err + return string(pkg.State), "", err } - return "", err + return "", "", err }, string(resource.PackageStateReady), opts) } diff --git a/client/polling.go b/client/polling.go index 580dea2..b55d585 100644 --- a/client/polling.go +++ b/client/polling.go @@ -22,7 +22,7 @@ func NewPollingOptions() *PollingOptions { } } -type getStateFunc func() (string, error) +type getStateFunc func() (string, string, error) func PollForStateOrTimeout(getState getStateFunc, successState string, opts *PollingOptions) error { if opts == nil { @@ -38,7 +38,7 @@ func PollForStateOrTimeout(getState getStateFunc, successState string, opts *Pol case <-timeout: return AsyncProcessTimeoutError case <-ticker.C: - state, err := getState() + state, cferror, err := getState() if err != nil { return err } @@ -46,7 +46,7 @@ func PollForStateOrTimeout(getState getStateFunc, successState string, opts *Pol case successState: return nil case opts.FailedState: - return AsyncProcessFailedError + return errors.Join(AsyncProcessFailedError, errors.New(cferror)) } } } diff --git a/client/polling_test.go b/client/polling_test.go index 1156bd3..be1e416 100644 --- a/client/polling_test.go +++ b/client/polling_test.go @@ -1,11 +1,15 @@ package client import ( - "github.com/stretchr/testify/require" + "errors" "testing" "time" + + "github.com/stretchr/testify/require" ) +var CustomStagingErr = "StagingError - Staging error: Start command not specified" + func TestNewPollingOptions(t *testing.T) { opts := NewPollingOptions() require.Equal(t, "FAILED", opts.FailedState) @@ -18,18 +22,18 @@ func TestPollForStateOrTimeout(t *testing.T) { noWaitOpts.Timeout = time.Second noWaitOpts.CheckInterval = time.Millisecond - failedFn := func() (string, error) { - return "FAILED", nil + failedFn := func() (string, string, error) { + return "FAILED", CustomStagingErr, nil } - successFn := func() (string, error) { - return "SUCCESS", nil + successFn := func() (string, string, error) { + return "SUCCESS", "", nil } - timeoutFn := func() (string, error) { - return "PROCESSING", nil + timeoutFn := func() (string, string, error) { + return "PROCESSING", "", nil } err := PollForStateOrTimeout(failedFn, "NOPE", noWaitOpts) - require.Equal(t, AsyncProcessFailedError, err) + require.Equal(t, errors.Join(AsyncProcessFailedError, errors.New(CustomStagingErr)), err) err = PollForStateOrTimeout(successFn, "SUCCESS", noWaitOpts) require.NoError(t, err) diff --git a/operation/push.go b/operation/push.go index c5035da..f81c119 100644 --- a/operation/push.go +++ b/operation/push.go @@ -187,12 +187,12 @@ func (p *AppPushOperation) waitForDeployment(ctx context.Context, deploymentGUID pollOptions := client.NewPollingOptions() pollOptions.Timeout = time.Duration(instances) * time.Minute - depPollErr := client.PollForStateOrTimeout(func() (string, error) { + depPollErr := client.PollForStateOrTimeout(func() (string, string, error) { deployment, err := p.client.Deployments.Get(ctx, deploymentGUID) if err != nil { - return "", err + return "", "", err } - return deployment.Status.Value, nil + return deployment.Status.Value, deployment.Status.Reason, nil }, "FINALIZED", pollOptions) return depPollErr }