Skip to content

Commit

Permalink
twoliter: fetch build SDK prior to cargo-make
Browse files Browse the repository at this point in the history
Now that `krane` is run as a static library, we cannot execute it within
Makefile.toml.

This change moves the SDK fetch to occur prior to executing build make
targets.
  • Loading branch information
cbgbt committed Dec 24, 2024
1 parent 4587432 commit 179bec6
Show file tree
Hide file tree
Showing 13 changed files with 245 additions and 98 deletions.
11 changes: 11 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ bytes = "1"
chrono = { version = "0.4", default-features = false }
clap = "4"
coldsnap = { version = "0.6", default-features = false }
ctrlc = "3"
daemonize = "0.5"
duct = "0.13"
env_logger = "0.11"
Expand Down
1 change: 1 addition & 0 deletions twoliter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ async-trait.workspace = true
base64.workspace = true
buildsys-config.workspace = true
clap = { workspace = true, features = ["derive", "env", "std"] }
ctrlc = { workspace = true, features = ["termination"] }
env_logger.workspace = true
filetime.workspace = true
flate2.workspace = true
Expand Down
69 changes: 8 additions & 61 deletions twoliter/embedded/Makefile.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ BUILDSYS_BUILD_DIR = "${BUILDSYS_ROOT_DIR}/build"
BUILDSYS_PACKAGES_DIR = "${BUILDSYS_BUILD_DIR}/rpms"
BUILDSYS_KITS_DIR = "${BUILDSYS_BUILD_DIR}/kits"
BUILDSYS_EXTERNAL_KITS_DIR = "${BUILDSYS_BUILD_DIR}/external-kits"
BUILDSYS_EXTERNAL_SDKS_DIR = "${BUILDSYS_BUILD_DIR}/external-sdk-archives"
BUILDSYS_STATE_DIR = "${BUILDSYS_BUILD_DIR}/state"
BUILDSYS_IMAGES_DIR = "${BUILDSYS_BUILD_DIR}/images"
BUILDSYS_LOGS_DIR = "${BUILDSYS_BUILD_DIR}/logs"
Expand Down Expand Up @@ -291,64 +290,12 @@ mkdir -p ${GO_MOD_CACHE}
'''
]

[tasks.setup-build]
dependencies = ["setup"]
script = [
'''
for cmd in docker gzip lz4; do
if ! command -v ${cmd} >/dev/null 2>&1 ; then
echo "required program '${cmd}' not found" >&2
exit 1
fi
done
'''
]

[tasks.fetch]
dependencies = [
"fetch-sdk",
"fetch-sources",
"fetch-vendored",
]

[tasks.fetch-sdk]
dependencies = ["setup-build"]
script_runner = "bash"
script = [
'''
cleanup() {
[ -n "${SDK_ARCHIVE_PATH}" ] && rm -rf "${SDK_ARCHIVE_PATH}"
}
trap 'cleanup' EXIT
SDK_PLATFORM="$(docker version --format '{{.Server.Os}}/{{.Server.Arch}}')"
KRANE="${TWOLITER_TOOLS_DIR}/krane"
mkdir -p "${BUILDSYS_EXTERNAL_SDKS_DIR}"
SDK_ARCHIVE_PATH="$(mktemp -p ${BUILDSYS_EXTERNAL_SDKS_DIR} bottlerocket-sdk-tmp-archive-XXXXXXXX.tar)"
if [ ! -s "${BUILDSYS_EXTERNAL_KITS_DIR}/.sdk-verified" ]; then
echo "Twoliter could not validate '${TLPRIVATE_SDK_IMAGE}', refusing to continue" >&2
exit 1
fi
if ! docker image inspect "${TLPRIVATE_SDK_IMAGE}" >/dev/null 2>&1 ; then
echo "Pulling SDK '${TLPRIVATE_SDK_IMAGE}'"
if ! ${KRANE} pull "${TLPRIVATE_SDK_IMAGE}" "${SDK_ARCHIVE_PATH}" --platform "${SDK_PLATFORM}" ; then
echo "failed to pull '${TLPRIVATE_SDK_IMAGE}'" >&2
exit 1
fi
if ! docker load --input "${SDK_ARCHIVE_PATH}" ; then
echo "failed to load '${TLPRIVATE_SDK_IMAGE}' into docker daemon" >&2
exit 1
fi
fi
'''
]

[tasks.fetch-sources]
dependencies = ["setup"]
script_runner = "bash"
Expand All @@ -364,7 +311,7 @@ chmod -R o+r ${CARGO_HOME}
]

[tasks.fetch-vendored]
dependencies = ["fetch-sdk"]
dependencies = ["setup"]
script = [
'''
go_fetch() {
Expand All @@ -384,7 +331,7 @@ done
]

