Skip to content

Commit

Permalink
Windows builds
Browse files Browse the repository at this point in the history
Signed-off-by: James Sturtevant <[email protected]>
Signed-off-by: James Sturtevant <[email protected]>
  • Loading branch information
jsturtevant committed Aug 21, 2023
1 parent 52e55cf commit ea1e5e6
Show file tree
Hide file tree
Showing 31 changed files with 1,232 additions and 926 deletions.
5 changes: 5 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[target.'cfg(windows)']
rustflags = [
"-Adead_code",
"-Awarnings",
]
39 changes: 29 additions & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,40 +11,59 @@ env:

jobs:
fmt:
runs-on: "ubuntu-latest"
strategy:
matrix:
os: ["ubuntu-latest", "windows-latest"]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- uses: actions-rust-lang/setup-rust-toolchain@v1
with:
components: rustfmt, clippy
rustflags: '' #Disable. By default this action sets environment variable is set to -D warnings. We manage this in the Makefile
- name: Setup build env
run: ./scripts/setup.sh
run: |
os=$(echo "$RUNNER_OS" | tr '[:upper:]' '[:lower:]')
./scripts/setup-$os.sh
shell: bash
- run:
# needed to run rustfmt in nightly toolchain
rustup toolchain install nightly --component rustfmt
- name: Set environment variables for Windows
if: runner.os == 'Windows'
run: |
# required until standalong is implemented for windows (https://github.com/WasmEdge/wasmedge-rust-sdk/issues/54)
echo "WASMEDGE_LIB_DIR=C:\Program Files\WasmEdge\lib" >> $env:GITHUB_ENV
echo "WASMEDGE_INCLUDE_DIR=C:\Program Files\WasmEdge\include" >> $env:GITHUB_ENV
- name: Run checks
run: make check
build:
strategy:
matrix:
os: ["ubuntu-20.04", "ubuntu-22.04"]
os: ["ubuntu-20.04", "ubuntu-22.04", "windows-latest"]
runs-on: ${{ matrix.os }}
steps:
- name: "check cgroup version"
run: "mount | grep cgroup"
if: runner.os == 'Linux'
- uses: actions/checkout@v3
- uses: actions-rust-lang/setup-rust-toolchain@v1
env:
RUST_CACHE_KEY_OS: ${{ matrix.os }}
with:
rustflags: '' #Disable. By default this action sets environment variable is set to -D warnings. We manage this in the Makefile
- name: Setup build env
run: ./scripts/setup.sh
run: |
os=$(echo "$RUNNER_OS" | tr '[:upper:]' '[:lower:]')
./scripts/setup-$os.sh
shell: bash
- name: Set environment variables for Windows
if: runner.os == 'Windows'
run: |
echo "WASMEDGE_LIB_DIR=C:\Program Files\WasmEdge\lib" >> $env:GITHUB_ENV
echo "WASMEDGE_INCLUDE_DIR=C:\Program Files\WasmEdge\include" >> $env:GITHUB_ENV
- name: Build
uses: actions-rs/cargo@v1
with:
command: build
args: --all --verbose
run: make build
- name: Validate docs
run: ./scripts/validate-docs.sh
- name: Run tests
Expand All @@ -65,7 +84,7 @@ jobs:
- name: setup rust-wasm target
run: rustup target add wasm32-wasi
- name: Setup build env
run: ./scripts/setup.sh
run: ./scripts/setup-linux.sh
shell: bash
- name: run
run: make test/k8s
Expand All @@ -92,7 +111,7 @@ jobs:
- name: setup rust-wasm target
run: rustup target add wasm32-wasi
- name: Setup build env
run: ./scripts/setup.sh
run: ./scripts/setup-linux.sh
shell: bash
- name: run
run: make test/k3s
Expand Down
22 changes: 16 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,32 +10,42 @@ ifeq ($(TARGET),release)
RELEASE_FLAG = --release
endif

FEATURES := --features libcontainer_default
WARNINGS := -D warnings
ifeq ($(OS), Windows_NT)
# need to turn off static/standalone for wasm-edge
FEATURES = --no-default-features
# turn of warnings until windows is fully supported #49
WARNINGS =
endif

DOCKER_BUILD ?= docker buildx build

KIND_CLUSTER_NAME ?= containerd-wasm

.PHONY: build
build:
cargo build -p containerd-shim-wasm --features generate_bindings $(RELEASE_FLAG)
# compiling against libcontainer's default features (dependency on libseccomp)
cargo build -p containerd-shim-wasm --features libcontainer_default $(RELEASE_FLAG)
cargo build $(RELEASE_FLAG)
cargo build -p containerd-shim-wasm $(FEATURES) $(RELEASE_FLAG)
cargo build $(FEATURES) $(RELEASE_FLAG)

.PHONY: check
check:
cargo +nightly fmt --all -- --check
cargo clippy --all --all-targets -- -D warnings
cargo clippy $(FEATURES) --all --all-targets -- $(WARNINGS)

