Giter VIP home page Giter VIP logo

tmp-postgres's Introduction

Hackage Travis CI Status

tmp-postgres

tmp-postgres provides functions for creating a temporary postgres instance. By default it will create a temporary data directory and a temporary directory for a UNIX domain socket for postgres to listen on.

Here is an example using the exception-safe 'with' function:

with $ \db -> bracket
  (connectPostgreSQL (toConnectionString db))
  close $
  \conn -> execute_ conn "CREATE TABLE foo (id int)"

To extend or override the defaults use withConfig (or startConfig).

tmp-postgres ultimately calls initdb (optionally) , postgres and createdb (optionally).

All of the command line, environment variables and configuration files that are generated by default for the respective executables can be extended.

In general tmp-postgres is useful if you want a clean temporary postgres and do not want to worry about clashing with an existing postgres instance (or needing to ensure postgres is already running).

Here are some different use cases for tmp-postgres and their respective configurations:

  • The default 'with' and 'start' functions can be used to make a sandboxed temporary database for testing.
  • By disabling initdb one could run a temporary isolated postgres on a base backup to test a migration.
  • By using the 'stopPostgres' and 'withRestart' functions one can test backup strategies.

WARNING!! Ubuntu's PostgreSQL installation does not put initdb on the PATH. We need to add it manually. The necessary binaries are in the /usr/lib/postgresql/VERSION/bin/ directory, and should be added to the PATH

echo "export PATH=$PATH:/usr/lib/postgresql/VERSION/bin/" >> /home/ubuntu/.bashrc

Installation

macOS

$ brew install postgres
$ stack install tmp-postgres

Ubuntu

Ubuntu's PostgreSQL installation does not put initdb on the PATH. We need to add it manually.

$ sudo apt-get install postgresql-VERSION
$ echo "export PATH=$PATH:/usr/lib/postgresql/VERSION/bin/" >> /home/ubuntu/.bashrc
$ stack install tmp-postgres

GitHub Actions

Assuming you are using one of the standard workflow containers, simply add workflow steps which install postgresql as above. For example,

jobs:
  build:
    runs-on: ubuntu-18.04
    steps:
      - name: "Install postgresql"
        run: "sudo apt-get update && sudo apt-get install postgresql-10"

      # ...

      - name: "Run test"
        run: |
          export PATH=$PATH:/usr/lib/postgresql/10/bin
          stack test

tmp-postgres's People

Contributors

jfischoff avatar tebello-thejane avatar joshcough avatar tomjaguarpaw avatar georgefst avatar gambolingpangolin avatar mwotton avatar blaisorblade avatar samtay avatar

Stargazers

Kayla Firestack avatar Tim Miller avatar Larry Diehl avatar Anthony Alaribe avatar Eric Ahlberg avatar Mauricio Fierro avatar Leonhard Riedißer avatar  avatar Jan Hrcek avatar Florian Klein avatar Mohammad Hasani avatar Scott Fleischman avatar Josh Miller avatar Raimon Grau avatar Harry Gallagher avatar Nikita avatar Tristan de Cacqueray avatar  avatar  avatar Peter Kjeld Andersen avatar  avatar Ian Jeffries avatar Sergei Dolgov avatar Dmitry Ivanov avatar Javier Maldonado avatar Matt Parsons avatar Shinya Yamaguchi avatar Daniel Harvey avatar Veronika Romashkina avatar Siva avatar Johannes Grødem avatar Tarek Touati avatar Jezen Thomas avatar Vaibhav Sagar avatar Thomas Honeyman avatar Dmitrii Kovanikov avatar iko avatar Darin Minamoto avatar Cameron Samak avatar Patrick Mylund Nielsen avatar Olle Fredriksson avatar Adam Wespiser avatar  avatar Casey Allred avatar shrynx avatar Steven Shaw avatar Tyler Weir avatar John Children avatar Andrejs Agejevs avatar Patrick Cieplak avatar Ollie Charles avatar John Children avatar Daniel Kahlenberg avatar

Watchers

 avatar James Cloos avatar Mitchell Dalvi Rosen avatar  avatar  avatar  avatar Scott Fleischman avatar

tmp-postgres's Issues

README example wrong

The README gives the following as an example

result <- start []
case result of
  Left err -> print err
  Right tempDB -> do
     -- Do stuff
     stop tempDB

but it seems it should be more like

result <- start defaultOptions
case result of
  Left err -> print err >> pure Nothing
  ...

