Skip to content

Commit

Permalink
Tweaks for running on our system (#57)
Browse files Browse the repository at this point in the history
  • Loading branch information
rukai authored Jul 22, 2024
1 parent 4fed1a1 commit 37134f5
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 20 deletions.
24 changes: 14 additions & 10 deletions aws-throwaway/src/backend/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ struct Subnet {
map_public_ip_on_launch: Option<bool>,
}

const AZ: &str = "us-east-1c";

struct Tags {
pub user_name: String,
pub cleanup: CleanupResources,
Expand Down Expand Up @@ -103,6 +101,7 @@ impl Tags {
pub struct Aws {
tags: Tags,
keyname: String,
az_name: String,
client_private_key: String,
host_public_key: String,
host_public_key_bytes: Vec<u8>,
Expand All @@ -125,6 +124,7 @@ impl Aws {
let keyname = format!("aws-throwaway-{user_name}-{}", Uuid::new_v4());
let security_group_name = format!("aws-throwaway-{user_name}-{}", Uuid::new_v4());
let placement_group_name = format!("aws-throwaway-{user_name}-{}", Uuid::new_v4());
let az_name = builder.az_name.unwrap_or_else(|| "us-east-1c".into());

let tags = Tags {
user_name,
Expand All @@ -143,7 +143,7 @@ impl Aws {
&builder.expose_ports_to_internet
),
Aws::create_placement_group(&tags, &placement_group_name, builder.placement_strategy),
Aws::get_subnet(builder.subnet_id)
Aws::get_subnet(builder.subnet_id, az_name.clone())
);

let subnet_id = subnet.subnet_id.unwrap();
Expand All @@ -158,6 +158,7 @@ impl Aws {

Aws {
use_public_addresses,
az_name,
keyname,
client_private_key,
host_public_key_bytes,
Expand Down Expand Up @@ -300,21 +301,21 @@ impl Aws {
tracing::info!("created placement group");
}

async fn get_subnet(subnet_id: Option<String>) -> Subnet {
async fn get_subnet(subnet_id: Option<String>, az_name: String) -> Subnet {
let mut command = vec!["ec2", "describe-subnets", "--filters"];

// this is needed to keep the string values alive for the length of the borrow
let value;

match subnet_id {
match &subnet_id {
Some(subnet_id) => command.push({
value = format!("Name=subnet-id,Values={subnet_id}");
&value
}),
None => {
command.push("Name=default-for-az,Values=true");
command.push({
value = format!("Name=availability-zone,Values={AZ}");
value = format!("Name=availability-zone,Values={az_name}");
&value
});
}
Expand All @@ -326,7 +327,10 @@ impl Aws {
}
let Response::Subnets(mut result) = run_command(&command).await.unwrap();

result.pop().unwrap()
result.pop().unwrap_or_else(|| match subnet_id {
Some(subnet) => panic!("Subnet {subnet} could not be found"),
None => panic!("No default subnet configured for {az_name}"),
})
}

/// Call before dropping [`Aws`]
Expand Down Expand Up @@ -583,8 +587,8 @@ impl Aws {

let tag_specifications = self.tags.create_tags("instance", "aws-throwaway");
let placement = format!(
"AvailabilityZone={AZ},GroupName={}",
self.placement_group_name
"AvailabilityZone={},GroupName={}",
self.az_name, self.placement_group_name
);
// Secondary interfaces should not be used until they are configured.
let mut bring_down_secondary_interfaces = String::new();
Expand All @@ -609,7 +613,7 @@ sudo systemctl start ssh
self.host_public_key, self.host_private_key
);
let block_device_mappings = format!(
"DeviceName=/dev/sda1,Ebs={{DeleteOnTermination=true,VolumeSize={},VolumeType=gp2}}",
"DeviceName=/dev/sda1,Ebs={{DeleteOnTermination=true,VolumeSize={},VolumeType=gp2,Encrypted=true}}",
definition.volume_size_gb
);

Expand Down
26 changes: 18 additions & 8 deletions aws-throwaway/src/backend/sdk/aws.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ use std::pin::Pin;
use std::time::{Duration, Instant};
use uuid::Uuid;

const AZ: &str = "us-east-1c";

async fn config() -> SdkConfig {
let region_provider = RegionProviderChain::first_try(Region::new("us-east-1"));
aws_config::defaults(BehaviorVersion::latest())
Expand All @@ -37,6 +35,7 @@ async fn config() -> SdkConfig {
/// Construct this type to create and cleanup aws resources.
pub struct Aws {
client: aws_sdk_ec2::Client,
az_name: String,
keyname: String,
client_private_key: String,
host_public_key: String,
Expand All @@ -57,6 +56,7 @@ impl Aws {
let keyname = format!("aws-throwaway-{user_name}-{}", Uuid::new_v4());
let security_group_name = format!("aws-throwaway-{user_name}-{}", Uuid::new_v4());
let placement_group_name = format!("aws-throwaway-{user_name}-{}", Uuid::new_v4());
let az_name = builder.az_name.unwrap_or_else(|| "us-east-1c".into());
let client = aws_sdk_ec2::Client::new(&config);

let tags = Tags {
Expand All @@ -83,7 +83,7 @@ impl Aws {
&placement_group_name,
builder.placement_strategy
),
Aws::get_subnet(&client, builder.subnet_id)
Aws::get_subnet(&client, builder.subnet_id, az_name.clone())
);

let subnet_id = subnet.subnet_id.unwrap();
Expand All @@ -99,6 +99,7 @@ impl Aws {
Aws {
use_public_addresses,
client,
az_name,
keyname,
client_private_key,
host_public_key_bytes,
Expand All @@ -111,6 +112,7 @@ impl Aws {
tags,
}
}

/// Returns an [`AwsBuilder`] that will build a new [`Aws`].
///
/// Before building the [`Aws`], all preexisting resources conforming to the specified [`CleanupResources`] approach are destroyed.
Expand Down Expand Up @@ -248,8 +250,12 @@ impl Aws {
tracing::info!("created placement group");
}

async fn get_subnet(client: &aws_sdk_ec2::Client, subnet_id: Option<String>) -> Subnet {
match subnet_id {
async fn get_subnet(
client: &aws_sdk_ec2::Client,
subnet_id: Option<String>,
az_name: String,
) -> Subnet {
match &subnet_id {
Some(subnet_id) => client.describe_subnets().filters(
Filter::builder()
.name("subnet-id")
Expand All @@ -267,7 +273,7 @@ impl Aws {
.filters(
Filter::builder()
.name("availability-zone")
.values(AZ)
.values(&az_name)
.build(),
),
}
Expand All @@ -278,7 +284,10 @@ impl Aws {
.subnets
.unwrap()
.pop()
.unwrap()
.unwrap_or_else(|| match subnet_id {
Some(subnet) => panic!("Subnet {subnet} could not be found"),
None => panic!("No default subnet configured for {az_name}"),
})
}

/// Call before dropping [`Aws`]
Expand Down Expand Up @@ -500,7 +509,7 @@ impl Aws {
.set_placement(Some(
Placement::builder()
.group_name(&self.placement_group_name)
.availability_zone(AZ)
.availability_zone(&self.az_name)
.build(),
))
.set_subnet_id(if definition.network_interface_count == 1 {
Expand All @@ -518,6 +527,7 @@ impl Aws {
.delete_on_termination(true)
.volume_size(definition.volume_size_gb as i32)
.volume_type(VolumeType::Gp2)
.encrypted(true)
.build(),
)
.build(),
Expand Down
15 changes: 13 additions & 2 deletions aws-throwaway/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub struct AwsBuilder {
cleanup: CleanupResources,
use_public_addresses: bool,
vpc_id: Option<String>,
az_name: Option<String>,
subnet_id: Option<String>,
placement_strategy: PlacementStrategy,
security_group_id: Option<String>,
Expand All @@ -28,8 +29,8 @@ pub struct AwsBuilder {
/// * you want to connect directly from within the VPC
/// * you have already created a specific VPC, subnet or security group that you want aws-throwaway to make use of.
///
/// All resources will be created in us-east-1c.
/// This is hardcoded so that aws-throawaway only has to look into one region when cleaning up.
/// All resources will be created in us-east-1.
/// This is hardcoded so that aws-throwaway only has to look into one region when cleaning up.
/// All instances are created in a single spread placement group in a single AZ to ensure consistent latency between instances.
// TODO: document minimum required access for default configuration.
impl AwsBuilder {
Expand All @@ -38,6 +39,7 @@ impl AwsBuilder {
cleanup,
use_public_addresses: true,
vpc_id: None,
az_name: None,
subnet_id: None,
// refer to: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/placement-groups.html
// I believe Spread is the best default since it is the easiest for amazon to fulfill and gives the most realistic results in benchmarks.
Expand Down Expand Up @@ -71,6 +73,15 @@ impl AwsBuilder {
self
}

/// * Some(_) => All resources will go into the specified AZ
/// * None => All resources will go into the default AZ (us-east-1c)
///
/// The default is `None`
pub fn use_az(mut self, az_name: Option<String>) -> Self {
self.az_name = az_name;
self
}

/// * Some(_) => All instances will go into the specified subnet
/// * None => All instances will go into the default subnet for the specified or default vpc
///
Expand Down

0 comments on commit 37134f5

Please sign in to comment.