Skip to content

Commit d2b4c3b

Browse files
committed
sources/skopeo: support specifying format
Support specifying the format of the local archive (or directory) for the container. The default is kept as docker-archive for backwards compatibility. The 'dir' format will be used to retain signatures and manifests. The oci-archive is also added for completeness. It's the format that the oci-archive stage produces, so it could be useful to support pulling and storing this format in the future. The remove-signatures option is kept only for the docker-archive format. The final move (os.rename()) at the end of the fetch_one() method now creates the checksum directory if it doesn't exist and moves the child archive into it, adding to any existing archives that might exist in other formats. The archive name for the docker-archive format remains as container-image.tar for backwards compatibility, though this can change with minimal side effects. Dropped the .tar suffix from the symlink in the skopeo stage since it's not necessary and the target of the link might be a directory now.
1 parent 299995f commit d2b4c3b

File tree

2 files changed

+24
-14
lines changed

2 files changed

+24
-14
lines changed

sources/org.osbuild.skopeo

+23-13
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import sys
1212
import tempfile
1313

1414
from osbuild import sources
15-
from osbuild.util import ctx
15+
from osbuild.util import containers, ctx
1616

1717
SCHEMA = """
1818
"additionalProperties": false,
@@ -44,6 +44,12 @@ SCHEMA = """
4444
"tls-verify": {
4545
"type": "boolean",
4646
"description": "Require https (default true)."
47+
},
48+
"format": {
49+
"type": "string",
50+
"enum": ["docker-archive", "oci-archive", "dir"],
51+
"description": "The storage format to use when copying to the osbuild store",
52+
"default": "docker-archive"
4753
}
4854
}
4955
}
@@ -75,25 +81,27 @@ class SkopeoSource(sources.SourceService):
7581
digest = image["digest"]
7682
tls_verify = image.get("tls-verify", True)
7783

84+
# We use the docker format by default, not oci, because that is the default return image type of real world
85+
# registries, allowing the image to get the same image if as if you did "podman pull" (rather than converting
86+
# the image to oci format, changing the id).
87+
# However, the docker format doesn't have support for signatures and doesn't retain manifests.
88+
archive_format = image.get("format", "docker-archive")
89+
7890
with tempfile.TemporaryDirectory(prefix="tmp-download-", dir=self.cache) as tmpdir:
7991
archive_dir = os.path.join(tmpdir, "container-archive")
8092
os.makedirs(archive_dir)
8193
os.chmod(archive_dir, 0o755)
82-
archive_path = os.path.join(archive_dir, "container-image.tar")
8394

8495
source = f"docker://{imagename}@{digest}"
8596

86-
# We use the docker format, not oci, because that is the
87-
# default return image type of real world registries,
88-
# allowing the image to get the same image id as if you
89-
# did "podman pull" (rather than converting the image to
90-
# oci format, changing the id)
91-
destination = f"docker-archive:{archive_path}"
97+
archive_name = containers.archive_name(archive_format)
98+
destination = f"{archive_format}:{archive_dir}/{archive_name}"
9299

93100
extra_args = []
94101

95-
# The archive format can't store signatures, but we still verify them during download
96-
extra_args.append("--remove-signatures")
102+
if archive_format == "docker-archive":
103+
# The docker-archive format can't store signatures, but we still verify them during download
104+
extra_args.append("--remove-signatures")
97105

98106
if not tls_verify:
99107
extra_args.append("--src-tls-verify=false")
@@ -111,12 +119,14 @@ class SkopeoSource(sources.SourceService):
111119
raise RuntimeError(
112120
f"Downloaded image {imagename}@{digest} has a id of {downloaded_id}, but expected {image_id}")
113121

114-
# Atomically move download dir into place on successful download
122+
# Atomically move download archive into place on successful download
115123
with ctx.suppress_oserror(errno.ENOTEMPTY, errno.EEXIST):
116-
os.rename(archive_dir, f"{self.cache}/{image_id}")
124+
os.makedirs(f"{self.cache}/{image_id}", exist_ok=True)
125+
os.rename(f"{archive_dir}/{archive_name}", f"{self.cache}/{image_id}/{archive_name}")
117126

118127
def exists(self, checksum, desc):
119-
return os.path.isfile(f"{self.cache}/{checksum}/container-image.tar")
128+
archive_name = containers.archive_name(desc["image"].get("format", "docker-archive"))
129+
return os.path.exists(f"{self.cache}/{checksum}/{archive_name}")
120130

121131

122132
def main():

stages/org.osbuild.skopeo

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ def main(inputs, output, options):
8282
# treats them special, like e.g. /some/path:tag, so we make a symlink to the real name
8383
# and pass the symlink name to skopeo to make it work with anything
8484
with tempfile.TemporaryDirectory() as tmpdir:
85-
linkname = os.path.join(tmpdir, "image.tar")
85+
linkname = os.path.join(tmpdir, "image")
8686
os.symlink(source, linkname)
8787

8888
if container_format == "docker-archive":

0 commit comments

Comments
 (0)