Add basic Rust CLI bindings for DBus
This stubs out sufficient infrastructure for us to register as a client and call the Moo API. A glaring problem here is the lack of extensive `glib::Variant` bindings; that's covered in the next gtk-rs release. My real goal was to try porting the `rpmostree-builtin-apply-live.cxx` code entirely to Rust, but there's more to do to expose the transaction helper APIs we have.
This commit is contained in:
parent
283824c6cb
commit
6fd9db246a
@ -95,8 +95,8 @@ macro_rules! cxxrs_bind {
|
||||
// When extending this list, also update rpmostree-cxxrs-prelude.h and lib.rs
|
||||
// This macro is special to ostree types currently.
|
||||
cxxrs_bind!(Ostree, ostree, ostree_sys, [Sysroot, Repo, Deployment]);
|
||||
cxxrs_bind!(G, gio, gio_sys, [Cancellable]);
|
||||
cxxrs_bind!(G, glib, gobject_sys, [Object]);
|
||||
cxxrs_bind!(G, gio, gio_sys, [Cancellable, DBusConnection]);
|
||||
cxxrs_bind!(G, glib, glib_sys, [VariantDict]);
|
||||
|
||||
// An error type helper; separate from the GObject bridging
|
||||
|
@ -37,6 +37,7 @@ pub mod ffi {
|
||||
type OstreeDeployment = crate::FFIOstreeDeployment;
|
||||
type GObject = crate::FFIGObject;
|
||||
type GCancellable = crate::FFIGCancellable;
|
||||
type GDBusConnection = crate::FFIGDBusConnection;
|
||||
type GVariantDict = crate::FFIGVariantDict;
|
||||
|
||||
#[namespace = "dnfcxx"]
|
||||
@ -295,6 +296,14 @@ pub mod ffi {
|
||||
fn main_print_error(msg: &str);
|
||||
}
|
||||
|
||||
unsafe extern "C++" {
|
||||
include!("rpmostree-clientlib.h");
|
||||
fn client_require_root() -> Result<()>;
|
||||
type ClientConnection;
|
||||
fn new_client_connection() -> Result<UniquePtr<ClientConnection>>;
|
||||
fn get_connection<'a>(self: Pin<&'a mut ClientConnection>) -> Pin<&'a mut GDBusConnection>;
|
||||
}
|
||||
|
||||
unsafe extern "C++" {
|
||||
include!("rpmostree-diff.hpp");
|
||||
type RPMDiff;
|
||||
|
@ -47,6 +47,8 @@ enum Opt {
|
||||
GenerateSyntheticUpgrade(SyntheticUpgradeOpts),
|
||||
/// Validate that we can parse the output of `rpm-ostree status --json`.
|
||||
ValidateParseStatus,
|
||||
/// Test that we can 🐄
|
||||
Moo,
|
||||
}
|
||||
|
||||
/// Returns `true` if a file is ELF; see https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
|
||||
@ -226,11 +228,54 @@ fn validate_parse_status() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn test_moo() -> Result<()> {
|
||||
use glib::translate::*;
|
||||
|
||||
crate::ffi::client_require_root()?;
|
||||
|
||||
let mut client_conn = crate::ffi::new_client_connection()?;
|
||||
let mut bus_conn = client_conn.pin_mut().get_connection();
|
||||
let bus_conn = bus_conn.gobj_wrap();
|
||||
|
||||
// Unfortunately glib bindings don't support tuples, we need
|
||||
// `(b)` i.e. the 1-tuple with a boolean, and not just `b`.
|
||||
let params = unsafe {
|
||||
let truev = glib_sys::g_variant_new_boolean(true.to_glib());
|
||||
let r = glib_sys::g_variant_new_tuple(&truev as *const *mut _, 1);
|
||||
glib_sys::g_variant_ref_sink(r);
|
||||
from_glib_full(r)
|
||||
};
|
||||
let reply = bus_conn.call_sync(
|
||||
Some("org.projectatomic.rpmostree1"),
|
||||
"/org/projectatomic/rpmostree1/fedora_coreos",
|
||||
"org.projectatomic.rpmostree1.OSExperimental",
|
||||
"Moo",
|
||||
Some(¶ms),
|
||||
Some(glib::VariantTy::new("(s)").unwrap()),
|
||||
gio::DBusCallFlags::NONE,
|
||||
-1,
|
||||
gio::NONE_CANCELLABLE,
|
||||
)?;
|
||||
let reply_child: glib::Variant = unsafe {
|
||||
from_glib_full(glib_sys::g_variant_get_child_value(
|
||||
reply.to_glib_none().0,
|
||||
0,
|
||||
))
|
||||
};
|
||||
// Unwrap safety: We validated the (s) above.
|
||||
let reply = reply_child.get_str().unwrap();
|
||||
let cow = "🐄\n";
|
||||
assert_eq!(reply, cow);
|
||||
println!("ok {}", cow.trim());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn testutils_entrypoint(args: Vec<String>) -> CxxResult<()> {
|
||||
let opt = Opt::from_iter(args.iter());
|
||||
match opt {
|
||||
Opt::GenerateSyntheticUpgrade(ref opts) => update_os_tree(opts)?,
|
||||
Opt::ValidateParseStatus => validate_parse_status()?,
|
||||
Opt::Moo => test_moo()?,
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
@ -192,6 +192,17 @@ option_context_new_with_commands (RpmOstreeCommandInvocation *invocation,
|
||||
return util::move_nullify (context);
|
||||
}
|
||||
|
||||
namespace rpmostreecxx {
|
||||
|
||||
void
|
||||
client_require_root(void)
|
||||
{
|
||||
if (getuid () != 0 && getenv ("RPMOSTREE_SUPPRESS_REQUIRES_ROOT_CHECK") == NULL)
|
||||
throw std::runtime_error("This command requires root privileges");
|
||||
}
|
||||
|
||||
} /* namespace */
|
||||
|
||||
gboolean
|
||||
rpmostree_option_context_parse (GOptionContext *context,
|
||||
const GOptionEntry *main_entries,
|
||||
@ -256,10 +267,8 @@ rpmostree_option_context_parse (GOptionContext *context,
|
||||
exit (EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
if ((flags & RPM_OSTREE_BUILTIN_FLAG_REQUIRES_ROOT) > 0
|
||||
&& getuid () != 0
|
||||
&& getenv ("RPMOSTREE_SUPPRESS_REQUIRES_ROOT_CHECK") == NULL)
|
||||
return glnx_throw (error, "This command requires root privileges");
|
||||
if ((flags & RPM_OSTREE_BUILTIN_FLAG_REQUIRES_ROOT) > 0)
|
||||
rpmostreecxx::client_require_root();
|
||||
|
||||
if (use_daemon)
|
||||
{
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "ostree.h"
|
||||
#include "rpmostree-builtin-types.h"
|
||||
#include "rpmostree-clientlib.h"
|
||||
#include "rpmostree-cxxrs.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
@ -240,6 +240,22 @@ app_load_sysroot_impl (const char *sysroot, gboolean force_peer,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
namespace rpmostreecxx {
|
||||
|
||||
std::unique_ptr<ClientConnection>
|
||||
new_client_connection()
|
||||
{
|
||||
g_autoptr(GError) local_error = NULL;
|
||||
GDBusConnection *conn = NULL;
|
||||
GBusType bus_type;
|
||||
|
||||
if (!app_load_sysroot_impl(NULL, false, NULL, &conn, &bus_type, &local_error))
|
||||
util::throw_gerror(local_error);
|
||||
return std::make_unique<ClientConnection>(conn, bus_type);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
/**
|
||||
* rpmostree_load_sysroot
|
||||
* @sysroot: sysroot path
|
||||
|
@ -29,6 +29,35 @@
|
||||
#include <string.h>
|
||||
#include <ostree.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace rpmostreecxx {
|
||||
|
||||
class ClientConnection final {
|
||||
private:
|
||||
GDBusConnection *conn;
|
||||
GBusType bus_type;
|
||||
public:
|
||||
ClientConnection(GDBusConnection *connp, GBusType bus_typep) : conn(connp), bus_type(bus_typep) {}
|
||||
~ClientConnection() {
|
||||
g_clear_object(&conn);
|
||||
}
|
||||
|
||||
GDBusConnection &get_connection() {
|
||||
return *conn;
|
||||
}
|
||||
|
||||
GBusType get_bus_type() const {
|
||||
return bus_type;
|
||||
}
|
||||
};
|
||||
|
||||
void client_require_root();
|
||||
|
||||
std::unique_ptr<ClientConnection> new_client_connection();
|
||||
|
||||
} // namespace
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define BUS_NAME "org.projectatomic.rpmostree1"
|
||||
|
@ -28,8 +28,9 @@ namespace rpmostreecxx {
|
||||
typedef ::OstreeSysroot OstreeSysroot;
|
||||
typedef ::OstreeRepo OstreeRepo;
|
||||
typedef ::OstreeDeployment OstreeDeployment;
|
||||
typedef ::GCancellable GCancellable;
|
||||
typedef ::GObject GObject;
|
||||
typedef ::GCancellable GCancellable;
|
||||
typedef ::GDBusConnection GDBusConnection;
|
||||
typedef ::GVariantDict GVariantDict;
|
||||
}
|
||||
|
||||
|
@ -60,17 +60,8 @@ fi
|
||||
assert_file_has_content err.txt 'Unknown.*command'
|
||||
echo "ok error on unknown command"
|
||||
|
||||
stateroot=$(dirname $(ls /ostree/deploy/*/var))
|
||||
ospath=/org/projectatomic/rpmostree1/${stateroot//-/_}
|
||||
# related: https://github.com/coreos/fedora-coreos-config/issues/194
|
||||
(export LANG=C.utf8
|
||||
# And for some reason this one is set in kola runs but not interactive shells
|
||||
unset LC_ALL
|
||||
gdbus call \
|
||||
--system --dest org.projectatomic.rpmostree1 \
|
||||
--object-path /org/projectatomic/rpmostree1/fedora_coreos \
|
||||
--method org.projectatomic.rpmostree1.OSExperimental.Moo true > moo.txt
|
||||
assert_file_has_content moo.txt '🐄')
|
||||
rpm-ostree testutils moo
|
||||
echo "ok moo"
|
||||
|
||||
# Reload as root https://github.com/projectatomic/rpm-ostree/issues/976
|
||||
|
Loading…
Reference in New Issue
Block a user