Test failures

On Stackage nightly. Full log

Database.Postgres.Temp.Internal
  Database.Postgres.Temp.Internal
    startWithLogger/stop
      deletes the temp dir and postgres on exception in InitDB
      deletes the temp dir and postgres on exception in WriteConfig FAILED [1]
      deletes the temp dir and postgres on exception in FreePort FAILED [2]
      deletes the temp dir and postgres on exception in StartPostgres FAILED [3]
      deletes the temp dir and postgres on exception in WaitForDB FAILED [4]
      deletes the temp dir and postgres on exception in CreateDB FAILED [5]
      deletes the temp dir and postgres on exception in Finished FAILED [6]
      creates a useful connection string and stop still cleans up FAILED [7]
      can override settings FAILED [8]

Failures:

  test/Database/Postgres/Temp/InternalSpec.hs:37: 
  1) Database.Postgres.Temp.Internal.Database.Postgres.Temp.Internal.startWithLogger/stop deletes the temp dir and postgres on exception in WriteConfi
g
       did not get expected exception: Except

  test/Database/Postgres/Temp/InternalSpec.hs:37: 
  2) Database.Postgres.Temp.Internal.Database.Postgres.Temp.Internal.startWithLogger/stop deletes the temp dir and postgres on exception in FreePort
       did not get expected exception: Except

  test/Database/Postgres/Temp/InternalSpec.hs:37: 
  3) Database.Postgres.Temp.Internal.Database.Postgres.Temp.Internal.startWithLogger/stop deletes the temp dir and postgres on exception in StartPostg
res
       did not get expected exception: Except

  test/Database/Postgres/Temp/InternalSpec.hs:37: 
  4) Database.Postgres.Temp.Internal.Database.Postgres.Temp.Internal.startWithLogger/stop deletes the temp dir and postgres on exception in WaitForDB
       did not get expected exception: Except

  test/Database/Postgres/Temp/InternalSpec.hs:37: 
  5) Database.Postgres.Temp.Internal.Database.Postgres.Temp.Internal.startWithLogger/stop deletes the temp dir and postgres on exception in CreateDB
       did not get expected exception: Except

  test/Database/Postgres/Temp/InternalSpec.hs:37: 
  6) Database.Postgres.Temp.Internal.Database.Postgres.Temp.Internal.startWithLogger/stop deletes the temp dir and postgres on exception in Finished
       did not get expected exception: Except

  test/Database/Postgres/Temp/InternalSpec.hs:43: 
  7) Database.Postgres.Temp.Internal.Database.Postgres.Temp.Internal.startWithLogger/stop creates a useful connection string and stop still cleans up
       uncaught exception: ErrorCall (InitDBFailed (ExitFailure 127)
       CallStack (from HasCallStack):
         error, called at test/Database/Postgres/Temp/InternalSpec.hs:50:27 in main:Database.Postgres.Temp.InternalSpec)

  test/Database/Postgres/Temp/InternalSpec.hs:58: 
  8) Database.Postgres.Temp.Internal.Database.Postgres.Temp.Internal.startWithLogger/stop can override settings
       uncaught exception: ErrorCall (InitDBFailed (ExitFailure 127)
       CallStack (from HasCallStack):
         error, called at test/Database/Postgres/Temp/InternalSpec.hs:64:29 in main:Database.Postgres.Temp.InternalSpec)

Randomized with seed 1122578657

Support faster db creation setup

Starting a whole process for a test is pretty time consuming. However creating a database, migrating it and using it as a template to start other tests is probably faster.

