in ecr/layer_writer.go [157:203]
func (lw *layerWriter) Commit(ctx context.Context, size int64, expected digest.Digest, opts ...content.Opt) error {
log.G(lw.ctx).WithField("size", size).WithField("expected", expected).Debug("ecr.layer.commit")
lw.buf.Close()
select {
case err := <-lw.err:
if err != nil {
log.G(lw.ctx).
WithError(err).
WithField("expected", expected).
Error("ecr.layer.commit: error while uploading parts")
return err
}
case <-lw.ctx.Done():
}
completeLayerUploadInput := &ecr.CompleteLayerUploadInput{
RegistryId: aws.String(lw.base.ecrSpec.Registry()),
RepositoryName: aws.String(lw.base.ecrSpec.Repository),
UploadId: aws.String(lw.uploadID),
LayerDigests: []*string{aws.String(expected.String())},
}
completeLayerUploadOutput, err := lw.base.client.CompleteLayerUpload(completeLayerUploadInput)
if err != nil {
// If the layer that is being uploaded already exists then return successfully instead of failing. Unfortunately
// in this case we do not get the digest back from ECR, but if the client-provided digest starts with a
// "sha256:" then the ECR has validated that the digest provided matches ours. If the expected digest uses a
// different algorithm we have to fail as we do not know the digest ECR calculated and the expected digest
// has not been validated.
awsErr, ok := err.(awserr.Error)
if ok && awsErr.Code() == "LayerAlreadyExistsException" && strings.HasPrefix(expected.String(), "sha256:") {
log.G(lw.ctx).Debug("ecr.layer.commit: layer already exists")
return nil
} else {
return err
}
}
actualDigest := aws.StringValue(completeLayerUploadOutput.LayerDigest)
if actualDigest != expected.String() {
return errors.New("ecr: failed to validate uploaded digest")
}
log.G(ctx).
WithField("expected", expected).
WithField("actual", actualDigest).
Debug("ecr.layer.commit: complete")
return nil
}