[tasks.unit-tests]
dependencies = ["fetch-sdk", "fetch-sources", "fetch-vendored"]
dependencies = ["setup", "fetch-sources", "fetch-vendored"]
script = [
'''
export VARIANT="${BUILDSYS_VARIANT}"
Expand Down Expand Up @@ -639,7 +586,7 @@ fi
]

[tasks.build-sbkeys]
dependencies = ["fetch-sdk"]
dependencies = ["setup"]
script_runner = "bash"
script = [
'''
Expand Down Expand Up @@ -707,7 +654,7 @@ fi
]

[tasks.boot-config]
dependencies = ["fetch-sdk"]
dependencies = ["setup"]
script_runner = "bash"
script = [
'''
Expand Down Expand Up @@ -747,7 +694,7 @@ echo "Boot configuration initrd may be found at ${BOOT_CONFIG}"
]

[tasks.validate-boot-config]
dependencies = ["fetch-sdk"]
dependencies = ["setup"]
script_runner = "bash"
script = [
'''
Expand Down Expand Up @@ -908,7 +855,7 @@ ln -snf "${BUILDSYS_VERSION_FULL}" "${BUILDSYS_OUTPUT_DIR}/latest"
]

[tasks.repack-variant]
dependencies = ["fetch-sdk", "build-sbkeys", "publish-setup", "cargo-metadata"]
dependencies = ["setup", "build-sbkeys", "publish-setup", "cargo-metadata"]
script = [
'''
export PATH="${TWOLITER_TOOLS_DIR}:${PATH}"
Expand Down Expand Up @@ -1223,7 +1170,7 @@ pubsys \
]

[tasks.ami]
dependencies = ["setup-build"]
dependencies = ["setup"]
script_runner = "bash"
script = [
'''
Expand Down Expand Up @@ -1569,7 +1516,7 @@ pubsys \
]

