From 1e2fd39838d703d83ec8e1ff48c2c8da7101c1e8 Mon Sep 17 00:00:00 2001 From: Joe Nelson Date: Wed, 24 May 2017 22:50:09 -0500 Subject: [PATCH] Use env interpolation in config (#826) --- CHANGELOG.md | 3 ++ docker/Dockerfile | 15 ++++++++++ docker/docker-compose.yml | 8 +++-- docker/postgrest.conf | 14 +++++++++ postgrest.cabal | 2 +- src/PostgREST/Config.hs | 63 ++++++++++++++++++++------------------- stack.yaml | 2 ++ 7 files changed, 72 insertions(+), 35 deletions(-) create mode 100644 docker/postgrest.conf diff --git a/CHANGELOG.md b/CHANGELOG.md index 36618a34fd6..3f9b104a16a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,9 +9,12 @@ This project adheres to [Semantic Versioning](http://semver.org/). - #742, Add connection retrying on startup and SIGHUP - @steve-chavez - #652, Add and/or params for complex boolean logic - @steve-chavez +- #808, Env var interpolation in config file (helps Docker) - @begriffs ### Fixed +- #822, Treat blank string JWT secret as no secret - @begriffs + ## [0.4.1.0] - 2017-04-25 ### Added diff --git a/docker/Dockerfile b/docker/Dockerfile index 8e526c890a6..e86e32f541a 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -11,6 +11,21 @@ RUN wget http://github.com/begriffs/postgrest/releases/download/v${POSTGREST_VER mv postgrest /usr/local/bin/postgrest && \ rm postgrest-${POSTGREST_VERSION}-ubuntu.tar.xz +COPY postgrest.conf /etc/postgrest.conf + + +ENV PGRST_DB_URI= \ + PGRST_DB_SCHEMA=public \ + PGRST_DB_ANON_ROLE= \ + PGRST_DB_POOL=100 \ + PGRST_SERVER_HOST=*4 \ + PGRST_SERVER_PORT=3000 \ + PGRST_SERVER_PROXY_URL= \ + PGRST_JWT_SECRET= \ + PGRST_SECRET_IS_BASE64=false \ + PGRST_MAX_ROWS= \ + PGRST_PRE_REQUEST= + # PostgREST reads /etc/postgrest.conf so map the configuration # file in when you run this container CMD exec postgrest /etc/postgrest.conf diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index a1b47027cb7..46b5b9d55fa 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -1,11 +1,13 @@ stgrest: - image: begriffs/postgrest:latest + image: pg_local ports: - "3000:3000" - volumes: - - ./config.conf:/etc/postgrest.conf links: - postgres:postgres + environment: + PGRST_DB_URI: postgres://app_user:password@postgres:5432/app_db + PGRST_DB_SCHEMA: public + PGRST_DB_ANON_ROLE: app_user postgres: image: postgres diff --git a/docker/postgrest.conf b/docker/postgrest.conf new file mode 100644 index 00000000000..03db461d9f2 --- /dev/null +++ b/docker/postgrest.conf @@ -0,0 +1,14 @@ +db-uri = "$(PGRST_DB_URI)" +db-schema = "$(PGRST_DB_SCHEMA)" +db-anon-role = "$(PGRST_DB_ANON_ROLE)" +db-pool = "$(PGRST_DB_POOL)" + +server-host = "$(PGRST_SERVER_HOST)" +server-port = "$(PGRST_SERVER_PORT)" + +server-proxy-url = "$(PGRST_SERVER_PROXY_URL)" +jwt-secret = "$(PGRST_JWT_SECRET)" +secret-is-base64 = "$(PGRST_SECRET_IS_BASE64)" + +max-rows = "$(PGRST_MAX_ROWS)" +pre-request = "$(PGRST_PRE_REQUEST)" diff --git a/postgrest.cabal b/postgrest.cabal index b8766d5289b..d1553045b9d 100644 --- a/postgrest.cabal +++ b/postgrest.cabal @@ -55,7 +55,7 @@ library , bytestring , case-insensitive , cassava - , configurator + , configurator-ng == 0.0.0.1 , containers , contravariant , either diff --git a/src/PostgREST/Config.hs b/src/PostgREST/Config.hs index a9666f6408c..13514c6873c 100644 --- a/src/PostgREST/Config.hs +++ b/src/PostgREST/Config.hs @@ -1,3 +1,4 @@ +{-# OPTIONS_GHC -fno-warn-type-defaults #-} {-| Module : PostgREST.Config Description : Manages PostgREST configuration options. @@ -27,9 +28,11 @@ import qualified Data.ByteString as B import qualified Data.ByteString.Char8 as BS import qualified Data.CaseInsensitive as CI import qualified Data.Configurator as C -import qualified Data.Configurator.Types as C +import qualified Data.Configurator.Parser as C +import Data.Configurator.Types (Value(..)) import Data.List (lookup) import Data.Monoid +import Data.Scientific (floatingOrInteger) import Data.Text (strip, intercalate, lines) import Data.Text.Encoding (encodeUtf8) import Data.Text.IO (hPutStrLn) @@ -38,6 +41,7 @@ import Network.Wai import Network.Wai.Middleware.Cors (CorsResourcePolicy (..)) import Options.Applicative hiding (str) import Paths_postgrest (version) +import System.IO (hPrint) import Text.Heredoc import Text.PrettyPrint.ANSI.Leijen hiding ((<>), (<$>)) import qualified Text.PrettyPrint.ANSI.Leijen as L @@ -95,30 +99,37 @@ readOptions = do cfgPath <- customExecParser parserPrefs opts -- Now read the actual config file conf <- catch - (C.load [C.Required cfgPath]) + (C.readConfig =<< C.load [C.Required cfgPath]) configNotfoundHint - handle missingKeyHint $ do - -- db ---------------- - cDbUri <- C.require conf "db-uri" - cDbSchema <- C.require conf "db-schema" - cDbAnon <- C.require conf "db-anon-role" - cPool <- C.lookupDefault 10 conf "db-pool" - -- server ------------ - cHost <- C.lookupDefault "*4" conf "server-host" - cPort <- C.lookupDefault 3000 conf "server-port" - cProxy <- C.lookup conf "server-proxy-uri" - -- jwt --------------- - cJwtSec <- C.lookup conf "jwt-secret" - cJwtB64 <- C.lookupDefault False conf "secret-is-base64" - -- safety ------------ - cMaxRows <- C.lookup conf "max-rows" - cReqCheck <- C.lookup conf "pre-request" - - return $ AppConfig cDbUri cDbAnon cProxy cDbSchema cHost cPort - (encodeUtf8 <$> cJwtSec) cJwtB64 cPool cMaxRows cReqCheck False + let (mAppConf, errs) = flip C.runParserA conf $ + AppConfig <$> + C.key "db-uri" + <*> C.key "db-anon-role" + <*> C.key "server-proxy-uri" + <*> C.key "db-schema" + <*> (fromMaybe "*4" <$> C.key "server-host") + <*> (fromMaybe 3000 . join . fmap coerceInt <$> C.key "server-port") + <*> (fmap encodeUtf8 . mfilter (/= "") <$> C.key "jwt-secret") + <*> (fromMaybe False <$> C.key "secret-is-base64") + <*> (fromMaybe 10 . join . fmap coerceInt <$> C.key "db-pool") + <*> (join . fmap coerceInt <$> C.key "max-rows") + <*> C.key "pre-request" + <*> pure False + + case mAppConf of + Nothing -> do + forM_ errs $ hPrint stderr + exitFailure + Just appConf -> + return appConf where + coerceInt :: (Read i, Integral i) => Value -> Maybe i + coerceInt (Number x) = rightToMaybe $ floatingOrInteger x + coerceInt (String x) = readMaybe $ toS x + coerceInt _ = Nothing + opts = info (helper <*> pathParser) $ fullDesc <> progDesc ( @@ -139,15 +150,6 @@ readOptions = do "Cannot open config file:\n\t" <> show e exitFailure - missingKeyHint :: C.KeyError -> IO a - missingKeyHint (C.KeyError n) = do - hPutStrLn stderr $ - "Required config parameter \"" <> n <> "\" is missing or of wrong type.\n" <> - "Documentation for configuration options available at\n" <> - "\thttp://postgrest.com/en/v0.4/admin.html#configuration\n\n" <> - "Try the --example-config option to see how to configure PostgREST." - exitFailure - exampleCfg :: Doc exampleCfg = vsep . map (text . toS) . lines $ [str|db-uri = "postgres://user:pass@localhost:5432/dbname" @@ -173,7 +175,6 @@ readOptions = do |# pre-request = "stored_proc_name" |] - pathParser :: Parser FilePath pathParser = strArgument $ diff --git a/stack.yaml b/stack.yaml index 818c3bc97f5..0596112d35e 100644 --- a/stack.yaml +++ b/stack.yaml @@ -2,6 +2,8 @@ resolver: lts-8.5 extra-deps: - Ranged-sets-0.3.0 - hasql-pool-0.4.1 + - configurator-ng-0.0.0.1 + - critbit-0.2.0.0 ghc-options: postgrest: -O2 -Werror -Wall -fwarn-identities -fno-warn-redundant-constraints nix: