(layers []v1.Descriptor, ociCompat api.OCIVersion)
| 160 | } |
| 161 | |
| 162 | func generateManifest(layers []v1.Descriptor, ociCompat api.OCIVersion) (v1.Descriptor, []v1.Descriptor, error) { |
| 163 | var toPush []v1.Descriptor |
| 164 | var config v1.Descriptor |
| 165 | var artifactType string |
| 166 | switch ociCompat { |
| 167 | case api.OCIVersion1_0: |
| 168 | // "Content other than OCI container images MAY be packaged using the image manifest. |
| 169 | // When this is done, the config.mediaType value MUST be set to a value specific to |
| 170 | // the artifact type or the empty value." |
| 171 | // Source: https://github.com/opencontainers/image-spec/blob/main/manifest.md#guidelines-for-artifact-usage |
| 172 | // |
| 173 | // The `ComposeEmptyConfigMediaType` is used specifically for this purpose: |
| 174 | // there is no config, and an empty descriptor is used for OCI 1.1 in |
| 175 | // conjunction with the `ArtifactType`, but for OCI 1.0 compatibility, |
| 176 | // tooling falls back to the config media type, so this is used to |
| 177 | // indicate that it's not a container image but custom content. |
| 178 | configData := []byte("{}") |
| 179 | config = v1.Descriptor{ |
| 180 | MediaType: ComposeEmptyConfigMediaType, |
| 181 | Digest: digest.FromBytes(configData), |
| 182 | Size: int64(len(configData)), |
| 183 | Data: configData, |
| 184 | } |
| 185 | // N.B. OCI 1.0 does NOT support specifying the artifact type, so it's |
| 186 | // left as an empty string to omit it from the marshaled JSON |
| 187 | artifactType = "" |
| 188 | toPush = append(toPush, config) |
| 189 | case api.OCIVersion1_1: |
| 190 | config = v1.DescriptorEmptyJSON |
| 191 | artifactType = ComposeProjectArtifactType |
| 192 | toPush = append(toPush, config) |
| 193 | default: |
| 194 | return v1.Descriptor{}, nil, fmt.Errorf("unsupported OCI version: %s", ociCompat) |
| 195 | } |
| 196 | |
| 197 | manifest, err := json.Marshal(v1.Manifest{ |
| 198 | Versioned: specs.Versioned{SchemaVersion: 2}, |
| 199 | MediaType: v1.MediaTypeImageManifest, |
| 200 | ArtifactType: artifactType, |
| 201 | Config: config, |
| 202 | Layers: layers, |
| 203 | Annotations: map[string]string{ |
| 204 | "org.opencontainers.image.created": time.Now().Format(time.RFC3339), |
| 205 | }, |
| 206 | }) |
| 207 | if err != nil { |
| 208 | return v1.Descriptor{}, nil, err |
| 209 | } |
| 210 | |
| 211 | manifestDescriptor := v1.Descriptor{ |
| 212 | MediaType: v1.MediaTypeImageManifest, |
| 213 | Digest: digest.FromString(string(manifest)), |
| 214 | Size: int64(len(manifest)), |
| 215 | Annotations: map[string]string{ |
| 216 | "com.docker.compose.version": api.ComposeVersion, |
| 217 | }, |
| 218 | ArtifactType: artifactType, |
| 219 | Data: manifest, |
no outgoing calls
no test coverage detected