.PHONY: fix
fix:
cargo +nightly fmt --all
cargo clippy --fix --all --all-targets -- -D warnings
cargo clippy $(FEATURES) --fix --all --all-targets -- $(WARNINGS)

.PHONY: test
test:
RUST_LOG=trace cargo test --all --verbose -- --nocapture
RUST_LOG=trace cargo test $(FEATURES) --all --verbose -- --nocapture
ifneq ($(OS), Windows_NT)
# run wasmedge test without the default `static` feature
RUST_LOG=trace cargo test --package containerd-shim-wasmedge --verbose --no-default-features --features standalone -- --nocapture
endif

.PHONY: install
install:
Expand Down
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,12 +146,18 @@ You will need to make sure the `containerd-[ wasmedge | wasmtime ]d` daemon has

#### Building

1. Install [youki dependencies](https://github.com/containers/youki#dependencies)
1. Install dependencies

If on ubuntu/debian you can use the following script. Refer to youki's documentation for other systems.
If on ubuntu/debian you can use the following script. Refer to [youki's](https://github.com/containers/youki#dependencies) documentation for other systems.

```
./scripts/setup.sh
./scripts/setup-linux.sh
```

If on Windows use (use [git BASH](https://gitforwindows.org/) terminal which has shell emulator)

```
./scripts/setup-windows.sh
```

2. Build
Expand Down
10 changes: 6 additions & 4 deletions crates/containerd-shim-wasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,22 @@ containerd-shim = { workspace = true }
anyhow = { workspace = true }
serde_json = { workspace = true }
oci-spec = { workspace = true }
command-fds = "0.2"
serde = { workspace = true }
thiserror = { workspace = true }
protobuf = "3.2"
ttrpc = { workspace = true }
nix = { workspace = true }
chrono = { workspace = true }
log = { workspace = true }
clone3 = "0.2"
libc = { workspace = true }

[target.'cfg(unix)'.dependencies]
clone3 = "0.2"
caps = "0.5"
command-fds = "0.2"
proc-mounts = "0.3"
libcontainer = { workspace = true, optional = true, default-features = false }
cgroups-rs = "0.3.3"
nix = { workspace = true }

[build-dependencies]
ttrpc-codegen = { version = "0.4.2", optional = true }
Expand All @@ -50,4 +52,4 @@ libseccomp = ["libcontainer/libseccomp"]
systemd = ["libcontainer/systemd"]
cgroupsv2 = ["libcontainer/v2"]
cgroupsv1 = ["libcontainer/v1"]
cgroupsv2_devices = ["libcontainer/cgroupsv2_devices"]
cgroupsv2_devices = ["libcontainer/cgroupsv2_devices"]
4 changes: 3 additions & 1 deletion crates/containerd-shim-wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@

pub mod sandbox;

mod macros;
pub mod services;
pub mod sys;

#[cfg(feature = "libcontainer")]
#[cfg(all(feature = "libcontainer", not(target_os = "windows")))]
pub mod libcontainer_instance;
19 changes: 19 additions & 0 deletions crates/containerd-shim-wasm/src/macros.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#[macro_export]
macro_rules! cfg_windows {
($($item:item)*) => {
$(
#[cfg(windows)]
$item
)*
}
}

#[macro_export]
macro_rules! cfg_unix {
($($item:item)*) => {
$(
#[cfg(unix)]
$item
)*
}
}
1 change: 1 addition & 0 deletions crates/containerd-shim-wasm/src/sandbox/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ pub enum Error {
#[error("{0}")]
Json(#[from] serde_json::Error),
/// Error from the system
#[cfg(unix)]
#[error("{0}")]
Errno(#[from] nix::errno::Errno),
}
Expand Down
9 changes: 8 additions & 1 deletion crates/containerd-shim-wasm/src/sandbox/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,17 @@ use std::sync::{Arc, Condvar, Mutex};
use std::thread;

use chrono::{DateTime, Utc};
use libc::{SIGINT, SIGKILL, SIGTERM};
use libc::{SIGINT, SIGTERM};

use super::error::Error;

pub type ExitCode = Arc<(Mutex<Option<(u32, DateTime<Utc>)>>, Condvar)>;

#[cfg(unix)]
use libc::SIGKILL;
#[cfg(windows)]
const SIGKILL: i32 = 9;

/// Generic options builder for creating a wasm instance.
/// This is passed to the `Instance::new` method.
#[derive(Clone)]
Expand Down Expand Up @@ -216,6 +221,7 @@ mod noptests {
use std::sync::mpsc::channel;
use std::time::Duration;

#[cfg(unix)]
use libc::SIGHUP;

use super::*;
Expand Down Expand Up @@ -259,6 +265,7 @@ mod noptests {
Ok(())
}

#[cfg(unix)]
#[test]
fn test_op_kill_other() -> Result<(), Error> {
let nop = Nop::new("".to_string(), None);
Expand Down
19 changes: 2 additions & 17 deletions crates/containerd-shim-wasm/src/sandbox/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
use std::collections::HashMap;
use std::env::current_dir;
use std::fs::File;
use std::os::unix::io::AsRawFd;
use std::path::Path;
use std::sync::{Arc, RwLock};
use std::thread;
Expand All @@ -17,7 +15,6 @@ use containerd_shim::protos::ttrpc::{Client, Server};
use containerd_shim::protos::TaskClient;
use containerd_shim::publisher::RemotePublisher;
use containerd_shim::{self as shim, api, TtrpcContext, TtrpcResult};
use nix::sched::{setns, unshare, CloneFlags};
use oci_spec::runtime;
use shim::Flags;
use ttrpc::context;
Expand All @@ -26,6 +23,7 @@ use super::error::Error;
use super::instance::Instance;
use super::{oci, sandbox};
use crate::services::sandbox_ttrpc::{Manager, ManagerClient};
use crate::sys::networking::setup_namespaces;

/// Sandbox wraps an Instance and is used with the `Service` to manage multiple instances.
pub trait Sandbox: Task + Send + Sync {
Expand Down Expand Up @@ -156,20 +154,7 @@ impl<T: Sandbox + 'static> Manager for Service<T> {
// Note that this changes the current thread's state.
// You probably want to run this in a new thread.
fn start_sandbox(cfg: runtime::Spec, server: &mut Server) -> Result<(), Error> {
let namespaces = cfg.linux().as_ref().unwrap().namespaces().as_ref().unwrap();
for ns in namespaces {
if ns.typ() == runtime::LinuxNamespaceType::Network {
if ns.path().is_some() {
let p = ns.path().clone().unwrap();
let f = File::open(p).context("could not open network namespace")?;
setns(f.as_raw_fd(), CloneFlags::CLONE_NEWNET)
.context("error setting network namespace")?;
break;
}

unshare(CloneFlags::CLONE_NEWNET).context("error unsharing network namespace")?;
}
}
setup_namespaces(&cfg)?;

server.start_listen().context("could not start listener")?;
Ok(())
Expand Down
26 changes: 19 additions & 7 deletions crates/containerd-shim-wasm/src/sandbox/oci.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@
use std::collections::HashMap;
use std::fs::File;
use std::io::{ErrorKind, Write};
#[cfg(unix)]
use std::os::unix::process::CommandExt;
use std::path::{Path, PathBuf};
use std::process;

use anyhow::Context;
use nix::sys::signal;
use nix::unistd::Pid;
pub use oci_spec::runtime::Spec;
use serde_json as json;

Expand Down Expand Up @@ -96,14 +95,28 @@ pub fn setup_prestart_hooks(hooks: &Option<oci_spec::runtime::Hooks>) -> Result<
// Based on OCI spec, the first argument of the args vector is the
// arg0, which can be different from the path. For example, path
// may be "/usr/bin/true" and arg0 is set to "true". However, rust
// command differenciates arg0 from args, where rust command arg
// command differentiates arg0 from args, where rust command arg
// doesn't include arg0. So we have to make the split arg0 from the
// rest of args.
if let Some((arg0, args)) = hook.args().as_ref().and_then(|a| a.split_first()) {
log::debug!("run_hooks arg0: {:?}, args: {:?}", arg0, args);
hook_command.arg0(arg0).args(args)

#[cfg(unix)]
{
hook_command.arg0(arg0).args(args);
}

#[cfg(windows)]
{
if !&hook.path().ends_with(arg0) {
return Err(crate::sandbox::Error::InvalidArgument("Running with arg0 as different name than executable is not supported on Windows due to rust std library process implementation.".to_string()));
}

hook_command.args(args);
}
} else {
hook_command.arg0(&hook.path().display().to_string())
#[cfg(unix)]
hook_command.arg0(&hook.path().display().to_string());
};

let envs: HashMap<String, String> = if let Some(env) = hook.env() {
Expand All @@ -119,7 +132,6 @@ pub fn setup_prestart_hooks(hooks: &Option<oci_spec::runtime::Hooks>) -> Result<
.stdin(process::Stdio::piped())
.spawn()
.with_context(|| "Failed to execute hook")?;
let hook_process_pid = Pid::from_raw(hook_process.id() as i32);

if let Some(stdin) = &mut hook_process.stdin {
// We want to ignore BrokenPipe here. A BrokenPipe indicates
Expand All @@ -135,7 +147,7 @@ pub fn setup_prestart_hooks(hooks: &Option<oci_spec::runtime::Hooks>) -> Result<
if e.kind() != ErrorKind::BrokenPipe {
// Not a broken pipe. The hook command may be waiting
// for us.
let _ = signal::kill(hook_process_pid, signal::Signal::SIGKILL);
let _ = hook_process.kill();
}
}
}
Expand Down
Loading

0 comments on commit ea1e5e6

Please sign in to comment.