From eabf76af0142b5a55119653017c2b0a1ddb2900a Mon Sep 17 00:00:00 2001 From: Jeremy Rickard Date: Tue, 13 Aug 2019 17:48:45 -0600 Subject: [PATCH] Update the docker driver to return early from fetchOutputs if there are no outputs defined on the operation. If there are none defined on the operation, there is a good chance /cnab/app/outputs won't exist and we shouldn't try to copy from it. If they do exist, we should continue and if it doesn't exist that is a failure case with that invocation image. --- driver/docker/docker.go | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/driver/docker/docker.go b/driver/docker/docker.go index 134d75ea..181c9851 100644 --- a/driver/docker/docker.go +++ b/driver/docker/docker.go @@ -227,21 +227,21 @@ func (d *Driver) exec(op *driver.Operation) (driver.OperationResult, error) { select { case err := <-errc: if err != nil { - opResult, fetchErr := d.fetchOutputs(ctx, resp.ID) + opResult, fetchErr := d.fetchOutputs(ctx, resp.ID, op) return opResult, containerError("error in container", err, fetchErr) } case s := <-statusc: if s.StatusCode == 0 { - return d.fetchOutputs(ctx, resp.ID) + return d.fetchOutputs(ctx, resp.ID, op) } if s.Error != nil { - opResult, fetchErr := d.fetchOutputs(ctx, resp.ID) + opResult, fetchErr := d.fetchOutputs(ctx, resp.ID, op) return opResult, containerError(fmt.Sprintf("container exit code: %d, message", s.StatusCode), err, fetchErr) } - opResult, fetchErr := d.fetchOutputs(ctx, resp.ID) + opResult, fetchErr := d.fetchOutputs(ctx, resp.ID, op) return opResult, containerError(fmt.Sprintf("container exit code: %d, message", s.StatusCode), err, fetchErr) } - opResult, fetchErr := d.fetchOutputs(ctx, resp.ID) + opResult, fetchErr := d.fetchOutputs(ctx, resp.ID, op) if fetchErr != nil { return opResult, fmt.Errorf("fetching outputs failed: %s", fetchErr) } @@ -259,10 +259,16 @@ func containerError(containerMessage string, containerErr, fetchErr error) error // fetchOutputs takes a context and a container ID; it copies the /cnab/app/outputs directory from that container. // The goal is to collect all the files in the directory (recursively) and put them in a flat map of path to contents. // This map will be inside the OperationResult. When fetchOutputs returns an error, it may also return partial results. -func (d *Driver) fetchOutputs(ctx context.Context, container string) (driver.OperationResult, error) { +func (d *Driver) fetchOutputs(ctx context.Context, container string, op *driver.Operation) (driver.OperationResult, error) { opResult := driver.OperationResult{ Outputs: map[string]string{}, } + // The /cnab/app/outputs directory probably only exists if outputs are created. In the + // case there are no outputs defined on the operation, there probably are none to copy + // and we should return early. + if len(op.Outputs) == 0 { + return opResult, nil + } ioReader, _, err := d.dockerCli.Client().CopyFromContainer(ctx, container, "/cnab/app/outputs") if err != nil { return opResult, fmt.Errorf("error copying outputs from container: %s", err)