Skip to content

Commit

Permalink
Made it so a database is actually used in digital ocean. Changed how …
Browse files Browse the repository at this point in the history
…options for db are acquired from configuration.
  • Loading branch information
nikthechampiongr committed Dec 10, 2023
1 parent 82455c0 commit 3f5cdc2
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 34 deletions.
12 changes: 12 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ chrono = "0.4.26"
config = "0.13.3"
reqwest = "0.11.18"
serde = {version = "1", features = ["std", "serde_derive"]}
serde-aux = "4"
sqlx = { version = "0.7.1", features = ["runtime-tokio", "tls-rustls", "postgres", "chrono", "uuid", "migrate"] }
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
uuid = {version ="1.4.1", features = ["v4", "fast-rng"]}
Expand Down
2 changes: 2 additions & 0 deletions configuration/local.yaml
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
application:
host: "127.0.0.1"
database:
require_ssl: false
2 changes: 2 additions & 0 deletions configuration/production.yaml
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
application:
host: 0.0.0.0
database:
require_ssl: true
20 changes: 16 additions & 4 deletions spec.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
# I am not even sure why I have this, digitalocean just fails with a cryptic
# error message on some file it could not find, does not tell me what it is, and
# half the lines of the logs are completely broken. I guess I won't lose any
# money.
name: zero2prod
region: fra1
services:
Expand All @@ -19,6 +15,22 @@ services:
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
Expand Down
51 changes: 32 additions & 19 deletions src/configuration.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
use std::convert::TryFrom;

use secrecy::{ExposeSecret, Secret};
use serde_aux::field_attributes::deserialize_number_from_string;
use sqlx::{
postgres::{PgConnectOptions, PgSslMode},
ConnectOptions,
};
use std::convert::TryFrom;

#[derive(serde::Deserialize)]
pub struct Settings {
Expand All @@ -18,30 +22,32 @@ pub struct ApplicationSettings {
pub struct DatabaseSettings {
pub username: String,
pub password: Secret<String>,
#[serde(deserialize_with = "deserialize_number_from_string")]
pub port: u16,
pub host: String,
pub database_name: String,
pub require_ssl: bool,
}

impl DatabaseSettings {
pub fn connection_string(&self) -> Secret<String> {
Secret::new(format!(
"postgres://{}:{}@{}:{}/{}",
self.username,
self.password.expose_secret(),
self.host,
self.port,
self.database_name
))
pub fn with_db(&self) -> PgConnectOptions {
self.without_db()
.database(&self.database_name)
.log_statements(tracing_log::log::LevelFilter::Trace)
}
pub fn connection_string_without_db(&self) -> Secret<String> {
Secret::new(format!(
"postgres://{}:{}@{}:{}",
self.username,
self.password.expose_secret(),
self.host,
self.port
))
pub fn without_db(&self) -> PgConnectOptions {
let ssl_mode = if self.require_ssl {
PgSslMode::Require
} else {
//Try encrypted connected but fall back if unavailable.
PgSslMode::Prefer
};
PgConnectOptions::new()
.host(&self.host)
.username(&self.username)
.password(self.password.expose_secret())
.port(self.port)
.ssl_mode(ssl_mode)
}
}

Expand Down Expand Up @@ -93,6 +99,13 @@ pub fn get_configuration() -> Result<Settings, config::ConfigError> {
.add_source(config::File::from(
configuration_directory.join(env.as_str()),
))
.add_source(
// This will match things like: APP_APPLICATION__PORT=5001 which is
// Settings.application.port
config::Environment::with_prefix("APP")
.prefix_separator("_")
.separator("__"),
)
.build()?;

settings.try_deserialize::<Settings>()
Expand Down
4 changes: 1 addition & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use secrecy::ExposeSecret;
use sqlx::postgres::PgPoolOptions;
use zero2prod::{configuration::get_configuration, startup::run, telemetry::*};

Expand All @@ -14,8 +13,7 @@ async fn main() -> Result<(), std::io::Error> {
);
let db_pool = PgPoolOptions::new()
.idle_timeout(std::time::Duration::from_secs(2))
.connect_lazy(configuration.database.connection_string().expose_secret())
.expect("Failed to create database connection");
.connect_lazy_with(configuration.database.with_db());
run(
std::net::TcpListener::bind(address).expect("Failed to bind to port"),
db_pool,
Expand Down
13 changes: 5 additions & 8 deletions tests/api/check_health.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use std::sync::OnceLock;

use secrecy::ExposeSecret;
use sqlx::{Connection, Executor};
use std::sync::OnceLock;
use zero2prod::{
configuration::{get_configuration, DatabaseSettings},
startup::run,
Expand Down Expand Up @@ -56,17 +54,16 @@ pub async fn spawn_app() -> TestApp {
}

async fn configure_database(config: &DatabaseSettings) -> sqlx::PgPool {
let mut connection =
sqlx::PgConnection::connect(&config.connection_string_without_db().expose_secret())
.await
.expect("Failed to connect to postgres instance");
let mut connection = sqlx::PgConnection::connect_with(&config.without_db())
.await
.expect("Failed to connect to postgres instance");

connection
.execute(format!(r#"CREATE DATABASE "{}""#, config.database_name,).as_str())
.await
.expect("Failed to create new database");

let db_pool = sqlx::PgPool::connect(&config.connection_string().expose_secret())
let db_pool = sqlx::PgPool::connect_with(config.with_db())
.await
.expect("Failed to connect to database");
sqlx::migrate!("./migrations")
Expand Down

0 comments on commit 3f5cdc2

Please sign in to comment.