Skip to content

Commit

Permalink
Merge pull request #6105 from habitat-sh/jb/launcher-prost
Browse files Browse the repository at this point in the history
Convert all of the launcher crates to use prost.
  • Loading branch information
raskchanky authored Feb 6, 2019
2 parents 42f641b + a8b1d75 commit f15f152
Show file tree
Hide file tree
Showing 31 changed files with 671 additions and 2,922 deletions.
10 changes: 6 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ $(foreach component,$(ALL),$(eval $(call BUILD,$(component))))

define UNIT
unit-$1: image ## executes the $1 component's unit test suite
$(run) sh -c 'cd components/$1 && TESTING_FS_ROOT=$(TESTING_FS_ROOT) cargo test $(CARGO_FLAGS)'
$(run) sh -c 'cd components/$1 && TESTING_FS_ROOT=$(TESTING_FS_ROOT) cargo test $(CARGO_FLAGS) -- --test-threads=1'
.PHONY: unit-$1
endef
$(foreach component,$(ALL),$(eval $(call UNIT,$(component))))
Expand All @@ -203,8 +203,7 @@ UNEXAMINED_LINTS = clippy::cyclomatic_complexity \
clippy::redundant_field_names \
clippy::too_many_arguments \
clippy::trivially_copy_pass_by_ref \
clippy::wrong_self_convention \
renamed_and_removed_lints
clippy::wrong_self_convention

# Lints we disagree with and choose to keep in our code with no warning
ALLOWED_LINTS =
Expand Down Expand Up @@ -260,7 +259,8 @@ DENIED_LINTS = clippy::assign_op_pattern \
clippy::useless_format \
clippy::useless_let_if_seq \
clippy::useless_vec \
clippy::write_with_newline
clippy::write_with_newline \
renamed_and_removed_lints

lint: image ## executes the $1 component's linter checks
$(run) cargo clippy --all-targets --tests $(CARGO_FLAGS) -- \
Expand Down
3 changes: 2 additions & 1 deletion components/launcher-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ name = "habitat-launcher-client"
version = "0.0.0"
edition = "2018"
authors = ["Jamie Winsor <reset@habitat.sh>"]
workspace = "../../"

[dependencies]
bincode = "*"
Expand All @@ -12,5 +13,5 @@ habitat-launcher-protocol = { path = "../launcher-protocol" }
ipc-channel = { git = "https://github.com/habitat-sh/ipc-channel", branch = "hbt-windows" }
libc = "*"
log = "*"
protobuf = "1.5.1"
prost = "*"
serde = "*"
87 changes: 34 additions & 53 deletions components/launcher-client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::HashMap;
use std::fs;
use std::io;
use std::path::Path;

use crate::core::os::process::Pid;
use crate::protocol;
use ipc_channel::ipc::{IpcOneShotServer, IpcReceiver, IpcSender};
use protobuf;

use crate::error::{Error, Result};
use habitat_core::os::process::Pid;
use habitat_launcher_protocol::{self as protocol, Error as ProtocolError};
use ipc_channel::ipc::{IpcOneShotServer, IpcReceiver, IpcSender};
use std::{collections::HashMap, fs, io, path::Path};

type Env = HashMap<String, String>;
type IpcServer = IpcOneShotServer<Vec<u8>>;
Expand All @@ -49,38 +43,37 @@ impl LauncherCli {
let tx = IpcSender::connect(pipe_to_launcher).map_err(Error::Connect)?;
let (ipc_srv, pipe_to_sup) = IpcServer::new().map_err(Error::BadPipe)?;
debug!("IpcServer::new() returned pipe_to_sup: {}", pipe_to_sup);
let mut cmd = protocol::Register::new();
cmd.set_pipe(pipe_to_sup);
let cmd = protocol::Register {
pipe: pipe_to_sup.clone(),
};
Self::send(&tx, &cmd)?;
let (rx, raw) = ipc_srv.accept().map_err(|_| Error::AcceptConn)?;
Self::read::<protocol::NetOk>(&raw)?;
Ok(LauncherCli {
tx: tx,
rx: rx,
pipe: cmd.take_pipe(),
pipe: pipe_to_sup,
})
}

/// Read a launcher protocol message from a byte array
fn read<T>(bytes: &[u8]) -> Result<T>
where
T: protobuf::MessageStatic,
T: protocol::LauncherMessage,
{
let txn = protocol::NetTxn::from_bytes(bytes).map_err(Error::Deserialize)?;
let txn = protocol::NetTxn::from_bytes(bytes)?;
if txn.message_id() == "NetErr" {
let err = txn
.decode::<protocol::NetErr>()
.map_err(Error::Deserialize)?;
return Err(Error::Protocol(err));
let err = txn.decode::<protocol::NetErr>()?;
return Err(Error::Protocol(ProtocolError::NetErr(err)));
}
let msg = txn.decode::<T>().map_err(Error::Deserialize)?;
let msg = txn.decode::<T>()?;
Ok(msg)
}

