@@ -216,10 +216,11 @@ enum AllowHTTP: String, ExpressibleByArgument, CaseIterable { case source, desti
216216
217217 // MARK: Build the image
218218
219- let finalImage = try await destination . publishContainerImage (
219+ let finalImage = try await publishContainerImage (
220220 baseImage: baseImage,
221221 destinationImage: destinationImage,
222222 source: source,
223+ destination: destination,
223224 architecture: architecture,
224225 os: os,
225226 resources: imageBuildOptions. resources,
@@ -232,165 +233,164 @@ enum AllowHTTP: String, ExpressibleByArgument, CaseIterable { case source, desti
232233 }
233234}
234235
235- extension RegistryClient {
236- func publishContainerImage(
237- baseImage: ImageReference ,
238- destinationImage: ImageReference ,
239- source: RegistryClient ? ,
240- architecture: String ,
241- os: String ,
242- resources: [ String ] ,
243- tag: String ? ,
244- verbose: Bool ,
245- executableURL: URL
246- ) async throws -> ImageReference {
247-
248- // MARK: Find the base image
249-
250- let baseImageManifest : ImageManifest
251- let baseImageConfiguration : ImageConfiguration
252- let baseImageDescriptor : ContentDescriptor
253- if let source {
254- ( baseImageManifest, baseImageDescriptor) = try await source. getImageManifest (
255- forImage: baseImage,
256- architecture: architecture
257- )
258- try log ( " Found base image manifest: \( ImageReference . Digest ( baseImageDescriptor. digest) ) " )
259-
260- baseImageConfiguration = try await source. getImageConfiguration (
261- forImage: baseImage,
262- digest: ImageReference . Digest ( baseImageManifest. config. digest)
263- )
264- log ( " Found base image configuration: \( baseImageManifest. config. digest) " )
265- } else {
266- baseImageManifest = . init(
267- schemaVersion: 2 ,
268- config: . init( mediaType: " scratch " , digest: " scratch " , size: 0 ) ,
269- layers: [ ]
270- )
271- baseImageConfiguration = . init(
272- architecture: architecture,
273- os: os,
274- rootfs: . init( _type: " layers " , diff_ids: [ ] )
275- )
276- if verbose { log ( " Using scratch as base image " ) }
277- }
278-
279- // MARK: Upload resource layers
280-
281- var resourceLayers : [ RegistryClient . ImageLayer ] = [ ]
282- for resourceDir in resources {
283- let resourceTardiff = try Archive ( ) . appendingRecursively ( atPath: resourceDir) . bytes
284- let resourceLayer = try await self . uploadLayer (
285- repository: destinationImage. repository,
286- contents: resourceTardiff
287- )
288-
289- if verbose {
290- log ( " resource layer: \( resourceLayer. descriptor. digest) ( \( resourceLayer. descriptor. size) bytes) " )
291- }
236+ func publishContainerImage(
237+ baseImage: ImageReference ,
238+ destinationImage: ImageReference ,
239+ source: RegistryClient ? ,
240+ destination: RegistryClient ,
241+ architecture: String ,
242+ os: String ,
243+ resources: [ String ] ,
244+ tag: String ? ,
245+ verbose: Bool ,
246+ executableURL: URL
247+ ) async throws -> ImageReference {
248+
249+ // MARK: Find the base image
250+
251+ let baseImageManifest : ImageManifest
252+ let baseImageConfiguration : ImageConfiguration
253+ let baseImageDescriptor : ContentDescriptor
254+ if let source {
255+ ( baseImageManifest, baseImageDescriptor) = try await source. getImageManifest (
256+ forImage: baseImage,
257+ architecture: architecture
258+ )
259+ try log ( " Found base image manifest: \( ImageReference . Digest ( baseImageDescriptor. digest) ) " )
292260
293- resourceLayers. append ( resourceLayer)
294- }
261+ baseImageConfiguration = try await source. getImageConfiguration (
262+ forImage: baseImage,
263+ digest: ImageReference . Digest ( baseImageManifest. config. digest)
264+ )
265+ log ( " Found base image configuration: \( baseImageManifest. config. digest) " )
266+ } else {
267+ baseImageManifest = . init(
268+ schemaVersion: 2 ,
269+ config: . init( mediaType: " scratch " , digest: " scratch " , size: 0 ) ,
270+ layers: [ ]
271+ )
272+ baseImageConfiguration = . init(
273+ architecture: architecture,
274+ os: os,
275+ rootfs: . init( _type: " layers " , diff_ids: [ ] )
276+ )
277+ if verbose { log ( " Using scratch as base image " ) }
278+ }
295279
296- // MARK: Upload the application layer
280+ // MARK: Upload resource layers
297281
298- let applicationLayer = try await self . uploadLayer (
282+ var resourceLayers : [ RegistryClient . ImageLayer ] = [ ]
283+ for resourceDir in resources {
284+ let resourceTardiff = try Archive ( ) . appendingRecursively ( atPath: resourceDir) . bytes
285+ let resourceLayer = try await destination. uploadLayer (
299286 repository: destinationImage. repository,
300- contents: try Archive ( ) . appendingFile ( at : executableURL ) . bytes
287+ contents: resourceTardiff
301288 )
289+
302290 if verbose {
303- log ( " application layer: \( applicationLayer . descriptor. digest) ( \( applicationLayer . descriptor. size) bytes) " )
291+ log ( " resource layer: \( resourceLayer . descriptor. digest) ( \( resourceLayer . descriptor. size) bytes) " )
304292 }
305293
306- // MARK: Create the application configuration
294+ resourceLayers. append ( resourceLayer)
295+ }
307296
308- let timestamp = Date ( timeIntervalSince1970 : 0 ) . ISO8601Format ( )
297+ // MARK: Upload the application layer
309298
310- // Inherit the configuration of the base image - UID, GID, environment etc -
311- // and override the entrypoint.
312- var inheritedConfiguration = baseImageConfiguration. config ?? . init( )
313- inheritedConfiguration. Entrypoint = [ " / \( executableURL. lastPathComponent) " ]
314- inheritedConfiguration. Cmd = [ ]
315- inheritedConfiguration. WorkingDir = " / "
299+ let applicationLayer = try await destination. uploadLayer (
300+ repository: destinationImage. repository,
301+ contents: try Archive ( ) . appendingFile ( at: executableURL) . bytes
302+ )
303+ if verbose {
304+ log ( " application layer: \( applicationLayer. descriptor. digest) ( \( applicationLayer. descriptor. size) bytes) " )
305+ }
316306
317- let configuration = ImageConfiguration (
318- created: timestamp,
319- architecture: architecture,
320- os: os,
321- config: inheritedConfiguration,
322- rootfs: . init(
323- _type: " layers " ,
324- // The diff_id is the digest of the _uncompressed_ layer archive.
325- // It is used by the runtime, which might not store the layers in
326- // the compressed form in which it received them from the registry.
327- diff_ids: baseImageConfiguration. rootfs. diff_ids
328- + resourceLayers. map { " \( $0. diffID) " }
329- + [ " \( applicationLayer. diffID) " ]
330- ) ,
331- history: [ . init( created: timestamp, created_by: " containertool " ) ]
332- )
307+ // MARK: Create the application configuration
308+
309+ let timestamp = Date ( timeIntervalSince1970: 0 ) . ISO8601Format ( )
310+
311+ // Inherit the configuration of the base image - UID, GID, environment etc -
312+ // and override the entrypoint.
313+ var inheritedConfiguration = baseImageConfiguration. config ?? . init( )
314+ inheritedConfiguration. Entrypoint = [ " / \( executableURL. lastPathComponent) " ]
315+ inheritedConfiguration. Cmd = [ ]
316+ inheritedConfiguration. WorkingDir = " / "
317+
318+ let configuration = ImageConfiguration (
319+ created: timestamp,
320+ architecture: architecture,
321+ os: os,
322+ config: inheritedConfiguration,
323+ rootfs: . init(
324+ _type: " layers " ,
325+ // The diff_id is the digest of the _uncompressed_ layer archive.
326+ // It is used by the runtime, which might not store the layers in
327+ // the compressed form in which it received them from the registry.
328+ diff_ids: baseImageConfiguration. rootfs. diff_ids
329+ + resourceLayers. map { " \( $0. diffID) " }
330+ + [ " \( applicationLayer. diffID) " ]
331+ ) ,
332+ history: [ . init( created: timestamp, created_by: " containertool " ) ]
333+ )
333334
334- let configurationBlobReference = try await self . putImageConfiguration (
335- forImage: destinationImage,
336- configuration: configuration
337- )
335+ let configurationBlobReference = try await destination . putImageConfiguration (
336+ forImage: destinationImage,
337+ configuration: configuration
338+ )
338339
339- if verbose {
340- log ( " image configuration: \( configurationBlobReference. digest) ( \( configurationBlobReference. size) bytes) " )
341- }
340+ if verbose {
341+ log ( " image configuration: \( configurationBlobReference. digest) ( \( configurationBlobReference. size) bytes) " )
342+ }
342343
343- // MARK: Create application manifest
344+ // MARK: Create application manifest
344345
345- let manifest = ImageManifest (
346- schemaVersion: 2 ,
347- mediaType: " application/vnd.oci.image.manifest.v1+json " ,
348- config: configurationBlobReference,
349- layers: baseImageManifest. layers
350- + resourceLayers. map { $0. descriptor }
351- + [ applicationLayer. descriptor]
352- )
346+ let manifest = ImageManifest (
347+ schemaVersion: 2 ,
348+ mediaType: " application/vnd.oci.image.manifest.v1+json " ,
349+ config: configurationBlobReference,
350+ layers: baseImageManifest. layers
351+ + resourceLayers. map { $0. descriptor }
352+ + [ applicationLayer. descriptor]
353+ )
353354
354- // MARK: Upload base image
355-
356- // Copy the base image layers to the destination repository
357- // Layers could be checked and uploaded concurrently
358- // This could also happen in parallel with the application image build
359- if let source {
360- for layer in baseImageManifest. layers {
361- try await source. copyBlob (
362- digest: ImageReference . Digest ( layer. digest) ,
363- fromRepository: baseImage. repository,
364- toClient: self ,
365- toRepository: destinationImage. repository
366- )
367- }
355+ // MARK: Upload base image
356+
357+ // Copy the base image layers to the destination repository
358+ // Layers could be checked and uploaded concurrently
359+ // This could also happen in parallel with the application image build
360+ if let source {
361+ for layer in baseImageManifest. layers {
362+ try await source. copyBlob (
363+ digest: ImageReference . Digest ( layer. digest) ,
364+ fromRepository: baseImage. repository,
365+ toClient: destination,
366+ toRepository: destinationImage. repository
367+ )
368368 }
369+ }
369370
370- // MARK: Upload application manifest
371-
372- let manifestDescriptor = try await self . putManifest (
373- repository: destinationImage. repository,
374- reference: destinationImage. reference,
375- manifest: manifest
376- )
371+ // MARK: Upload application manifest
377372
378- if verbose {
379- log ( " manifest: \( manifestDescriptor. digest) ( \( manifestDescriptor. size) bytes) " )
380- }
373+ let manifestDescriptor = try await destination. putManifest (
374+ repository: destinationImage. repository,
375+ reference: destinationImage. reference,
376+ manifest: manifest
377+ )
381378
382- // Use the manifest's digest if the user did not provide a human-readable tag
383- // To support multiarch images, we should also create an an index pointing to
384- // this manifest.
385- let reference : ImageReference . Reference
386- if let tag {
387- reference = try ImageReference . Tag ( tag)
388- } else {
389- reference = try ImageReference . Digest ( manifestDescriptor. digest)
390- }
379+ if verbose {
380+ log ( " manifest: \( manifestDescriptor. digest) ( \( manifestDescriptor. size) bytes) " )
381+ }
391382
392- var result = destinationImage
393- result. reference = reference
394- return result
383+ // Use the manifest's digest if the user did not provide a human-readable tag
384+ // To support multiarch images, we should also create an an index pointing to
385+ // this manifest.
386+ let reference : ImageReference . Reference
387+ if let tag {
388+ reference = try ImageReference . Tag ( tag)
389+ } else {
390+ reference = try ImageReference . Digest ( manifestDescriptor. digest)
395391 }
392+
393+ var result = destinationImage
394+ result. reference = reference
395+ return result
396396}
0 commit comments