Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "dropkick"
version = "0.2.1"
version = "0.3.0"
edition = "2021"
publish = false

Expand Down
29 changes: 23 additions & 6 deletions src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use cargo_metadata::MetadataCommand;
use clap::{Parser, ValueEnum};
use serde::{Deserialize, Serialize};
use std::io::{Read, Seek, SeekFrom, Write};
use tempfile::NamedTempFile;

#[derive(Debug, Parser, Serialize)]
#[serde(rename_all = "camelCase")]
Expand Down Expand Up @@ -44,6 +45,10 @@ pub(crate) struct Args {
#[serde(skip_serializing)]
pub(crate) package_dir: Utf8PathBuf,

/// Output path for built image (if not specified, the output is deleted)
#[clap(long)]
pub(crate) output_path: Option<Utf8PathBuf>,

#[clap(flatten)]
#[serde(flatten)]
pub(crate) config: Config,
Expand Down Expand Up @@ -143,19 +148,31 @@ impl Args {
Ok(serde_json::to_string(&self.into_nixos_builder()?)?)
}

pub(crate) fn create_iso(self, writer: &mut std::fs::File) -> Result<Metadata> {
pub(crate) fn create_iso(self) -> Result<(tempfile::TempPath, Metadata)> {
let output_path_arg = self.output_path.clone();
let (mut file, temp_path) = if let Some(output_path) = &output_path_arg {
NamedTempFile::new_in(output_path.parent().context("output path has no parent")?)?
.into_parts()
} else {
NamedTempFile::new()?.into_parts()
};

let nixos_builder = self.into_nixos_builder()?;
let metadata = nixos_builder.build(writer)?;
let metadata = nixos_builder.build(&mut file)?;

// append an empty ext4 filesystem to the image (see notes about /persist in config.nix)
sparse_copy(
&mut zstd::Decoder::new(include_bytes!("fs/ext4.zst").as_slice())?,
writer,
&mut file,
)?;
let len = writer.stream_position()?;
writer.set_len(len)?;
let len = file.stream_position()?;
file.set_len(len)?;

if let Some(output_path) = output_path_arg {
std::fs::copy(&temp_path, output_path)?;
}

Ok(metadata)
Ok((temp_path, metadata))
}
}

Expand Down
6 changes: 2 additions & 4 deletions src/ec2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,10 @@ use aws_sdk_ec2::types::{
};
use coldsnap::{SnapshotUploader, SnapshotWaiter};
use indicatif::ProgressBar;
use tempfile::NamedTempFile;

impl Args {
pub(crate) async fn create_ec2_image(self, config: &SdkConfig) -> Result<String> {
let (mut file, temp_path) = NamedTempFile::new()?.into_parts();
let metadata = self.create_iso(&mut file)?;
let (output_path, metadata) = self.create_iso()?;
let image_name = format!(
"{name:.len$}-{store_hash}",
name = metadata.package.name,
Expand Down Expand Up @@ -45,7 +43,7 @@ impl Args {
log::info!("uploading EC2 snapshot");
let snapshot_id = SnapshotUploader::new(ebs_client)
.upload_from_file(
&temp_path,
&output_path,
None,
Some(&image_name),
Some(ProgressBar::new(0)),
Expand Down
25 changes: 3 additions & 22 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,16 @@ mod tempdir;
use anyhow::{bail, Context, Result};
use aws_config::BehaviorVersion;
use aws_sdk_cloudformation::types::{Capability, Parameter, StackStatus};
use camino::Utf8PathBuf;
use clap::Parser;
use env_logger::Env;
use std::time::Duration;
use tempfile::NamedTempFile;

#[derive(Debug, Parser)]
enum Command {
/// Build virtual machine image
Build {
#[clap(flatten)]
build_args: crate::build::Args,

/// Output path for built image (if not specified, the output is deleted)
output_path: Option<Utf8PathBuf>,
},

/// Create image for use in EC2
Expand Down Expand Up @@ -69,23 +64,9 @@ async fn main() -> Result<()> {
env_logger::Builder::from_env(Env::default().default_filter_or("dropkick=info")).init();

match Command::parse() {
Command::Build {
build_args,
output_path,
} => {
let (mut file, persist) = if let Some(output_path) = &output_path {
let (file, temp_path) = NamedTempFile::new_in(
output_path.parent().context("output path has no parent")?,
)?
.into_parts();
(file, Some((temp_path, output_path)))
} else {
(tempfile::tempfile()?, None)
};
build_args.create_iso(&mut file)?;
if let Some((temp_path, output_path)) = persist {
temp_path.persist(output_path)?;
}
Command::Build { build_args } => {
build_args.create_iso()?;

Ok(())
}
Command::CreateEc2Image { build_args } => {
Expand Down
8 changes: 3 additions & 5 deletions src/oxide.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ use std::fs::File;
use std::io::Read;
use std::path::PathBuf;
use std::sync::Arc;
use tempfile::NamedTempFile;

impl Args {
pub(crate) async fn create_oxide_image(self, deploy: bool) -> Result<String> {
Expand All @@ -37,8 +36,7 @@ impl Args {

let hostname = self.hostname.clone();

let (mut file, temp_path) = NamedTempFile::new()?.into_parts();
let metadata = self.create_iso(&mut file)?;
let (output_path, metadata) = self.create_iso()?;
let mut image_name = format!(
"{name:.len$}-{store_hash}",
name = metadata.package.name,
Expand Down Expand Up @@ -71,7 +69,7 @@ impl Args {
let mut disk_name = format!("{}-disk", &image_name);
disk_name.truncate(63);

let disk_size = get_disk_size(&temp_path.to_path_buf())?;
let disk_size = get_disk_size(&output_path.to_path_buf())?;

context
.client()?
Expand All @@ -97,7 +95,7 @@ impl Args {
.send()
.await?;

let mut file = File::open(&temp_path)?;
let mut file = File::open(&output_path)?;
let mut offset = 0;
let file_size = file.metadata()?.len();

Expand Down