[tasks._upload-ova-base]
dependencies = ["setup-build"]
dependencies = ["setup"]
script_runner = "bash"
script = [
'''
Expand Down
86 changes: 86 additions & 0 deletions twoliter/src/cleanup.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
//! Provides a mechanism for cleaning up resources when twoliter is interrupted.
use anyhow::{Context, Result};
use std::collections::BTreeMap;
use std::future::Future;
use std::path::PathBuf;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex};
use tempfile::TempPath;
use uuid::Uuid;

use self::sealed::*;

lazy_static::lazy_static! {
pub(crate) static ref JANITOR: TempfileJanitor = TempfileJanitor::default();
}

impl TempfileJanitor {
/// Run a given async closure using a [`tempfile::TempPath`].
///
/// The closure has access to the path where the (closed) tempfile is stored.
/// [`TempfileJanitor`] will ensure that the temporary file is deleted in the case that the
/// current process receives SIGINT/SIGTERM/SIGHUP.
pub(crate) async fn with_tempfile<R, Fut>(
&self,
tmpfile: TempPath,
do_: impl FnOnce(PathBuf) -> Fut,
) -> Result<R>
where
Fut: Future<Output = R>,
{
let path = tmpfile.to_path_buf();
let path_id = Uuid::new_v4();

self.paths.lock().unwrap().insert(path_id, tmpfile);

let result = do_(path).await;

self.paths.lock().unwrap().remove(&path_id);

Ok(result)
}

pub(crate) fn try_cleanup(&mut self) {
tracing::info!("Cleaning up temporary resources...");
if let Ok(mut paths) = self.paths.lock() {
while let Some((_, path)) = paths.pop_first() {
tracing::debug!("Deleting tempfile at '{}'", path.display());
if let Err(e) = std::fs::remove_file(&path) {
tracing::error!("Failed to clean tempfile '{}': {}", path.display(), e);
}
}
}
tracing::info!("Done cleaning up.");
}

/// Attempts to install the cleanup process as a SIGINT/SIGTERM/SIGHUP signal handler
pub(crate) fn setup_signal_handler(&self) -> Result<()> {
let mut handler_ref = Self {
paths: Arc::clone(&self.paths),
};

let already_handling = Arc::new(AtomicBool::new(false));
ctrlc::try_set_handler(move || {
if already_handling
.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
.is_ok()
{
handler_ref.try_cleanup();
}
// SIGINT is 130
std::process::exit(130);
})
.context("Failed to create cleanup signal handler")
}
}

/// Signal handlers are global -- hide `TempfileJanitor` to encourage use of the static reference.
mod sealed {
use super::*;

#[derive(Default, Debug)]
pub(crate) struct TempfileJanitor {
pub(super) paths: Arc<Mutex<BTreeMap<Uuid, TempPath>>>,
}
}
2 changes: 2 additions & 0 deletions twoliter/src/cmd/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ impl BuildKit {
optional_envs.push(("BUILDSYS_LOOKASIDE_CACHE", lookaside_cache))
}

project.fetch_sdk().await?;
CargoMake::new(&project.sdk_image().project_image_uri().to_string())?
.env("TWOLITER_TOOLS_DIR", toolsdir.display().to_string())
.env("BUILDSYS_ARCH", &self.arch)
Expand Down Expand Up @@ -135,6 +136,7 @@ impl BuildVariant {
))
}

project.fetch_sdk().await?;
CargoMake::new(&project.sdk_image().project_image_uri().to_string())?
.env("TWOLITER_TOOLS_DIR", toolsdir.display().to_string())
.env("BUILDSYS_ARCH", &self.arch)
Expand Down
3 changes: 2 additions & 1 deletion twoliter/src/cmd/fetch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ impl Fetch {
pub(super) async fn run(&self) -> Result<()> {
let project = project::load_or_find_project(self.project_path.clone()).await?;
let project = project.load_lock::<Locked>().await?;
project.fetch(self.arch.as_str()).await?;
project.fetch_kits(self.arch.as_str()).await?;
project.fetch_sdk().await?;
Ok(())
}
}
44 changes: 14 additions & 30 deletions twoliter/src/cmd/make.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,19 @@ pub(crate) struct Make {
impl Make {
pub(super) async fn run(&self) -> Result<()> {
let project = project::load_or_find_project(self.project_path.clone()).await?;
let sdk_source = self.locked_sdk(&project).await?;

let sdk_source = if self.can_skip_kit_verification(&project) {
let project = project.load_lock::<SDKLocked>().await?;
project.fetch_sdk().await?;
project.sdk_image()
} else {
let project = project.load_lock::<Locked>().await?;
project.fetch_sdk().await?;
project.sdk_image()
}
.project_image_uri()
.to_string();

let toolsdir = project.project_dir().join("build/tools");
install_tools(&toolsdir).await?;
let makefile_path = toolsdir.join("Makefile.toml");
Expand All @@ -75,17 +87,6 @@ impl Make {

target_allows_kit_verification_skip && project_has_explicit_sdk_dep
}

/// Returns the locked SDK image for the project.
async fn locked_sdk(&self, project: &project::Project<Unlocked>) -> Result<String> {
Ok(if self.can_skip_kit_verification(project) {
project.load_lock::<SDKLocked>().await?.sdk_image()
} else {
project.load_lock::<Locked>().await?.sdk_image()
}
.project_image_uri()
.to_string())
}
}

#[cfg(test)]
Expand Down Expand Up @@ -227,6 +228,7 @@ mod test {
install_tools(&toolsdir).await.unwrap();
let makefile_path = toolsdir.join("Makefile.toml");

project.fetch_sdk().await?;
CargoMake::new(&sdk_source)
.unwrap()
.env("CARGO_HOME", project_dir.display().to_string())
Expand Down Expand Up @@ -266,24 +268,6 @@ mod test {
assert!(!target_can_skip_kit_verification("build-variant").await);
}

#[tokio::test]
#[ignore] // integration test
async fn test_fetch_sdk_succeeds_when_only_sdk_verified() {
let temp_dir = crate::test::copy_project_to_temp_dir(PROJECT);
assert!(run_makefile_target("fetch-sdk", &temp_dir.path(), false)
.await
.is_ok());
}

#[tokio::test]
#[ignore] // integration test
async fn test_fetch_sdk_fails_when_nothing_verified() {
let temp_dir = crate::test::copy_project_to_temp_dir(PROJECT);
assert!(run_makefile_target("fetch-sdk", &temp_dir.path(), true)
.await
.is_err());
}

#[tokio::test]
#[ignore] // integration test
async fn test_validate_kits_fails_when_only_sdk_verified() {
Expand Down
2 changes: 2 additions & 0 deletions twoliter/src/cmd/publish_kit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ impl PublishKit {
pub(super) async fn run(&self) -> Result<()> {
let project = project::load_or_find_project(self.project_path.clone()).await?;
let project = project.load_lock::<Locked>().await?;

let toolsdir = project.project_dir().join("build/tools");
install_tools(&toolsdir).await?;
let makefile_path = toolsdir.join("Makefile.toml");
Expand All @@ -48,6 +49,7 @@ impl PublishKit {
Some(kit_repo) => kit_repo,
None => &self.kit_name,
};
project.fetch_sdk().await?;
CargoMake::new(project.sdk_image().project_image_uri().to_string().as_str())?
.env("TWOLITER_TOOLS_DIR", toolsdir.display().to_string())
.env("BUILDSYS_KIT", &self.kit_name)
Expand Down
Loading

0 comments on commit 179bec6

Please sign in to comment.