Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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.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
33 changes: 27 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,35 @@ 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<(std::path::PathBuf, 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()
};
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function doesn't return either a NamedTempFile or TempPath, so the output path will be deleted when temp_path is dropped at the end of the function if output_path_arg is None.

To get the behavior you want you might need to have an enum with two variants, a PathBuf and a TempPath.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, hmm.

What do you think about using std::fs::copy instead of NamedTempFile::persist so it's not consumed and then we have this return the TempPath we created?


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)?;

let output_path = if let Some(output_path) = output_path_arg {
temp_path.persist(&output_path)?;

output_path.into_std_path_buf()
} else {
temp_path.to_path_buf()
};

Ok(metadata)
Ok((output_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