After we have benchmarks (#52) we can test this theory and if it is faster we should add some support for this workflow.

Add hint

This should run in CI and locally

Provide exe?

Hi,

If you are interested, can you provide this as an exe as well?

Thanks

Lenses for configuration

Having stock lenses for configuration might make mappending to defaultConfig easier.

So

defaultPostgresConf extra = defaultConfig <> mempty
  { configPlan = mempty
    { partialPlanConfig = extra
    }
  }

vs.

defaultPostgresConf extra = defaultConfig & configPlanL . partialPlanConfigL <>~ extra

Remove `Lastoid` only accumulate configuration

Being able to replace configuration is too confusing. It leads to situations with createdb where mappend on the default to add args to the createdb plan makes a unexpectedly incomplete plan.

Instead we should remove Lastoid and only accumulate plans.

To get around the issues with environment variables we should make a type that means "inherit the process environment variables" and "add these specific ones". During the creation of the complete plan the inherit constructor signals that getEnvironment should be called.

"createDB" appears to also be incorrect.

As with the initDB issue, createDB also appears to be misspelt. At least, it fails for me on Ubuntu, and I can't find any evidence that the capitalisation would work on any other platform.

Assuming that I'm not mistaken about createDB never being the correct name, I shall create a PR to change it to createdb now.

createdb often starts before the database is truly ready

See this output:

The files belonging to this database system will be owned by user "ollie".
This user must also own the server process.

The database cluster will be initialized with locales
  COLLATE:  en_US.UTF-8
  CTYPE:    en_GB.UTF-8
  MESSAGES: en_US.UTF-8
  MONETARY: en_US.UTF-8
  NUMERIC:  en_US.UTF-8
  TIME:     en_US.UTF-8
The default text search configuration will be set to "english".

Data page checksums are disabled.

creating directory /tmp/tmp-postgres11933/data ... ok
creating subdirectories ... ok
selecting default max_connections ... 100
selecting default shared_buffers ... 128MB
selecting dynamic shared memory implementation ... posix
creating configuration files ... ok
running bootstrap script ... ok
performing post-bootstrap initialization ... ok
syncing data to disk ... ok

Success. You can now start the database server using:

    /home/ollie/.nix-profile/bin/pg_ctl -D /tmp/tmp-postgres11933/data -l logfile start

LOG:  connection received: host=[local]
LOG:  incomplete startup packet
LOG:  database system was shut down at 2017-10-19 10:17:28 GMT
LOG:  connection received: host=[local]
FATAL:  the database system is starting up
LOG:  MultiXact member wraparound protections are now enabled
LOG:  connection received: host=[local]
FATAL:  the database system is starting up
createdb: could not connect to database template1: FATAL:  the database system is starting up
LOG:  database system is ready to accept connections
LOG:  autovacuum launcher started
LOG:  received fast shutdown request
LOG:  aborting any active transactions
LOG:  autovacuum launcher shutting down
LOG:  shutting down
LOG:  database system is shut down
query-tests: CreateDBFailed (ExitFailure 1)

Repeatedly running this command does eventually work. Notice that createdb has failed before the output database system is ready.

Cannot start the server if PGUSER environment variable is set

I have PGUSER=u23sq215lddvbv set when I run my tests, as it's used to connect to a shared staging database. My tests fail with the log:

LOG:  connection received: host=[local]
LOG:  connection authorized: user=u23sq215lddvbv database=template1
FATAL:  role "u23sq215lddvbv" does not exist
LOG:  connection received: host=[local]
LOG:  connection authorized: user=u23sq215lddvbv database=template1
FATAL:  role "u23sq215lddvbv" does not exist
LOG:  connection received: host=[local]
LOG:  connection authorized: user=u23sq215lddvbv database=template1
FATAL:  role "u23sq215lddvbv" does not exist
LOG:  connection received: host=[local]
LOG:  connection authorized: user=u23sq215lddvbv database=template1
FATAL:  role "u23sq215lddvbv" does not exist
LOG:  connection received: host=[local]
LOG:  connection authorized: user=u23sq215lddvbv database=template1
FATAL:  role "u23sq215lddvbv" does not exist
LOG:  connection received: host=[local]
LOG:  connection authorized: user=u23sq215lddvbv database=template1
FATAL:  role "u23sq215lddvbv" does not exist
LOG:  connection received: host=[local]
LOG:  connection authorized: user=u23sq215lddvbv database=template1
FATAL:  role "u23sq215lddvbv" does not exist

ad infinitum.

I believe the problem is the call waitDB doesn't specify a user, so it's inheriting whatever is in the environment.

Perhaps it would be good to run the PostgreSQL executables in an empty/controlled environment?

Make the user and database configurable

The initdb defaults to creating a superuser named the same as the user calling initdb. We should be able to configure this and the name of the database created.

Use --no-sync if users have 9.3 and above

First we should profile to see if --no-sync improves performance when starting up. If it does we should find a way to conditionally use it if users have 9.3 and above.

Remove postgresql-simple dependency

postgresql-simple is mostly used to make connections and could be replaced with a dependency on postgresql-libpq

This would reduce the overall dependency foot print

Replace `createdb` with custom `CREATE DATABASE` configuration

The lack of position independent command line arguments for createdb makes extending the createdb command line parameters problematic because the last parameter will not longer be the database name.

We should just call CREATE DATABASE with a query instead.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.