-
Notifications
You must be signed in to change notification settings - Fork 395
ostree: support it as an image source and drop any usage of the ostree CLI tool #360
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ostree: support it as an image source and drop any usage of the ostree CLI tool #360
Conversation
7a7aeca to
c65fed6
Compare
ostree/ostree_src.go
Outdated
| return 0, err | ||
| } | ||
|
|
||
| size, err := strconv.ParseInt(string(out[1:len(out)-2]), 10, 64) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 1:len(out)-2 is pretty magic, and fragile. Could this be expressed in safer terms, perhaps splitting trailing '\n' and white space?
(Applies to all instances of that.)
(I guess this would go away with using the bindings directly.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes that would go away with the bindings. Anyway, I agree it is quite hard to follow so I've pushed a new version with this part cleaned up. The out string is the output of g_variant_print from OSTree plus a \n. With this code I drop the quotes around the JSON file plus the final \n.
In the new version, I use g_variant_parse so that we don't have to deal how it is quoted.
ostree/ostree_src.go
Outdated
| if err != nil { | ||
| return nil, "", err | ||
| } | ||
| m := []byte(strings.Replace(string(out[1:len(out)-2]), "\\n", "\n", -1)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the strings.Replace safe? This seems ambiguous. What if the manifest contains "ignoredKey": "Foo\nBar", will it be corrupted?
(Again, perhaps will go away with the golfing bindings.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is also fixed with g_variant_parse.
ostree/ostree_src.go
Outdated
| } | ||
|
|
||
| func (s *ostreeImageSource) GetTargetManifest(digest digest.Digest) ([]byte, string, error) { | ||
| return nil, imgspecv1.MediaTypeImageManifest, nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably fail with a readable error message instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Still outstanding.)
ostree/ostree_src.go
Outdated
|
|
||
| // GetBlob returns a stream for the specified blob, and the blob's size. | ||
| func (s *ostreeImageSource) GetBlob(info types.BlobInfo) (io.ReadCloser, int64, error) { | ||
| blob := strings.Replace(string(info.Digest), "sha256:", "", 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be info.Digest.Hex()? Or is any non-sha256 digest supposed to be preserved including the prefix?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, fixed now.
ostree/ostree_src.go
Outdated
| return nil, 0, err | ||
| } | ||
| return ioutils.NewReadCloserWrapper(stream, func() error { | ||
| return os.RemoveAll(dir) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All the error paths also need to remove dir.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(This would need less repetition with a defer func() {if !succeeded { os.RemoveAll(dir) } }() or so. This still works I guess.)
f3a5ff9 to
3d85d7e
Compare
|
I've dropped the WIP and addressed the comments |
ostree/ostree_dest.go
Outdated
| "github.com/pkg/errors" | ||
|
|
||
| "github.com/ostreedev/ostree-go/pkg/otbuiltin" | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Nit: Please keep the imports organized in two sections, imports from the default Golang library, and all external imports.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ping
ostree/ostree_src.go
Outdated
| cstring := C.CString(in) | ||
| defer C.free(unsafe.Pointer(cstring)) | ||
|
|
||
| ptr := (*C.char)(C.g_variant_get_string(C.g_variant_parse(nil, (*C.gchar)(cstring), nil, nil, nil), nil)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn’t g_variant_unref need to be called?
ostree/ostree_src.go
Outdated
| } | ||
|
|
||
| func (s *ostreeImageSource) GetTargetManifest(digest digest.Digest) ([]byte, string, error) { | ||
| return nil, imgspecv1.MediaTypeImageManifest, nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Still outstanding.)
ostree/ostree_src.go
Outdated
| return nil, 0, err | ||
| } | ||
| return ioutils.NewReadCloserWrapper(stream, func() error { | ||
| return os.RemoveAll(dir) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(This would need less repetition with a defer func() {if !succeeded { os.RemoveAll(dir) } }() or so. This still works I guess.)
mtrmac
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apart from a few nits, the attempt to re-create compressed blobs is very problematic. I’m sorry I haven’t noticed that earlier.
| go func() { | ||
| io.Copy(gzipWriter, ots) | ||
| gzipWriter.Close() | ||
| pipeWriter.Close() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hum, trying to re-create a compressed blob by re-creating the uncompressed tarstream and compressing it doesn’t work long-term and is not supportable. (We did try to do this earlier, for containers-storage, IIRC; it failed after a few months.) The gzip bitstream is not stable over Golang versions, meaning that this will not be able to reproduce the compressed blobs of images compressed by earlier Golang versions, and after any future Golang upgrade a previously working GetBlob can start returning different data; in either case the blob won’t match the digest recorded in the manifest.
For me, this inability to handle compressed data is by no means a blocker for this PR; containers-storage has the same problem, and that will need to be solved by editing the manifest. See #305 and the conversations in there.
What to do for now, though? I would be fine with this PR just skipping the compression step, meaning that the ostree: source produces usable images only for originally uncompressed images, and dealing with the compression as a follow-up.
That follow-up can probably be built around the tentative c/i/manifest subpackage being explored in #305.
Cc: @nalind
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is something that is biting us also when we import layers from the local Docker engine, as we compute the checksum using whatever gzip implementation is used by the golang version used to build https://github.com/projectatomic/atomic/blob/master/dockertar-sha256-helper.go. In anycase, we should probably use skopeo copy in atomic for accessing the local Docker engine.
|
|
||
| // newImageSource returns an ImageSource for reading from an existing directory. | ||
| func newImageSource(ctx *types.SystemContext, tmpDir string, ref ostreeReference) (types.ImageSource, error) { | ||
| return &ostreeImageSource{ref: ref, tmpDir: tmpDir}, nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Does the tmpDir need to be user-specifiable? In #228, OSTreeTmpDirPath was introduced to affect the SELinux labels of the committed files; here the directory is used only to temporarily store a tarball, which AFAICT does not need any particular SELinux label, as long as this process can read and write the file.
Non-blocking, this does work fine.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes true. As you say, the tmpDir used should not affect the result. Also, in the long term, I'd like that the golang bindings offer some nice ways to browse/request files from the ostree repository without extracting them to a temporary directory first
2f78255 to
23e6ccd
Compare
86c852f to
37e6869
Compare
|
@mtrmac I've just rebased the PR |
8e15431 to
3db3651
Compare
6e3e7ab to
86aa36f
Compare
a40100e to
e7b1b04
Compare
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
Use the tar-split information to recreate the original tarball. It is not the ideal implementation yet, we will need to implement more stuff in the OSTree golang bindings before we can improve it. Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
1796a08 to
afa60a0
Compare
|
@mtrmac thanks for the detailed review. I've addressed the comments in the version here ⬆️ |
mtrmac
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please drop the gzipWriter and return the output of tar-split unmodified.
The GError memory handling, while now consistent, seems to be designed to be used differently.
ostree/ostree_src.go
Outdated
| } | ||
|
|
||
| func (o ostreePathFileGetter) Close() { | ||
| C.g_object_ref(C.gpointer(o.repo)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be g_object_unref
| } | ||
|
|
||
| // newImageSource returns an ImageSource for reading from an existing directory. | ||
| func newImageSource(ctx *types.SystemContext, tmpDir string, ref ostreeReference) (types.ImageSource, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(ctx is not used and could be dropped. Non-blocking.)
|
@mtrmac if I simply drop the is there anything more to do to get it working with the output from |
It “in principle” does not match with the
The work in #305 should make this possible one way or another; until then, I’d prefer not even trying here (but @runcom can persuade me otherwise). |
|
can this be changed once #305 is merged? It is really unfortunate that the checksum is calculated on the compressed file, we are already using this assumption in |
|
It doesn’t work. Whatever you are building that relies on this recompression doesn’t work reliably (and after #305 happens still will neither return compressed data nor return the original checksum). |
|
it doesn't depend on the compressed data, as long as we will be able to provide a modified manifest file that will match the uncompressed data. |
afa60a0 to
5363311
Compare
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
It could be missing in the manifest Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
Take rid of any usage of the OSTree CLI tool and use directly the ostree C library. Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
system containers used to support this format. Let's include it, since the required changes are minimal. Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
the previous implementation relied on the golang gzip implementation to generate always the same stream and thus checksum. Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
b8b40e1 to
c809f3d
Compare
|
I've added another patch to handle only uncompressed layers for now. When #305 will be merged, then I'll work on supporting compressed layers as well. |
well, #305 is needed by CRI-O as well, so it won't be that long till we merge that hopefully. That PR is actually fixing 2 bugs in CRI-O, meanwhile, I don't have any issue with this PR as long as when #305 is merged, this is reworked to take into account what's missing. @mtrmac sounds good? |
|
@mtrmac are you still fine if I drop the "ostree: support only uncompressed images for now" patch or is it necessary to get this PR approved? |
|
I’d still prefer the compression not to be included; I can’t see that making an incorrect impression that this works is valuable at all, and the post-#305 work will not benefit from the compression either. But, *shrug* if @runcom is fine with having that in, I won’t block on that. However you decide, please let me know when this is ready for merging. |
|
ok then, let's merge without the support for compressed images for now. I will take another look if and how it can be supported after #305 is merged. Thanks again for the reviews |
|
do I need to re-vendor Skopeo or is it going to happen anyway before a new release? |
|
It is very likely to happen, but we don’t have a process that absolutely guarantees it. If you want to be sure and submit a skopeo PR (just run |
No description provided.