| 103 | } |
| 104 | |
| 105 | func (b *Backend) Upload(_ context.Context, r io.Reader, resource *pb.CASResource) error { |
| 106 | // We need to read the whole content before uploading it to the registry |
| 107 | // This is due to the fact that our OCI push implementation does not support streaming/chunks for uncompressed layers |
| 108 | // We can not use stream.Layer since it only supports compressed layers, we want to store raw data and set custom mimetypes |
| 109 | // https://github.com/google/go-containerregistry/blob/main/pkg/v1/stream/README.md |
| 110 | // TODO: Split content in multiple layers and do concurrent uploads/downloads |
| 111 | data, err := io.ReadAll(r) |
| 112 | if err != nil { |
| 113 | return fmt.Errorf("reading content: %w", err) |
| 114 | } |
| 115 | |
| 116 | ref, err := name.ParseReference(b.resourcePath(resource.Digest)) |
| 117 | if err != nil { |
| 118 | return fmt.Errorf("parsing reference: %w", err) |
| 119 | } |
| 120 | |
| 121 | img, err := craftImage(data, resource) |
| 122 | if err != nil { |
| 123 | return fmt.Errorf("crafting image: %w", err) |
| 124 | } |
| 125 | |
| 126 | if err := validateImage(img, resource.Digest); err != nil { |
| 127 | return fmt.Errorf("validating image: %w", err) |
| 128 | } |
| 129 | |
| 130 | err = remote.Write(ref, img, remote.WithAuthFromKeychain(b.keychain)) |
| 131 | if err != nil { |
| 132 | return fmt.Errorf("writing image: %w", err) |
| 133 | } |
| 134 | |
| 135 | return nil |
| 136 | } |
| 137 | |
| 138 | func (b *Backend) resourcePath(resourceName string) string { |
| 139 | return fmt.Sprintf("%s/%s-%s", b.repo, b.prefix, resourceName) |