Description
Currently, to commit an image in the image library's containers-storage
transport, we create and populate layers, create the image record, and then save the non-layers under the directory that matches that image record's ID. The manifest and config blobs are among those non-layers.
This creates a small window where there's an image record without a manifest and/or config blob, and if another thread tries to read information about the image during that window, it will get unexpected errors, and those errors percolating up the stack is a problem.
Option 1: add an incomplete
flag that we use for screening out values that we'd otherwise return in an Images()
list, and clean them up when we get a write lock, as we do for incomplete layers. Won't work because we don't keep the lock during the commit operation, so things can get cleaned up from under us during the window.
Option 2: screen out values from the Images()
list if they don't include a manifest. The commit logic doesn't need to be changed because it gets the ID when it creates the image record, and uses that ID to save the manifest for the image. Downsides: if we crash, the phantom image record could stay there forever, since it would be filtered for everyone who didn't know its ID. The screening would also need to check for a config blob, which requires knowledge that lives in containers/image (schema 1 images don't have them, and logic for determining what kind of manifest we have is in containers/image), which we can't use as a dependency.
Option 3: if we fail to read an image's manifest, spin and try again. Downside: hacky, and we can only guess how long we should spin before giving up and reporting an error.
Option 4: expose a way to manipulate Flags
in the image record, add a flag that containers/image will set on works in progress, and teach everyone to skip over images that have the flag set. Downside: kind of sucks for everyone.
Option 5: ???