From 72827d616bede3dfb2d7944480e69330d4fc665a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9ophile=20Choutri?= Date: Thu, 22 Sep 2022 15:30:04 +0200 Subject: [PATCH] Simplify the db connstring configuration (#213) --- .github/workflows/backend.yml | 7 +++--- CHANGELOG.md | 1 + Makefile | 4 ++-- database.env | 2 +- environment.ci.sh | 5 ++--- environment.sh | 7 ++++-- environment.test.sh | 4 +++- src/Flora/Environment.hs | 31 ++++++++------------------- src/Flora/Environment/Config.hs | 38 +++++++++++++++++++-------------- 9 files changed, 49 insertions(+), 50 deletions(-) diff --git a/.github/workflows/backend.yml b/.github/workflows/backend.yml index 478722ce..68667101 100644 --- a/.github/workflows/backend.yml +++ b/.github/workflows/backend.yml @@ -63,10 +63,11 @@ jobs: cabal install postgresql-migration - name: Test run: | - source environment.ci.sh + set -x + source ./environment.ci.sh createdb -h "${FLORA_DB_HOST}" -p "${FLORA_DB_PORT}" -U "${FLORA_DB_USER}" -w "${FLORA_DB_DATABASE}" - migrate init "${FLORA_PG_CONNSTRING}" - migrate migrate "${FLORA_PG_CONNSTRING}" migrations + migrate init "${FLORA_DB_CONNSTRING}" + migrate migrate "${FLORA_DB_CONNSTRING}" migrations cabal run -- flora-cli create-user --username "hackage-user" --email "tech@flora.pm" --password "foobar2000" cabal test env: diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f2a2fd7..28216c51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Remove padding from README code paragraphs (#203) * Simplify the database pool settings (#210) * Readjust the size of the main title across browser sizes (#211) +* Take the database settings as a libpq connstring (#213) ## v1.0.2 -- 2022-09-13 diff --git a/Makefile b/Makefile index 8a43ead4..58cd2336 100644 --- a/Makefile +++ b/Makefile @@ -27,8 +27,8 @@ db-drop: ## Drop the database @dropdb -f --if-exists -h $(FLORA_DB_HOST) -p $(FLORA_DB_PORT) -U $(FLORA_DB_USER) $(FLORA_DB_DATABASE) db-setup: db-create ## Setup the dev database - @migrate init "$(FLORA_PG_CONNSTRING)" - @migrate migrate "$(FLORA_PG_CONNSTRING)" migrations + @migrate init "$(FLORA_DB_CONNSTRING)" + @migrate migrate "$(FLORA_DB_CONNSTRING)" migrations db-reset: db-drop db-setup db-provision ## Reset the dev database (uses Cabal) diff --git a/database.env b/database.env index 38a6d2f6..79a82dc0 100644 --- a/database.env +++ b/database.env @@ -1,3 +1,3 @@ POSTGRES_USER="postgres" POSTGRES_PASSWORD="postgres" -POSTGRES_DB="flora_dev" \ No newline at end of file +POSTGRES_DB="flora_dev" diff --git a/environment.ci.sh b/environment.ci.sh index a068d59a..d98aa5f8 100755 --- a/environment.ci.sh +++ b/environment.ci.sh @@ -5,11 +5,10 @@ export FLORA_DB_PASSWORD="postgres" export FLORA_DB_POOL_CONNECTIONS=20 export FLORA_DB_PORT=5432 export FLORA_DB_HOST="localhost" -export FLORA_DB_SUB_POOLS=10 export FLORA_DB_TIMEOUT=10 export FLORA_DB_USER="postgres" export FLORA_LOGGING_DESTINATION="stdout" export FLORA_HTTP_PORT=8083 -export FLORA_PG_URI="postgresql://${FLORA_DB_USER}:${FLORA_DB_PASSWORD}@${FLORA_DB_HOST}:${FLORA_DB_PORT}/${FLORA_DB_DATABASE}" -export FLORA_PG_CONNSTRING="host=${FLORA_DB_HOST} dbname=${FLORA_DB_DATABASE} user=${FLORA_DB_USER} password=${FLORA_DB_PASSWORD}" +export FLORA_DB_CONNSTRING="host=${FLORA_DB_HOST} dbname=${FLORA_DB_DATABASE}\ + user=${FLORA_DB_USER} password=${FLORA_DB_PASSWORD}" diff --git a/environment.sh b/environment.sh index 2dd12bc3..55b42f3a 100755 --- a/environment.sh +++ b/environment.sh @@ -8,9 +8,12 @@ export FLORA_DB_PASSWORD="postgres" export FLORA_DB_DATABASE="flora_dev" export FLORA_DB_POOL_CONNECTIONS="100" export FLORA_DB_TIMEOUT="10" +export FLORA_DB_SSLMODE="allow" +export FLORA_DB_PARAMETERS="?sslmode=verify-ca" -export FLORA_PG_URI="postgresql://${FLORA_DB_USER}:${FLORA_DB_PASSWORD}@${FLORA_DB_HOST}:${FLORA_DB_PORT}/${FLORA_DB_DATABASE}" -export FLORA_PG_CONNSTRING="host=${FLORA_DB_HOST} dbname=${FLORA_DB_DATABASE} user=${FLORA_DB_USER} password=${FLORA_DB_PASSWORD}" +export FLORA_DB_CONNSTRING="host=${FLORA_DB_HOST} dbname=${FLORA_DB_DATABASE} \ + user=${FLORA_DB_USER} password=${FLORA_DB_PASSWORD} \ + sslmode=${FLORA_DB_SSLMODE:-allow}" export FLORA_HTTP_PORT=8083 export FLORA_ENVIRONMENT="development" diff --git a/environment.test.sh b/environment.test.sh index d19dbe21..06b73b9e 100755 --- a/environment.test.sh +++ b/environment.test.sh @@ -6,4 +6,6 @@ export FLORA_DOMAIN="localhost" export FLORA_DB_DATABASE="flora_test" -export FLORA_PG_CONNSTRING="host=${FLORA_DB_HOST} dbname=${FLORA_DB_DATABASE} user=${FLORA_DB_USER} password=${FLORA_DB_PASSWORD}" +export FLORA_DB_CONNSTRING="host=${FLORA_DB_HOST} dbname=${FLORA_DB_DATABASE} \ + user=${FLORA_DB_USER} password=${FLORA_DB_PASSWORD} \ + sslmode=allow" diff --git a/src/Flora/Environment.hs b/src/Flora/Environment.hs index 311f9413..5a0f3b7b 100644 --- a/src/Flora/Environment.hs +++ b/src/Flora/Environment.hs @@ -11,10 +11,11 @@ module Flora.Environment where import Colourista.IO (blueMessage) +import Data.ByteString (ByteString) import Data.Pool (Pool) import Data.Pool qualified as Pool import Data.Text -import Data.Text qualified as T +import Data.Text.Encoding qualified as Text import Data.Time (NominalDiffTime) import Data.Word (Word16) import Database.PostgreSQL.Simple qualified as PG @@ -44,15 +45,15 @@ data TestEnv = TestEnv deriving stock (Generic) mkPool - :: PG.ConnectInfo -- Database access information + :: ByteString -- Database access information -> NominalDiffTime -- Allowed timeout -> Int -- Number of connections -> Eff '[IOE] (Pool PG.Connection) -mkPool connectInfo timeout' connections = +mkPool connectionInfo timeout' connections = liftIO $ Pool.newPool $ Pool.PoolConfig - { createResource = PG.connect connectInfo + { createResource = PG.connectPostgreSQL connectionInfo , freeResource = PG.close , poolCacheTTL = realToFrac timeout' , poolMaxResources = connections @@ -61,8 +62,8 @@ mkPool connectInfo timeout' connections = configToEnv :: FloraConfig -> Eff '[IOE] FloraEnv configToEnv x@FloraConfig{..} = do let PoolConfig{..} = dbConfig - pool <- mkPool connectInfo connectionTimeout connections - jobsPool <- mkPool connectInfo connectionTimeout connections + pool <- mkPool connectionInfo connectionTimeout connections + jobsPool <- mkPool connectionInfo connectionTimeout connections pure FloraEnv{..} where config = x @@ -70,27 +71,13 @@ configToEnv x@FloraConfig{..} = do testConfigToTestEnv :: TestConfig -> Eff '[IOE] TestEnv testConfigToTestEnv config@TestConfig{..} = do let PoolConfig{..} = config.dbConfig - pool <- mkPool connectInfo connectionTimeout connections + pool <- mkPool connectionInfo connectionTimeout connections pure TestEnv{..} -displayConnectInfo :: PG.ConnectInfo -> Text -displayConnectInfo PG.ConnectInfo{..} = - T.pack $ - "postgresql://" - <> connectUser - <> ":" - <> connectPassword - <> "@" - <> connectHost - <> ":" - <> show connectPort - <> "/" - <> connectDatabase - getFloraEnv :: Eff '[IOE] FloraEnv getFloraEnv = do config <- liftIO $ Env.parse id parseConfig - liftIO $ blueMessage $ "🔌 Connecting to database at " <> displayConnectInfo (config.connectInfo) + liftIO $ blueMessage $ "🔌 Connecting to database at " <> Text.decodeUtf8 config.connectionInfo configToEnv config getFloraTestEnv :: Eff '[IOE] TestEnv diff --git a/src/Flora/Environment/Config.hs b/src/Flora/Environment/Config.hs index f75354df..02630e91 100644 --- a/src/Flora/Environment/Config.hs +++ b/src/Flora/Environment/Config.hs @@ -1,9 +1,8 @@ -{-# OPTIONS_GHC -Wno-orphans #-} - -- | Externally facing config parsed from the environment. module Flora.Environment.Config ( FloraConfig (..) , LoggingEnv (..) + , ConnectionInfo (..) , TestConfig (..) , PoolConfig (..) , DeploymentEnv (..) @@ -15,10 +14,12 @@ where import Control.Monad ((>=>)) import Data.Bifunctor +import Data.ByteString (ByteString) import Data.Pool (Pool) -import Data.Text +import Data.Text (Text) import Data.Text.Display (Display (..)) import Data.Time (NominalDiffTime) +import Data.Typeable import Data.Word (Word16) import Database.PostgreSQL.Simple qualified as PG import Env @@ -37,6 +38,16 @@ import Env import GHC.Generics import Text.Read (readMaybe) +data ConnectionInfo = ConnectionInfo + { connectHost :: Text + , connectPort :: Word16 + , connectUser :: Text + , connectPassword :: Text + , connectDatabase :: Text + , sslMode :: Text + } + deriving (Generic, Eq, Read, Show, Typeable) + data DeploymentEnv = Production | Development @@ -67,7 +78,7 @@ data LoggingEnv = LoggingEnv -- | The datatype that is used to model the external configuration data FloraConfig = FloraConfig { dbConfig :: PoolConfig - , connectInfo :: PG.ConnectInfo + , connectionInfo :: ByteString , domain :: Text , httpPort :: Word16 , logging :: LoggingEnv @@ -84,7 +95,7 @@ data PoolConfig = PoolConfig data TestConfig = TestConfig { httpPort :: Word16 , dbConfig :: PoolConfig - , connectInfo :: PG.ConnectInfo + , connectionInfo :: ByteString } deriving stock (Generic) @@ -94,14 +105,9 @@ data TestEnv = TestEnv } deriving stock (Generic) -parseConnectInfo :: Parser Error PG.ConnectInfo -parseConnectInfo = - PG.ConnectInfo - <$> var str "FLORA_DB_HOST" (help "PostgreSQL host") - <*> var port "FLORA_DB_PORT" (help "PostgreSQL port") - <*> var str "FLORA_DB_USER" (help "PostgreSQL user") - <*> var str "FLORA_DB_PASSWORD" (help "PostgreSQL password") - <*> var str "FLORA_DB_DATABASE" (help "Control-Plane database") +parseConnectionInfo :: Parser Error ByteString +parseConnectionInfo = + var str "FLORA_DB_CONNSTRING" (help "libpq-compatible connection string") parsePoolConfig :: Parser Error PoolConfig parsePoolConfig = @@ -127,13 +133,13 @@ parseDomain = var str "FLORA_DOMAIN" (help "URL domain for Flora") parseDeploymentEnv :: Parser Error DeploymentEnv parseDeploymentEnv = - var deploymentEnv "FLORA_ENVIRONMENT" (help "Name of the current environment (production, development)") + var deploymentEnv "FLORA_ENVIRONMENT" (help "Name of the current environment (production, development, test)") parseConfig :: Parser Error FloraConfig parseConfig = FloraConfig <$> parsePoolConfig - <*> parseConnectInfo + <*> parseConnectionInfo <*> parseDomain <*> parsePort <*> parseLoggingEnv @@ -144,7 +150,7 @@ parseTestConfig = TestConfig <$> parsePort <*> parsePoolConfig - <*> parseConnectInfo + <*> parseConnectionInfo -- Env parser helpers