Skip to content

Commit

Permalink
Merge branch 'main' into no-rmp
Browse files Browse the repository at this point in the history
  • Loading branch information
jonaro00 authored Jun 28, 2024
2 parents dc54497 + 22dc7c7 commit 716e4ce
Show file tree
Hide file tree
Showing 7 changed files with 212 additions and 29 deletions.
44 changes: 34 additions & 10 deletions cargo-shuttle/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ use ignore::WalkBuilder;
use indicatif::ProgressBar;
use indoc::{formatdoc, printdoc};
use shuttle_common::models::deployment::{
BuildMetaBeta, DeploymentRequestBuildArchiveBeta, DeploymentRequestImageBeta,
BuildArgsBeta, BuildMetaBeta, DeploymentRequestBuildArchiveBeta, DeploymentRequestImageBeta,
};
use shuttle_common::{
constants::{
Expand Down Expand Up @@ -1055,7 +1055,14 @@ impl Shuttle {
client.get_service_resources(self.ctx.project_name()).await
}
.map_err(suggestions::resources::get_service_resources_failure)?;
let table = get_resource_tables(&resources, self.ctx.project_name(), raw, show_secrets);

let table = get_resource_tables(
&resources,
self.ctx.project_name(),
raw,
show_secrets,
self.beta,
);

println!("{table}");

Expand Down Expand Up @@ -1261,7 +1268,15 @@ impl Shuttle {

println!(
"{}",
get_resource_tables(&mocked_responses, service_name.as_str(), false, false)
get_resource_tables(
&mocked_responses,
service_name.as_str(),
false,
false,
// Set beta to false to avoid breaking local run with beta changes.
// TODO: make local run compatible with --beta.
false
)
);

//
Expand Down Expand Up @@ -1821,23 +1836,31 @@ impl Shuttle {
};

if self.beta {
let mut build_args = BuildArgsBeta::default();

let metadata = async_cargo_metadata(manifest_path.as_path()).await?;
let packages = find_shuttle_packages(&metadata)?;
// TODO: support overriding this
let package = packages
.first()
.expect("at least one shuttle crate in the workspace");
let package_name = package.name.to_owned();
deployment_req_buildarch_beta.package_name = package_name;
build_args.package_name = Some(package_name);

// TODO: add these to the request and builder
let (_no_default_features, _features) = if package.features.contains_key("shuttle") {
(true, vec!["shuttle".to_owned()])
// activate shuttle feature is present
let (no_default_features, features) = if package.features.contains_key("shuttle") {
(true, Some(vec!["shuttle".to_owned()]))
} else {
(false, vec![])
(false, None)
};
build_args.no_default_features = no_default_features;
build_args.features = features.map(|v| v.join(","));

// TODO: determine which (one) binary to build
// TODO: have the above be configurable in CLI and Shuttle.toml

deployment_req_buildarch_beta.build_args = Some(build_args);

// TODO: have all of the above be configurable in CLI and Shuttle.toml
}

if let Ok(repo) = Repository::discover(working_directory) {
Expand Down Expand Up @@ -2106,7 +2129,8 @@ impl Shuttle {
let resources = client
.get_service_resources(self.ctx.project_name())
.await?;
let resources = get_resource_tables(&resources, self.ctx.project_name(), false, false);
let resources =
get_resource_tables(&resources, self.ctx.project_name(), false, false, self.beta);

println!("{resources}{service}");

Expand Down
67 changes: 66 additions & 1 deletion common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ impl AsRef<str> for ApiKey {
////// Resource Input/Output types

/// The input given to Shuttle DB resources
#[derive(Deserialize, Serialize, Default)]
#[derive(Clone, Deserialize, Serialize, Default)]
pub struct DbInput {
pub local_uri: Option<String>,
/// Override the default db name. Only applies to RDS.
Expand Down Expand Up @@ -172,6 +172,71 @@ impl DatabaseInfo {
}
}

/// Holds the data for building a database connection string on the Beta platform.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DatabaseInfoBeta {
engine: String,
role_name: String,
role_password: Secret<String>,
database_name: String,
port: String,
hostname: String,
/// The RDS instance name, which is required for deleting provisioned RDS instances, it's
/// optional because it isn't needed for shared PG deletion.
instance_name: Option<String>,
}

impl DatabaseInfoBeta {
pub fn new(
engine: String,
role_name: String,
role_password: String,
database_name: String,
port: String,
hostname: String,
instance_name: Option<String>,
) -> Self {
Self {
engine,
role_name,
role_password: Secret::new(role_password),
database_name,
port,
hostname,
instance_name,
}
}

/// For connecting to the database.
pub fn connection_string(&self, show_password: bool) -> String {
format!(
"{}://{}:{}@{}:{}/{}",
self.engine,
self.role_name,
if show_password {
self.role_password.expose()
} else {
self.role_password.redacted()
},
self.hostname,
self.port,
self.database_name,
)
}

pub fn role_name(&self) -> String {
self.role_name.to_string()
}

pub fn database_name(&self) -> String {
self.database_name.to_string()
}

pub fn instance_name(&self) -> Option<String> {
self.instance_name.clone()
}
}

/// Used to request a container from the local run provisioner
#[derive(Serialize, Deserialize)]
pub struct ContainerRequest {
Expand Down
6 changes: 1 addition & 5 deletions common/src/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,9 @@ pub struct LogItem {

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct LogItemBeta {
/// Time log was captured
pub timestamp: DateTime<Utc>,

/// Stdout/stderr
/// Which container / log stream this line came from
pub source: String,

/// The log line
pub line: String,
}

Expand Down
55 changes: 51 additions & 4 deletions common/src/models/deployment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ pub struct DeploymentRequest {
}

#[derive(Deserialize, Serialize)]
#[serde(untagged)]
#[serde(tag = "type", content = "content")]
pub enum DeploymentRequestBeta {
/// Build an image from the source code in an attached zip archive
BuildArchive(DeploymentRequestBuildArchiveBeta),
Expand All @@ -304,15 +304,62 @@ pub enum DeploymentRequestBeta {
pub struct DeploymentRequestBuildArchiveBeta {
/// The S3 object version ID of the archive to use
pub archive_version_id: String,
/// The cargo package name to compile and run.
pub package_name: String,
// TODO: Binary name, feature flags?, other cargo args?
pub build_args: Option<BuildArgsBeta>,
/// Secrets to add before this deployment.
/// TODO: Remove this in favour of a separate secrets uploading action.
pub secrets: Option<HashMap<String, String>>,
pub build_meta: Option<BuildMetaBeta>,
}

#[derive(Deserialize, Serialize)]
pub struct BuildArgsBeta {
/// Use the built in cargo chef setup for caching
pub cargo_chef: bool,
/// Build with the built in `cargo build` setup
pub cargo_build: bool,
/// The cargo package name to compile
pub package_name: Option<String>,
/// The cargo binary name to compile
pub binary_name: Option<String>,
/// comma-separated list of features to activate
pub features: Option<String>,
/// Passed on to `cargo build`
pub no_default_features: bool,
/// Use the mold linker
pub mold: bool,
}

impl Default for BuildArgsBeta {
fn default() -> Self {
Self {
cargo_chef: true,
cargo_build: true,
package_name: Default::default(),
binary_name: Default::default(),
features: Default::default(),
no_default_features: Default::default(),
mold: Default::default(),
}
}
}

impl BuildArgsBeta {
pub fn into_vars(&self) -> [(&str, &str); 7] {
[
("CARGO_CHEF", if self.cargo_chef { "true" } else { "" }),
("CARGO_BUILD", if self.cargo_build { "true" } else { "" }),
("PACKAGE", self.package_name.as_deref().unwrap_or_default()),
("BIN", self.binary_name.as_deref().unwrap_or_default()),
("FEATURES", self.features.as_deref().unwrap_or_default()),
(
"NO_DEFAULT_FEATURES",
if self.no_default_features { "true" } else { "" },
),
("MOLD", if self.mold { "true" } else { "" }),
]
}
}

#[derive(Default, Deserialize, Serialize)]
pub struct BuildMetaBeta {
pub git_commit_id: Option<String>,
Expand Down
66 changes: 58 additions & 8 deletions common/src/models/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,23 @@ use std::collections::HashMap;

use comfy_table::{
modifiers::UTF8_ROUND_CORNERS,
presets::{NOTHING, UTF8_FULL},
presets::{NOTHING, UTF8_BORDERS_ONLY, UTF8_FULL},
Attribute, Cell, CellAlignment, ContentArrangement, Table,
};
use crossterm::style::Stylize;

use crate::{
resource::{Response, Type},
secrets::SecretStore,
DatabaseResource,
DatabaseInfoBeta, DatabaseResource,
};

pub fn get_resource_tables(
resources: &[Response],
service_name: &str,
raw: bool,
show_secrets: bool,
beta: bool,
) -> String {
if resources.is_empty() {
if raw {
Expand All @@ -44,12 +45,21 @@ pub fn get_resource_tables(
let mut output = Vec::new();

if let Some(databases) = resource_groups.get("Databases") {
output.push(get_databases_table(
databases,
service_name,
raw,
show_secrets,
));
if beta {
output.push(get_databases_table_beta(
databases,
service_name,
raw,
show_secrets,
));
} else {
output.push(get_databases_table(
databases,
service_name,
raw,
show_secrets,
));
}
};

if let Some(secrets) = resource_groups.get("Secrets") {
Expand Down Expand Up @@ -137,6 +147,46 @@ fn get_databases_table(
format!("These databases are linked to {service_name}\n{table}\n{show_secret_hint}")
}

fn get_databases_table_beta(
databases: &Vec<&Response>,
service_name: &str,
raw: bool,
show_secrets: bool,
) -> String {
let mut table = Table::new();

if raw {
table
.load_preset(NOTHING)
.set_content_arrangement(ContentArrangement::Disabled)
.set_header(vec![
Cell::new("Type").set_alignment(CellAlignment::Left),
Cell::new("Connection string").set_alignment(CellAlignment::Left),
]);
} else {
table
.load_preset(UTF8_BORDERS_ONLY)
.set_content_arrangement(ContentArrangement::Disabled)
.set_header(vec![Cell::new("Type"), Cell::new("Connection string")]);
}

for database in databases {
let connection_string = serde_json::from_value::<DatabaseInfoBeta>(database.data.clone())
.expect("resource data to be a valid database")
.connection_string(show_secrets);

table.add_row(vec![database.r#type.to_string(), connection_string]);
}

let show_secret_hint = if databases.is_empty() || show_secrets {
""
} else {
"Hint: you can show the secrets of these resources using `cargo shuttle resource list --show-secrets`\n"
};

format!("These databases are linked to {service_name}\n{table}\n{show_secret_hint}")
}

fn get_secrets_table(secrets: &[&Response], service_name: &str, raw: bool) -> String {
let mut table = Table::new();

Expand Down
1 change: 1 addition & 0 deletions common/src/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ pub enum ResourceState {
Failed,
Ready,
Deleting,
Deleted,
}

/// Returned when provisioning a Shuttle resource
Expand Down
2 changes: 1 addition & 1 deletion runtime/src/alpha.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ where
// it has sent a load response, so that the ECS task will fail.
tokio::spawn(async move {
// Note: The timeout is quite long since RDS can take a long time to provision.
tokio::time::sleep(Duration::from_secs(180)).await;
tokio::time::sleep(Duration::from_secs(270)).await;
if !matches!(state.lock().unwrap().deref(), State::Running) {
println!("the runtime failed to enter the running state before timing out");

Expand Down

0 comments on commit 716e4ce

Please sign in to comment.