Add script to re-tag plugin
parent
ef789c0f4b
commit
4a4110649d
@ -0,0 +1,81 @@
|
||||
import os
|
||||
|
||||
import dxf
|
||||
|
||||
MTYPE_PLUGIN_CONFIG = 'application/vnd.docker.plugin.v1+json'
|
||||
MTYPE_LAYER = 'application/vnd.docker.image.rootfs.diff.tar.gzip'
|
||||
MTYPE_MANIFEST = 'application/vnd.docker.distribution.manifest.v2+json'
|
||||
MTYPE_MANIFEST_LIST = 'application/vnd.docker.distribution.manifest.list.v2+json'
|
||||
|
||||
class Platform:
|
||||
def __init__(self, s):
|
||||
self.buildx = s
|
||||
|
||||
split = s.split('/')
|
||||
if len(split) < 2:
|
||||
raise Exception('Invalid platform format')
|
||||
|
||||
self.dirname = '_'.join(split)
|
||||
|
||||
self.os = split[0]
|
||||
self.architecture = split[1]
|
||||
|
||||
self.variant = None
|
||||
if len(split) > 3:
|
||||
raise Exception('Invalid platform format')
|
||||
elif len(split) == 3:
|
||||
self.variant = split[2]
|
||||
elif self.architecture == 'arm64':
|
||||
# Weird exception? (seen in alpine images)
|
||||
self.variant = 'v8'
|
||||
|
||||
@property
|
||||
def manifest(self):
|
||||
d = {
|
||||
'os': self.os,
|
||||
'architecture': self.architecture,
|
||||
}
|
||||
if self.variant is not None:
|
||||
d['variant'] = self.variant
|
||||
|
||||
return d
|
||||
|
||||
def tag(self, t):
|
||||
if self.variant is not None:
|
||||
return f'{t}-{self.os}-{self.architecture}-{self.variant}'
|
||||
return f'{t}-{self.os}-{self.architecture}'
|
||||
|
||||
def __str__(self):
|
||||
return f'Platform(os={self.os}, architecture={self.architecture}, variant={self.variant})'
|
||||
def __repr__(self):
|
||||
return str(self)
|
||||
|
||||
def dxf_auth(reg: dxf.DXF, res):
|
||||
reg.authenticate(username=os.getenv('REGISTRY_USERNAME'), password=os.getenv('REGISTRY_PASSWORD'), response=res)
|
||||
|
||||
class DXF(dxf.DXF):
|
||||
def set_manifest(self, alias, manifest_json, mime=MTYPE_MANIFEST):
|
||||
"""
|
||||
Give a name (alias) to a manifest.
|
||||
|
||||
:param alias: Alias name
|
||||
:type alias: str
|
||||
|
||||
:param manifest_json: A V2 Schema 2 manifest JSON string
|
||||
:type digests: list
|
||||
"""
|
||||
self._request('put',
|
||||
'manifests/' + alias,
|
||||
data=manifest_json,
|
||||
headers={'Content-Type': mime})
|
||||
|
||||
def push_manifest(self, manifest_dict, ref=None, mime=MTYPE_MANIFEST):
|
||||
mf = json.dumps(manifest_dict, sort_keys=True).encode('utf-8')
|
||||
size = len(mf)
|
||||
digest = dxf.hash_bytes(mf)
|
||||
|
||||
if ref is None:
|
||||
ref = digest
|
||||
|
||||
self.set_manifest(ref, mf, mime=mime)
|
||||
return size, digest
|
@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
|
||||
from docker_image import reference
|
||||
|
||||
from common import *
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Re-tag an existing multiarch plugin')
|
||||
parser.add_argument('image', help='existing image (registry/image:tag)')
|
||||
parser.add_argument('tag', help='new tag')
|
||||
parser.add_argument('-p', '--platforms', default='linux/amd64', help='buildx platforms')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
platforms = [Platform(p) for p in args.platforms.split(',')]
|
||||
|
||||
ref = reference.Reference.parse(args.image)
|
||||
hostname, repo = ref.split_hostname()
|
||||
without_tag = ref['name']
|
||||
|
||||
old_tag = ref['tag']
|
||||
new_tag = args.tag
|
||||
|
||||
reg = DXF(hostname, repo, auth=dxf_auth)
|
||||
|
||||
for p in platforms:
|
||||
mf = reg.get_manifest(p.tag(old_tag))
|
||||
|
||||
print(f'Re-tagging {without_tag}:{p.tag(old_tag)} as {without_tag}:{p.tag(new_tag)}')
|
||||
reg.set_manifest(p.tag(new_tag), mf, mime=MTYPE_MANIFEST)
|
||||
|
||||
print(f'Re-tagging {args.image} as {without_tag}:{new_tag}')
|
||||
mf = reg.get_manifest(old_tag)
|
||||
reg.set_manifest(new_tag, mf, mime=MTYPE_MANIFEST_LIST)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
Reference in New Issue