Update to ostree-ext v0.1.2, add new ex-container
command
This new `rpm-ostree ex-container` CLI is just code copied from the `ostree-ext-cli container` binary code. In the future I may just add the CLI code as a library API too to simplify this. For now, I don't want to try to add a new Rust CLI as an RPM package for example. This exposes it via rpm-ostree, and in the future rpm-ostree may have some layering on top of this anyways.
This commit is contained in:
parent
38c25bfb75
commit
54a011df40
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -1532,6 +1532,7 @@ dependencies = [
|
|||||||
"env_logger",
|
"env_logger",
|
||||||
"envsubst",
|
"envsubst",
|
||||||
"fn-error-context",
|
"fn-error-context",
|
||||||
|
"futures",
|
||||||
"gio",
|
"gio",
|
||||||
"gio-sys",
|
"gio-sys",
|
||||||
"glib",
|
"glib",
|
||||||
@ -1566,6 +1567,7 @@ dependencies = [
|
|||||||
"system-deps 3.1.1",
|
"system-deps 3.1.1",
|
||||||
"systemd",
|
"systemd",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
]
|
]
|
||||||
|
@ -35,6 +35,7 @@ cxx = "1.0.49"
|
|||||||
envsubst = "0.2.0"
|
envsubst = "0.2.0"
|
||||||
env_logger = "0.8.3"
|
env_logger = "0.8.3"
|
||||||
fn-error-context = "0.1.2"
|
fn-error-context = "0.1.2"
|
||||||
|
futures = "0.3.15"
|
||||||
gio = "0.9.1"
|
gio = "0.9.1"
|
||||||
gio-sys = "0.10.1"
|
gio-sys = "0.10.1"
|
||||||
gobject-sys = "0.10.0"
|
gobject-sys = "0.10.0"
|
||||||
@ -70,6 +71,7 @@ systemd = "0.8.2"
|
|||||||
tempfile = "3.2.0"
|
tempfile = "3.2.0"
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
tracing-subscriber = "0.2"
|
tracing-subscriber = "0.2"
|
||||||
|
tokio = { version = "1.6.0", features = ["full"] }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
|
104
rust/src/container.rs
Normal file
104
rust/src/container.rs
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
//! CLI exposing `ostree-rs-ext container`
|
||||||
|
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
|
||||||
|
use std::convert::TryInto;
|
||||||
|
|
||||||
|
use anyhow::{Context, Result};
|
||||||
|
use structopt::StructOpt;
|
||||||
|
|
||||||
|
#[derive(Debug, StructOpt)]
|
||||||
|
enum Opts {
|
||||||
|
/// Import an ostree commit embedded in a remote container image
|
||||||
|
Import {
|
||||||
|
/// Path to the repository
|
||||||
|
#[structopt(long)]
|
||||||
|
repo: String,
|
||||||
|
|
||||||
|
/// Image reference, e.g. registry:quay.io/exampleos/exampleos:latest
|
||||||
|
imgref: String,
|
||||||
|
},
|
||||||
|
|
||||||
|
/// Print information about an exported ostree-container image.
|
||||||
|
Info {
|
||||||
|
/// Image reference, e.g. registry:quay.io/exampleos/exampleos:latest
|
||||||
|
imgref: String,
|
||||||
|
},
|
||||||
|
|
||||||
|
/// Export an ostree commit to an OCI layout
|
||||||
|
Export {
|
||||||
|
/// Path to the repository
|
||||||
|
#[structopt(long)]
|
||||||
|
repo: String,
|
||||||
|
|
||||||
|
/// The ostree ref or commit to export
|
||||||
|
rev: String,
|
||||||
|
|
||||||
|
/// Image reference, e.g. registry:quay.io/exampleos/exampleos:latest
|
||||||
|
imgref: String,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn container_import(repo: &str, imgref: &str) -> Result<()> {
|
||||||
|
let repo = &ostree::Repo::open_at(libc::AT_FDCWD, repo, gio::NONE_CANCELLABLE)?;
|
||||||
|
let imgref = imgref.try_into()?;
|
||||||
|
let (tx_progress, rx_progress) = tokio::sync::watch::channel(Default::default());
|
||||||
|
let target = indicatif::ProgressDrawTarget::stdout();
|
||||||
|
let style = indicatif::ProgressStyle::default_bar();
|
||||||
|
let pb = indicatif::ProgressBar::new_spinner();
|
||||||
|
pb.set_draw_target(target);
|
||||||
|
pb.set_style(style.template("{spinner} {prefix} {msg}"));
|
||||||
|
pb.enable_steady_tick(200);
|
||||||
|
pb.set_message("Downloading...");
|
||||||
|
let import = ostree_ext::container::import(repo, &imgref, Some(tx_progress));
|
||||||
|
tokio::pin!(import);
|
||||||
|
tokio::pin!(rx_progress);
|
||||||
|
loop {
|
||||||
|
tokio::select! {
|
||||||
|
_ = rx_progress.changed() => {
|
||||||
|
let n = rx_progress.borrow().processed_bytes;
|
||||||
|
pb.set_message(&format!("Processed: {}", indicatif::HumanBytes(n)));
|
||||||
|
}
|
||||||
|
import = &mut import => {
|
||||||
|
pb.finish();
|
||||||
|
println!("Imported: {}", import?.ostree_commit);
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn container_export(repo: &str, rev: &str, imgref: &str) -> Result<()> {
|
||||||
|
let repo = &ostree::Repo::open_at(libc::AT_FDCWD, repo, gio::NONE_CANCELLABLE)?;
|
||||||
|
let imgref = imgref.try_into()?;
|
||||||
|
let pushed = ostree_ext::container::export(repo, rev, &imgref).await?;
|
||||||
|
println!("{}", pushed);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn container_info(imgref: &str) -> Result<()> {
|
||||||
|
let imgref = imgref.try_into()?;
|
||||||
|
let info = ostree_ext::container::fetch_manifest_info(&imgref).await?;
|
||||||
|
println!("{} @{}", imgref, info.manifest_digest);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Main entrypoint for container
|
||||||
|
pub fn entrypoint(args: &[&str]) -> Result<()> {
|
||||||
|
tokio::runtime::Builder::new_multi_thread()
|
||||||
|
.enable_all()
|
||||||
|
.build()
|
||||||
|
.context("Failed to build tokio runtime")?
|
||||||
|
.block_on(async {
|
||||||
|
match Opts::from_iter(args.iter().skip(1)) {
|
||||||
|
Opts::Import { repo, imgref } => {
|
||||||
|
container_import(repo.as_str(), imgref.as_str()).await
|
||||||
|
}
|
||||||
|
Opts::Info { imgref } => container_info(imgref.as_str()).await,
|
||||||
|
Opts::Export { repo, rev, imgref } => {
|
||||||
|
container_export(repo.as_str(), rev.as_str(), imgref.as_str()).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
Ok(())
|
||||||
|
}
|
@ -519,6 +519,7 @@ pub(crate) use bwrap::*;
|
|||||||
mod client;
|
mod client;
|
||||||
pub(crate) use client::*;
|
pub(crate) use client::*;
|
||||||
mod cliwrap;
|
mod cliwrap;
|
||||||
|
pub mod container;
|
||||||
pub use cliwrap::*;
|
pub use cliwrap::*;
|
||||||
mod composepost;
|
mod composepost;
|
||||||
pub mod countme;
|
pub mod countme;
|
||||||
|
@ -7,6 +7,7 @@ fn inner_main(args: &Vec<&str>) -> Result<()> {
|
|||||||
match args.get(1).map(|s| *s) {
|
match args.get(1).map(|s| *s) {
|
||||||
// Add custom Rust commands here, and also in `libmain.cxx` if user-visible.
|
// Add custom Rust commands here, and also in `libmain.cxx` if user-visible.
|
||||||
Some("countme") => rpmostree_rust::countme::entrypoint(args),
|
Some("countme") => rpmostree_rust::countme::entrypoint(args),
|
||||||
|
Some("ex-container") => rpmostree_rust::container::entrypoint(args),
|
||||||
_ => {
|
_ => {
|
||||||
// Otherwise fall through to C++ main().
|
// Otherwise fall through to C++ main().
|
||||||
Ok(rpmostree_rust::ffi::rpmostree_main(&args)?)
|
Ok(rpmostree_rust::ffi::rpmostree_main(&args)?)
|
||||||
|
37
tests/kolainst/destructive/ex-container
Executable file
37
tests/kolainst/destructive/ex-container
Executable file
@ -0,0 +1,37 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Copyright (C) 2021 Red Hat Inc.
|
||||||
|
#
|
||||||
|
# This library is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU Lesser General Public
|
||||||
|
# License as published by the Free Software Foundation; either
|
||||||
|
# version 2 of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This library is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# Lesser General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser General Public
|
||||||
|
# License along with this library; if not, write to the
|
||||||
|
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
# Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
. ${KOLA_EXT_DATA}/libtest.sh
|
||||||
|
|
||||||
|
set -x
|
||||||
|
|
||||||
|
libtest_prepare_offline
|
||||||
|
|
||||||
|
booted_commit=$(rpm-ostree status --json | jq -r '.deployments[0].checksum')
|
||||||
|
rpm-ostree ex-container export --repo=/ostree/repo ${booted_commit} containers-storage:localhost/fcos
|
||||||
|
target_sha256=$(podman run --entrypoint bash --rm -i localhost/fcos -c 'sha256sum /usr/bin/rpm-ostree' | cut -f 1 -d ' ')
|
||||||
|
src_sha256=$(sha256sum /usr/bin/rpm-ostree | cut -f 1 -d ' ')
|
||||||
|
assert_streq "${src_sha256}" "${target_sha256}"
|
||||||
|
echo "ok container export"
|
||||||
|
|
||||||
|
# TODO test container import too, ideally via registry. But I don't want to
|
||||||
|
# make this test super flaky right now by pulling from the internet, and
|
||||||
|
# we need infrastructure to mock up serving via local registry.
|
Loading…
Reference in New Issue
Block a user