Skip to content

Example API Interaction

Vanessa Sochat edited this page Jan 28, 2019 · 1 revision

Singularity Images

For this example, I've taken an (already built) container on Singularity Hub, meaning we have a binary in Google Storage, and I'm exploring a proof of concept of providing its metadata statically here. Here is a direct link to download a container.

While the md5 is not registered and thus a valid type, I'm using it just for this example. The hash of the container is a1025471b564766d08bdf2cb062c795c.

Step 1: Get the Manifest

For demonstration I'll present this in Python. First, we get the image manifest.

import requests

registry = "https://singularityhub.github.io/container-storage"
namespace = "vanessa/greeting"
tag = "latest"

manifest_url = "%s/%s/manifests/%s" %(registry, namespace, tag)
manifest = requests.get(manifest_url).json()

print(json.dumps(manifest, indent=4))
{
    "schemaVersion": 2,
    "mediaType": "application/vnd.singularity.distribution.manifest.v2+json",
    "config": {
        "mediaType": "application/vnd.singularity.container.image.v1+json",
        "size": 5539,
        "digest": "sha256:8c7ad11d488a8dd933239b9543a81dbe226416e96dc2f441d3bd038d664c1c92"
    },
    "layers": [
        {
            "mediaType": "application/vnd.singularity.image.squashfs",
            "size": 2065537,
            "digest": "md5:a1025471b564766d08bdf2cb062c795c",
            "urls": [
                "https://storage.googleapis.com/singularityhub/singularityhub/github.com/vsoch/singularity-images/130504089d5b2b44e2788992d0de75b625da6796/a1025471b564766d08bdf2cb062c795c/a1025471b564766d08bdf2cb062c795c.simg"
            ]
        }
    ]
}

Step 2: Download Image URLs

This ignores the config and content type for now, and just downloads the image url. I would want to assume that the client knows that given a singularity squashfs, the correct thing to do is download the single binary. Let's write a function to stream it to the filesystem:

def stream_file(url, download_to):
    response = requests.get(url, stream=True)
    with open(download_to, 'wb') as filey:
        for chunk in response.iter_content(chunk_size=1024): 
            if chunk: 
                filey.write(chunk)
    return download_to
layers = manifest['layers']

# {'digest': 'md5:a1025471b564766d08bdf2cb062c795c',
# 'mediaType': 'application/vnd.singularity.image.squashfs',
# 'size': 2065537,
# 'urls': ['https://storage.googleapis.com/singularityhub/singularityhub/github.com/vsoch/singularity-images/130504089d5b2b44e2788992d0de75b625da6796/a1025471b564766d08bdf2cb062c795c/a1025471b564766d08bdf2cb062c795c.simg']}

for layer in layers:
    url = layer['urls'][0]
    download_to = stream_file(url, 'mycontainer.simg')    

Step 3: Run the Container

Does it work?

$ singularity run mycontainer.simg
You say please, but all I see is pizza..

Yep!

Here is the md5sum:

$ md5sum mycontainer.simg
a1025471b564766d08bdf2cb062c795c  mycontainer.simg

There are a couple of things to discuss here:

  • The content type for Singularity I don't think exists. Can it exist and require a single binary (via a url) and then just be validated using a digest?
  • What goes in the config section then?
  • The storage needs to have an organizational standard. Given being stored in a Github repository, to me the logical answer is:
<github.com>/<username>/<reponame>/<commit>/<hash>/ [container]