Skip to content
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

WIP: Use skopeo to fetch images #15

Closed
wants to merge 1 commit into from
Closed

WIP: Use skopeo to fetch images #15

wants to merge 1 commit into from

Conversation

cgwalters
Copy link
Member

The goal here is to implement: #6

We want to honor things like mirroring set up in /etc/containers.

However, after doing all this work I hit on two things:

  • containers/image barfs if the destination is a pipe
  • And actually even if we ask to copy into an oci-archive it still
    spools everything to a temporary directory and then tars it
    back up, entirely obviating the point of streaming.

The goal here is to implement: #6

We want to honor things like mirroring set up in `/etc/containers`.

However, after doing all this work I hit on two things:

- containers/image barfs if the destination is a pipe
- And actually even if we ask to copy into an `oci-archive` it still
  spools everything to a temporary directory and then tars it
  back up, entirely obviating the point of streaming.
@cgwalters
Copy link
Member Author

For me also this was a huge deep dive into async Rust. I would say I'm intermediate at Rust but I'd only dabbled in async.

In particular the parse_tar function is "bridging" the world of async rust to sync because I wanted to keep using the existing sync tar crate. So I spent a lot of time trying to figure out how to take an AsyncRead and turn that into a plain Read usable in a worker thread.

Then further, I wanted to stream output too, so I ended up using tokio's mpsc channels which are documented to be usable both sync and async. But even this took me a bit to figure out from searching through the tokio docs. Web searches for "async sync bridge read" and the like aren't helpful - the terms are too generic.

Further complicating things I wanted to return an impl Stream<Item=Result<TarEntry>> but we also need to poll the future for the helpers. I tried making my own struct for this but implementing poll_next() was a whole other level of learning - particularly around pinning the inner futures, etc. I ended up just returning two futures.

In addition to this I also spent a lot of time on inscrutable compiler errors that result when e.g. you forget to include TryStreamExt or you forget to wrap the result in a future in a helper closure, etc. Also some lifetime issues that I am still not sure I quite understand (e.g. my use of the Rc<String>), and I ended up tossing in various .boxed_local() for lifetime issues on some of the futures.

Now of course there is https://crates.io/crates/tokio-tar but in a very Rust thing, there's an open PR to port to tokio 1.0 that hasn't merged because it's probably just someone's side project or something.

And....after doing all that I very belatedly realized that skopeo doesn't actually stream the results at all 😢 - so all this work on parsing the tar stream is pointless, I could have just forked skopeo to write to a tempdir, and then parse that.

Ultimately I think we need a more direct containers/image backend to make this truly work well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant