Digital Ocean Deployment

This commit is contained in:
Nick Bland 2022-01-03 17:11:11 +10:00
parent 6741ed9e14
commit bfcaa6f487
No known key found for this signature in database
GPG Key ID: B46CF88E4DAB4A2C
8 changed files with 87 additions and 19 deletions

13
Cargo.lock generated
View File

@ -985,9 +985,11 @@ dependencies = [
"actix-web", "actix-web",
"chrono", "chrono",
"config", "config",
"log",
"once_cell", "once_cell",
"reqwest", "reqwest",
"serde 1.0.130", "serde 1.0.130",
"serde-aux",
"sqlx", "sqlx",
"tokio", "tokio",
"tracing", "tracing",
@ -1605,6 +1607,17 @@ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]]
name = "serde-aux"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93abf9799c576f004252b2a05168d58527fb7c54de12e94b4d12fe3475ffad24"
dependencies = [
"chrono",
"serde 1.0.130",
"serde_json",
]
[[package]] [[package]]
name = "serde-hjson" name = "serde-hjson"
version = "0.9.1" version = "0.9.1"

View File

@ -19,6 +19,8 @@ tracing-subscriber = { version = "0.2.12", features = ["registry", "env-filter"]
tracing-bunyan-formatter = "0.1.6" tracing-bunyan-formatter = "0.1.6"
tracing-log = "0.1.1" tracing-log = "0.1.1"
tracing-actix-web = "0.4.0-beta.12" tracing-actix-web = "0.4.0-beta.12"
serde-aux = "3.0.1"
log = "0.4"
[dependencies.sqlx] [dependencies.sqlx]
version = "0.5.7" version = "0.5.7"

View File

@ -1,2 +1,4 @@
application: application:
host: 127.0.0.1 host: 127.0.0.1
database:
require_ssl: false

View File

@ -1,2 +1,4 @@
application: application:
host: 0.0.0.0 host: 0.0.0.0
database:
require_ssl: true

41
spec.yaml Normal file
View File

@ -0,0 +1,41 @@
#! spec.yaml
name: rust-project
region: sgp1
services:
- name: rust-project
dockerfile_path: Dockerfile
source_dir: .
github:
repo: NickBland/mailApp
branch: master
deploy_on_push: true
health_check:
http_path: /health_check
http_port: 8000
instance_count: 1
instance_size_slug: basic-xxs
routes:
- path: /
envs:
- key: APP_DATABASE__USERNAME
scope: RUN_TIME
value: ${newsletter.USERNAME}
- key: APP_DATABASE__PASSWORD
scope: RUN_TIME
value: ${newsletter.PASSWORD}
- key: APP_DATABASE__HOST
scope: RUN_TIME
value: ${newsletter.HOSTNAME}
- key: APP_DATABASE__PORT
scope: RUN_TIME
value: ${newsletter.PORT}
- key: APP_DATABASE__DATABASE_NAME
scope: RUN_TIME
value: ${newsletter.DATABASE}
databases:
- engine: PG
name: newsletter
num_nodes: 1
size: deb-s-dev-database
version: "12"

View File

@ -1,5 +1,8 @@
use std::convert::{TryFrom, TryInto}; use std::convert::{TryFrom, TryInto};
use serde_aux::field_attributes::deserialize_number_from_string;
use sqlx::postgres::{PgConnectOptions, PgSslMode};
#[derive(serde::Deserialize)] #[derive(serde::Deserialize)]
pub struct Settings { pub struct Settings {
pub database: DatabaseSettings, pub database: DatabaseSettings,
@ -8,6 +11,7 @@ pub struct Settings {
#[derive(serde::Deserialize)] #[derive(serde::Deserialize)]
pub struct ApplicationSettings { pub struct ApplicationSettings {
#[serde(deserialize_with = "deserialize_number_from_string")]
pub port: u16, pub port: u16,
pub host: String, pub host: String,
} }
@ -16,9 +20,11 @@ pub struct ApplicationSettings {
pub struct DatabaseSettings { pub struct DatabaseSettings {
pub username: String, pub username: String,
pub password: String, pub password: String,
#[serde(deserialize_with = "deserialize_number_from_string")]
pub port: u16, pub port: u16,
pub host: String, pub host: String,
pub database_name: String, pub database_name: String,
pub require_ssl: bool,
} }
pub fn get_configuration() -> Result<Settings, config::ConfigError> { pub fn get_configuration() -> Result<Settings, config::ConfigError> {
@ -36,7 +42,7 @@ pub fn get_configuration() -> Result<Settings, config::ConfigError> {
.expect("Failed to parse APP_ENVIRONMENT."); .expect("Failed to parse APP_ENVIRONMENT.");
settings.merge( settings.merge(
config::File::from(configuration_directory.join(environment.as_str())).required(true) config::File::from(configuration_directory.join(environment.as_str())).required(true),
)?; )?;
settings.merge(config::Environment::with_prefix("app").separator("__"))?; settings.merge(config::Environment::with_prefix("app").separator("__"))?;
@ -74,17 +80,21 @@ impl TryFrom<String> for Environment {
} }
impl DatabaseSettings { impl DatabaseSettings {
pub fn connection_string(&self) -> String { pub fn without_db(&self) -> PgConnectOptions {
format!( let ssl_mode = if self.require_ssl {
"postgres://{}:{}@{}:{}/{}", PgSslMode::Require
self.username, self.password, self.host, self.port, self.database_name } else {
) PgSslMode::Prefer
};
PgConnectOptions::new()
.host(&self.host)
.username(&self.username)
.password(&self.password)
.port(self.port)
.ssl_mode(ssl_mode)
} }
pub fn connection_string_without_db(&self) -> String { pub fn with_db(&self) -> PgConnectOptions {
format!( self.without_db().database(&self.database_name).log_statements(log::LevelFilter::Trace)
"postgres://{}:{}@{}:{}",
self.username, self.password, self.host, self.port
)
} }
} }

View File

@ -16,9 +16,7 @@ async fn main() -> std::io::Result<()> {
// Configure connection to database for our startup // Configure connection to database for our startup
let connection_pool = PgPoolOptions::new() let connection_pool = PgPoolOptions::new()
.connect_timeout(std::time::Duration::from_secs(2)) .connect_timeout(std::time::Duration::from_secs(2))
.connect(&configuration.database.connection_string()) .connect_lazy_with(configuration.database.with_db());
.await
.expect("Failed to connect to Postgres.");
// Take port from settings file // Take port from settings file
let address = format!("{}:{}", configuration.application.host, configuration.application.port); let address = format!("{}:{}", configuration.application.host, configuration.application.port);

View File

@ -49,16 +49,16 @@ async fn spawn_app() -> TestApp {
pub async fn configure_database(config: &DatabaseSettings) -> PgPool { pub async fn configure_database(config: &DatabaseSettings) -> PgPool {
// Create database // Create database
let mut connection = PgConnection::connect(&config.connection_string_without_db()) let mut connection = PgConnection::connect(&config.without_db())
.await .await
.expect("Failed to connect to Postgres"); .expect("Failed to connect to Postgres");
connection connection
.execute(&*format!(r#"CREATE DATABASE "{}";"#, config.database_name)) .execute(&*format!(r#"CREATE DATABASE "{}";"#, config.database_name).as_str())
.await .await
.expect("Failed to create database."); .expect("Failed to create database.");
// Migrate database // Migrate database
let connection_pool = PgPool::connect(&config.connection_string()) let connection_pool = PgPool::connect(config.with_db())
.await .await
.expect("Failed to connect to Postgres."); .expect("Failed to connect to Postgres.");
sqlx::migrate!("./migrations") sqlx::migrate!("./migrations")