4
4
# arguments provided by the user.
5
5
6
6
import argparse
7
+ import json
7
8
import os
8
9
import sys
9
10
from cosalib .container_manifest import create_and_push_container_manifest
10
11
from cosalib .builds import Builds
11
12
from cosalib .meta import GenericBuildMeta
13
+ from cosalib .cmdlib import runcmd
12
14
from cosalib .cmdlib import sha256sum_file
13
15
14
16
sys .path .insert (0 , os .path .dirname (os .path .abspath (__file__ )))
15
17
16
18
17
19
def main ():
18
20
args = parse_args ()
21
+ map_arch = {}
22
+ map_arch ['arm64' ] = 'aarch64'
23
+ map_arch ['amd64' ] = 'x86_64'
24
+
19
25
if args .authfile :
20
26
os .environ ["REGISTRY_AUTH_FILE" ] = args .authfile
21
27
if args .images :
@@ -37,6 +43,19 @@ def main():
37
43
# - Store the path to the container image in the container_images list
38
44
images = []
39
45
buildmetas = dict ()
46
+ digests = {}
47
+ upload = False
48
+ # Checks if we already have it in the remote
49
+ cmd = ["skopeo" , "inspect" , "--raw" , f"docker://{ args .repo } :{ args .tags [0 ]} " ]
50
+ manifest_meta = runcmd (cmd , capture_output = True , check = False ).stdout
51
+ if manifest_meta :
52
+ manifests = json .loads (manifest_meta )
53
+ for manifest in manifests ['manifests' ]:
54
+ arch = manifest ['platform' ]['architecture' ]
55
+ if arch in map_arch :
56
+ arch = map_arch [arch ]
57
+ digests [arch ] = manifest ['digest' ]
58
+
40
59
for arch in args .arches :
41
60
if arch not in build_arches :
42
61
print (f"Requested architecture { arch } is not in { args .build } " )
@@ -48,6 +67,14 @@ def main():
48
67
if not buildmeta ['images' ][args .artifact ]:
49
68
print (f"No artifact { args .artifact } in { args .build } /{ arch } " )
50
69
raise Exception
70
+
71
+ # Checks if the meta digest matches each arch digest in the remote
72
+ if 'digest' in buildmetas [arch ][args .metajsonname ]:
73
+ digest = buildmetas [arch ][args .metajsonname ]['digest' ]
74
+ if arch not in digests :
75
+ upload = True
76
+ elif digest != digests [arch ]:
77
+ upload = True
51
78
ociarchive = os .path .join (builddir , buildmeta ['images' ][args .artifact ]['path' ])
52
79
ocisha256sum = buildmeta ['images' ][args .artifact ]['sha256' ]
53
80
if not os .path .exists (ociarchive ):
@@ -58,26 +85,25 @@ def main():
58
85
raise Exception
59
86
images .append (f"oci-archive:{ ociarchive } " )
60
87
61
- # Create/Upload the manifest list to the container registry
62
- manifest_info = create_and_push_container_manifest (
63
- args .repo , args .tags , images , args .v2s2 )
64
-
65
- # Update the `meta.json` files. Note the digest included is the
66
- # arch-specific one for each individual arch, and not the manifest list
67
- # digest. See: https://github.com/coreos/coreos-assembler/issues/3122.
68
- assert len (manifest_info ['manifests' ]) == len (buildmetas )
69
- for manifest in manifest_info ['manifests' ]:
70
- arch = manifest ['platform' ]['architecture' ]
71
- if arch == 'arm64' :
72
- arch = 'aarch64'
73
- elif arch == 'amd64' :
74
- arch = 'x86_64'
75
- buildmetas [arch ][args .metajsonname ] = {
76
- 'image' : args .repo ,
77
- 'digest' : manifest ['digest' ],
78
- 'tags' : args .tags
79
- }
80
- buildmetas [arch ].write (artifact_name = args .metajsonname )
88
+ if upload is True or args .force is True :
89
+ # Create/Upload the manifest list to the container registry
90
+ manifest_info = create_and_push_container_manifest (
91
+ args .repo , args .tags , images , args .v2s2 )
92
+
93
+ # Update the `meta.json` files. Note the digest included is the
94
+ # arch-specific one for each individual arch, and not the manifest list
95
+ # digest. See: https://github.com/coreos/coreos-assembler/issues/3122.
96
+ assert len (manifest_info ['manifests' ]) == len (buildmetas )
97
+ for manifest in manifest_info ['manifests' ]:
98
+ arch = manifest ['platform' ]['architecture' ]
99
+ if arch in map_arch :
100
+ arch = map_arch [arch ]
101
+ buildmetas [arch ][args .metajsonname ] = {
102
+ 'image' : args .repo ,
103
+ 'digest' : manifest ['digest' ],
104
+ 'tags' : args .tags
105
+ }
106
+ buildmetas [arch ].write (artifact_name = args .metajsonname )
81
107
82
108
83
109
def parse_args ():
@@ -108,6 +134,7 @@ Examples:
108
134
parser .add_argument ("--authfile" , help = "A file to use for registry auth" )
109
135
parser .add_argument ('--v2s2' , action = 'store_true' ,
110
136
help = 'Use old image manifest version 2 schema 2 format' )
137
+ parser .add_argument ("--force" , help = "Force manifest overwriting" , action = 'store_true' )
111
138
112
139
group = parser .add_mutually_exclusive_group (required = True )
113
140
group .add_argument ("--image" , dest = 'images' , action = 'append' , default = [],
0 commit comments