/// Receive and read protocol message from an IpcReceiver
fn recv<T>(rx: &IpcReceiver<Vec<u8>>) -> Result<T>
where
T: protobuf::MessageStatic,
T: protocol::LauncherMessage,
{
match rx.recv() {
Ok(bytes) => Self::read(&bytes),
Expand All @@ -91,18 +84,18 @@ impl LauncherCli {
/// Send a command to a Launcher
fn send<T>(tx: &IpcSender<Vec<u8>>, message: &T) -> Result<()>
where
T: protobuf::MessageStatic,
T: protocol::LauncherMessage,
{
let txn = protocol::NetTxn::build(message).map_err(Error::Serialize)?;
let bytes = txn.to_bytes().map_err(Error::Serialize)?;
let txn = protocol::NetTxn::build(message)?;
let bytes = txn.to_bytes()?;
tx.send(bytes).map_err(Error::Send)?;
Ok(())
}

/// Receive and read protocol message from an IpcReceiver
fn try_recv<T>(rx: &IpcReceiver<Vec<u8>>) -> Result<Option<T>>
where
T: protobuf::MessageStatic,
T: protocol::LauncherMessage,
{
match rx.try_recv().map_err(|err| Error::from(*err)) {
Ok(bytes) => {
Expand All @@ -124,11 +117,10 @@ impl LauncherCli {

/// Restart a running process with the same arguments
pub fn restart(&self, pid: Pid) -> Result<Pid> {
let mut msg = protocol::Restart::new();
msg.set_pid(pid.into());
let msg = protocol::Restart { pid: pid.into() };
Self::send(&self.tx, &msg)?;
let reply = Self::recv::<protocol::SpawnOk>(&self.rx)?;
Ok(reply.get_pid() as Pid)
Ok(reply.pid as Pid)
}

/// Send a process spawn command to the connected Launcher
Expand All @@ -154,44 +146,33 @@ impl LauncherCli {
G: ToString,
P: ToString,
{
let mut msg = protocol::Spawn::new();
msg.set_binary(bin.as_ref().to_path_buf().to_string_lossy().into_owned());

// On Windows, we only expect user to be Some.
//
// On Linux, we expect user_id and group_id to be Some, while
// user and group may be either Some or None. Only the IDs are
// used; names are only for backward compatibility with older
// Launchers.
if let Some(name) = user {
msg.set_svc_user(name.to_string());
}
if let Some(name) = group {
msg.set_svc_group(name.to_string());
}
if let Some(uid) = user_id {
msg.set_svc_user_id(uid);
}
if let Some(gid) = group_id {
msg.set_svc_group_id(gid);
}
let msg = protocol::Spawn {
binary: bin.as_ref().to_path_buf().to_string_lossy().into_owned(),
svc_user: user.map(|u| u.to_string()),
svc_group: group.map(|g| g.to_string()),
svc_user_id: user_id,
svc_group_id: group_id,
svc_password: password.map(|p| p.to_string()),
env: env,
id: id.to_string(),
..Default::default()
};

// This is only for Windows
if let Some(password) = password {
msg.set_svc_password(password.to_string());
}
msg.set_env(env);
msg.set_id(id.to_string());
Self::send(&self.tx, &msg)?;
let reply = Self::recv::<protocol::SpawnOk>(&self.rx)?;
Ok(reply.get_pid() as Pid)
Ok(reply.pid as Pid)
}

pub fn terminate(&self, pid: Pid) -> Result<i32> {
let mut msg = protocol::Terminate::new();
msg.set_pid(pid.into());
let msg = protocol::Terminate { pid: pid.into() };
Self::send(&self.tx, &msg)?;
let reply = Self::recv::<protocol::TerminateOk>(&self.rx)?;
Ok(reply.get_exit_code())
Ok(reply.exit_code)
}
}
25 changes: 9 additions & 16 deletions components/launcher-client/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,19 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use std::error;
use std::fmt;
use std::io;
use std::result;

use crate::protocol;
use habitat_launcher_protocol as protocol;
use ipc_channel;
use protobuf;
use std::{error, fmt, io, result};

#[derive(Debug)]
pub enum Error {
AcceptConn,
BadPipe(io::Error),
Connect(io::Error),
Deserialize(protobuf::ProtobufError),
IPCBincode(String),
IPCIO(io::ErrorKind),
Protocol(protocol::NetErr),
Protocol(protocol::Error),
Send(ipc_channel::Error),
Serialize(protobuf::ProtobufError),
}

pub type Result<T> = result::Result<T, Error>;
Expand All @@ -42,16 +35,12 @@ impl fmt::Display for Error {
Error::AcceptConn => "Unable to accept connection from Launcher".to_string(),
Error::BadPipe(ref e) => format!("Unable to open pipe to Launcher, {}", e),
Error::Connect(ref e) => format!("Unable to connect to Launcher's pipe, {}", e),
Error::Deserialize(ref e) => {
format!("Unable to deserialize message from Launcher, {}", e)
}
Error::IPCBincode(ref e) => {
format!("Unable to read message frame from Launcher, {}", e)
}
Error::IPCIO(ref e) => format!("Unable to receive message from Launcher, {:?}", e),
Error::Protocol(ref e) => format!("{}", e),
Error::Send(ref e) => format!("Unable to send to Launcher's pipe, {}", e),
Error::Serialize(ref e) => format!("Unable to serialize message to Launcher, {}", e),
};
write!(f, "{}", msg)
}
Expand All @@ -63,12 +52,10 @@ impl error::Error for Error {
Error::AcceptConn => "Unable to accept connection from Launcher",
Error::BadPipe(_) => "Unable to open pipe to Launcher",
Error::Connect(_) => "Unable to connect to Launcher's pipe",
Error::Deserialize(_) => "Unable to deserialize message from Launcher",
Error::IPCBincode(_) => "Unable to encode/decode message framing to/from Launcher",
Error::IPCIO(_) => "Unable to receive message from Launcher",
Error::Protocol(_) => "Received an error from Launcher",
Error::Send(_) => "Unable to send to Launcher's pipe",
Error::Serialize(_) => "Unable to serialize message to Launcher",
}
}
}
Expand All @@ -81,3 +68,9 @@ impl From<ipc_channel::ErrorKind> for Error {
}
}
}

impl From<protocol::Error> for Error {
fn from(err: protocol::Error) -> Error {
Error::Protocol(err)
}
}
6 changes: 2 additions & 4 deletions components/launcher-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,19 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use habitat_core as core;
use habitat_launcher_protocol as protocol;
#[macro_use]
extern crate log;

mod client;
pub mod error;

pub use crate::protocol::{
pub use habitat_launcher_protocol::{
ERR_NO_RETRY_EXCODE, LAUNCHER_LOCK_CLEAN_ENV, LAUNCHER_PID_ENV, OK_NO_RETRY_EXCODE,
};

pub use crate::client::LauncherCli;
pub use crate::error::Error;

pub fn env_pipe() -> Option<String> {
core::env::var(protocol::LAUNCHER_PIPE_ENV).ok()
habitat_core::env::var(habitat_launcher_protocol::LAUNCHER_PIPE_ENV).ok()
}
10 changes: 5 additions & 5 deletions components/launcher-protocol/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ version = "0.0.0"
edition = "2018"
authors = ["Jamie Winsor <reset@habitat.sh>"]
build = "build.rs"
workspace = "../../"

[dependencies]
protobuf = "1.5.1"
bytes = "*"
prost = "*"
prost-derive = "*"
serde = "*"
serde_derive = "*"

[build-dependencies]
pkg-config = "*"

[features]
protocols = []
prost-build = "*"
23 changes: 20 additions & 3 deletions components/launcher-protocol/build.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,23 @@
// Inline common build protocols behavior
include!("../libbuild-protocols.rs");
use prost_build;

/// Automatically generate Rust code from our protobuf definitions at
/// compile time.
///
/// Generated code is deposited in `OUT_DIR` and automatically
/// `include!`-ed in our Rust modules, per standard Prost practice.

fn main() {
protocols::generate_if_feature_enabled();
let mut config = prost_build::Config::new();
config.type_attribute(".", "#[derive(Serialize, Deserialize)]");
config
.compile_protos(
&[
"protocols/error.proto",
"protocols/launcher.proto",
"protocols/net.proto",
"protocols/supervisor.proto",
],
&["protocols/"],
)
.unwrap()
}
2 changes: 1 addition & 1 deletion components/launcher-protocol/protocols/error.proto
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
syntax = "proto2";

package error;
package launcher.error;

enum ErrCode {
Unknown = 0;
Expand Down
2 changes: 1 addition & 1 deletion components/launcher-protocol/protocols/launcher.proto
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
syntax = "proto2";

package launcher;
package launcher.launcher;

message Register {
optional string pipe = 1;
Expand Down
Loading

0 comments on commit f15f152

Please sign in to comment.