Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: blue-yonder/postgraas_server
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.0.0b2
Choose a base ref
...
head repository: blue-yonder/postgraas_server
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref

Commits on Sep 28, 2017

  1. Copy the full SHA
    5b1f701 View commit details
  2. Copy the full SHA
    b6d9fba View commit details
  3. Merge pull request #17 from blue-yonder/bugfix_bad_username

    Bugfix bad username
    treebee authored Sep 28, 2017
    Copy the full SHA
    b3b6486 View commit details

Commits on Nov 29, 2017

  1. Copy the full SHA
    4e24aa9 View commit details
  2. Copy the full SHA
    7e6775b View commit details

Commits on Dec 1, 2017

  1. adjusted changelog

    sebastianneubauer committed Dec 1, 2017
    Copy the full SHA
    749effa View commit details
  2. 1
    Copy the full SHA
    4ca65f1 View commit details
  3. Copy the full SHA
    b55bd34 View commit details
  4. adjusted travis

    sebastianneubauer committed Dec 1, 2017
    Copy the full SHA
    4c84815 View commit details

Commits on Jan 5, 2018

  1. Apply PEP8 formatting

    Frank Fischer authored and sebastianneubauer committed Jan 5, 2018
    Copy the full SHA
    81970d3 View commit details
  2. Fix Python3 imports and statements

    Frank Fischer authored and sebastianneubauer committed Jan 5, 2018
    Copy the full SHA
    88e5d31 View commit details
  3. Fix file execute flags

    Frank Fischer authored and sebastianneubauer committed Jan 5, 2018
    Copy the full SHA
    f05a8b9 View commit details
  4. Minor documentation fix

    Frank Fischer authored and sebastianneubauer committed Jan 5, 2018
    Copy the full SHA
    0ea3c7f View commit details
  5. Remove redundant __future__ imports

    Frank Fischer authored and sebastianneubauer committed Jan 5, 2018
    Copy the full SHA
    6bbcc01 View commit details
  6. Remove Python 2 from Travis

    Frank Fischer authored and sebastianneubauer committed Jan 5, 2018
    Copy the full SHA
    d49aaab View commit details

Commits on Jan 7, 2018

  1. Copy the full SHA
    b4e2847 View commit details
  2. fixed tests

    sebastianneubauer committed Jan 7, 2018
    Copy the full SHA
    4f58b12 View commit details
  3. Copy the full SHA
    44b414e View commit details
  4. Copy the full SHA
    cbc7f38 View commit details
  5. Copy the full SHA
    335111f View commit details
  6. Copy the full SHA
    3426ead View commit details
  7. Copy the full SHA
    d0959e6 View commit details
  8. Copy the full SHA
    2470ea9 View commit details
  9. Copy the full SHA
    36576a6 View commit details
  10. Copy the full SHA
    90e05b6 View commit details
  11. Copy the full SHA
    4ea3d1d View commit details

Commits on Jan 10, 2018

  1. Copy the full SHA
    6789dbb View commit details

Commits on Jan 19, 2018

  1. Copy the full SHA
    20487fc View commit details

Commits on Jan 30, 2018

  1. Properly close database connections and transactions

    This addresses the first item of issue #19.
    matthias-bach-by authored and sebastianneubauer committed Jan 30, 2018
    Copy the full SHA
    bd4f1b8 View commit details

Commits on Feb 1, 2018

  1. Harden the database creation against SQL injections

    If using the PostgreSQL backend, database creation was previously vulnerable to SQL injections. This commit fixes these.
    
    There are two tests which no longer behave as expected and have been disabled for now. They use usernames that previously broke the SQL statement but have now become valid. We might want to think about restricting the possible username somewhat again.
    matthias-bach-by committed Feb 1, 2018
    Copy the full SHA
    7cd8d01 View commit details
  2. Copy the full SHA
    ed2e895 View commit details
  3. Copy the full SHA
    d3bd5e1 View commit details
  4. Copy the full SHA
    f417b5b View commit details
  5. Copy the full SHA
    5885998 View commit details

Commits on May 7, 2018

  1. fix status code on name conflict

    Markus Klein committed May 7, 2018
    Copy the full SHA
    277cc41 View commit details

Commits on May 8, 2018

  1. Copy the full SHA
    010cf43 View commit details
  2. Copy the full SHA
    a627811 View commit details
  3. Copy the full SHA
    67c59a0 View commit details
  4. update changelog

    Markus Klein committed May 8, 2018
    Copy the full SHA
    6169388 View commit details
  5. Merge pull request #30 from pacman82/fix-status-code-on-name-conflict

    fix status code on name conflict
    matthias-bach-by authored May 8, 2018
    Copy the full SHA
    f56813a View commit details

Commits on May 9, 2018

  1. Copy the full SHA
    e265233 View commit details

Commits on Aug 3, 2018

  1. Copy the full SHA
    45125d4 View commit details

Commits on Aug 6, 2018

  1. - distinguish return code between authentication failure and other fa…

    …ilures when connecting to postgres database, when deleting a database
    
    - return status code in other cases of failures, too
    Jonas Weismueller committed Aug 6, 2018
    Copy the full SHA
    569dc71 View commit details
  2. using consistently 'abort' in case of failure

    Jonas Weismueller committed Aug 6, 2018
    Copy the full SHA
    44abcec View commit details
  3. remove unused imports

    Jonas Weismueller committed Aug 6, 2018
    Copy the full SHA
    479dd66 View commit details
  4. Merge pull request #31 from blue-yonder/bugfix/delete-pg-instances-wi…

    …th-proper-http-status-codes
    
    return proper HTTP status codes, when handling postgraas instances
    Jonas Weismüller authored Aug 6, 2018
    Copy the full SHA
    ca9981a View commit details

Commits on Aug 17, 2018

  1. Copy the full SHA
    7633620 View commit details
  2. Drop redundant registration of the Sentry log handler

    This is automatically registered by the Sentry initialization.
    matthias-bach-by committed Aug 17, 2018
    Copy the full SHA
    c8fb761 View commit details
  3. Stop Sentry from swallowing log messages

    For a pre-defined set of loggers, like the Gunicorn loggers, Sentry
    will register itself and disable propagation. However, this means any
    handlers registered on the root level, like custom formatting stream
    loggers or forwarding to central log aggregation will no longer get to
    see these messages.
    matthias-bach-by committed Aug 17, 2018
    Copy the full SHA
    7d91ffb View commit details

Commits on Jan 22, 2019

  1. Copy the full SHA
    74454f2 View commit details
Showing with 1,124 additions and 406 deletions.
  1. 0 .coveragerc
  2. +2 −0 .gitignore
  3. +10 −15 .travis.yml
  4. 0 AUTHORS.rst
  5. +52 −1 CHANGES.rst
  6. 0 MANIFEST.in
  7. +109 −7 README.rst
  8. +1 −1 deploy/templates/postgraas_server.cfg.j2
  9. +1 −1 docs/conf.py
  10. +2 −4 postgraas_server/backends/__init__.py
  11. +8 −4 postgraas_server/backends/docker/__init__.py
  12. +9 −8 postgraas_server/backends/docker/create_db.py
  13. +1 −1 postgraas_server/backends/docker/postgres_instance_driver.py
  14. +14 −4 postgraas_server/backends/postgres_cluster/__init__.py
  15. +54 −44 postgraas_server/backends/postgres_cluster/postgres_cluster_driver.py
  16. +36 −35 postgraas_server/configuration.py
  17. +7 −6 postgraas_server/create_app.py
  18. +8 −16 postgraas_server/init_db.py
  19. +3 −2 postgraas_server/management_database.py
  20. +58 −42 postgraas_server/management_resources.py
  21. +3 −4 postgraas_server/postgraas_api.py
  22. +21 −21 postgraas_server/prometheus_app.py
  23. +2 −2 postgraas_server/utils.py
  24. 0 requirements.in
  25. +1 −1 requirements.txt
  26. 0 requirements_dev.txt
  27. +6 −3 setup.cfg
  28. +3 −2 setup_integration_test_docker.sh
  29. +0 −1 tests/conftest.py
  30. +14 −9 tests/test_integration/application.cfg
  31. +70 −60 tests/test_integration/backends/postgres_cluster/test_postgres_cluster_driver.py
  32. +213 −0 tests/test_integration/test_backend_behaviour.py
  33. +3 −2 tests/test_integration/test_create_db.py
  34. +56 −0 tests/test_integration/test_init_db.py
  35. +2 −1 tests/test_integration/test_management_database.py
  36. +229 −73 tests/test_integration/{test_postgras_api.py → test_postgraas_api.py}
  37. +1 −1 tests/test_integration/utils.py
  38. +6 −2 tests/test_unit/application.cfg
  39. +7 −0 tests/test_unit/application_secure.cfg
  40. +2 −8 tests/test_unit/backends/postgres_cluster/test_postgres_cluster_driver.py
  41. +3 −0 tests/test_unit/secret_file.json
  42. +27 −0 tests/test_unit/test_backends_plugin.py
  43. +80 −25 tests/test_unit/test_configuration.py
Empty file modified .coveragerc
100755 → 100644
Empty file.
2 changes: 2 additions & 0 deletions .gitignore
100755 → 100644
Original file line number Diff line number Diff line change
@@ -38,3 +38,5 @@ docs/api/*
docs/_build/*
cover/*
MANIFEST
pyvenv.cfg
application.cfg
25 changes: 10 additions & 15 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,38 +1,33 @@
language: python
python:
- '2.7'
- '3.5'
- '3.6'
services:
- docker
- postgresql
addons:
postgresql: "9.4"
env:
- PGDATABASE=postgres PGUSER=postgres PGPASSWORD=postgraas_password
before_install:
- docker pull postgres:9.4
- psql -c "alter user $PGUSER with password '$PGPASSWORD';" -U postgres
- sudo sed -ie 's/trust/md5/g' /etc/postgresql/9.4/main/pg_hba.conf
- sudo service postgresql restart
- docker pull postgres
install:
- pip install pip-tools
- pip-compile --upgrade -o requirements-pinned.txt requirements.txt requirements_secrets.in requirements_prometheus.in
- pip-compile --upgrade -o test-requirements-pinned.txt requirements-pinned.txt requirements_dev.txt
- cat requirements-pinned.txt
- pip install -r test-requirements-pinned.txt
- pip install pyscaffold
- pip install 'pyscaffold<3.0'
- pip install coveralls
- pip install -e .[docker]
- pip freeze

script: py.test
script:
- . setup_integration_test_docker.sh
- py.test
after_success:
- coveralls
deploy:
provider: pypi
user: sebastianneubauer
password:
secure: AwbSrSt2gVm8FhXKMOdtmwifnNwjUbuLeJdpMnIXMLkpzEAMAoJPPkn4+hsvaC9HpKZKl/CMo94ZZ+39lQ1n8C+7LvhcvR6QEBnSS44PuTZb7cb//WEexHpJx2uqP36GA7OAcyQ1fLQ10sMU1xqxFWvHrboafqHt9i5U30HpWwSwZK8EsEHfAzJGyCaRxqgyuUZUNPhzN6JFfmrIuHWXEl85z7TiTrnBT7tsSFj242qO/XNrq7PzhLRxV+e6HXIDTlCBY3TVg7FcDacIAZOWnJn8ixW/uZz2Cg9Etjl1E5PauCAo/mOzNSp4MoL+EsTlhY6eIOYOBt1nrd1UkZeWZzVvVsSMwgkN5erJ/Gd/e63UlcFB0Gr5g4s+Gl/yLTZpLSL+643Adn67IK/JkkynkvMvePVDpIxgSaAzQYllCYrVi7Hy7OugYeH907cOhGzjChi3uHQR+tWxT26fL6+CQCeVW5O5sqm08HUYBbDit8BRdjhu4keG8p4xoJ4GH3Nffo4+IDU2ANpoxVgJf5+o9TACpKR6yTYI2Jq02d+CBvJbqmNTtC6wpSDianviHDxNNipbJJtIbtCgS3ERtmxsPUBWvYaFAEYncNwYC/h7b59VUjXGgzx/E55j0T61xfn2EQvFSo7Y+z0MNMmFBEzAp86GFPkWUNRywuuPxeHFQFY=
distributions: "sdist bdist_wheel"
user: __token__
distributions: sdist bdist_wheel
skip_existing: true
on:
tags: true
branch: master
Empty file modified AUTHORS.rst
100755 → 100644
Empty file.
53 changes: 52 additions & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
@@ -2,11 +2,62 @@
Changelog
=========

latest
v2.1.4
======

- Fixed some errors in README.rst that prevented successfull build

v2.1.3
======

- Prevent internal server errors upon database delete when there are multiple active sessions

v2.1.2
======

- Blacklist postgres as username

v2.1.1
======

- Allow user to supply username in the format `user@host` himself.

v2.1.0
======

- init-db now constructs usernames identical to the server. Thus, `user@host` names now work properly.
- Fix log messages of Gunicorn and Flask not ending up in the root logger.`

v2.0.2
======

- return proper HTTP status codes, when deleting postgraas instances

v2.0.1
======

- prevent creation of databases with an empty password as those cannot be removed.
- return http status code 409 instead of 200 in case of a name conflict during creation of a new
instance.

v2.0.0
======

- security: Harden the Postgres cluster backend against SQL injections.
- hardened the server against leaking of database connections and transactions.

v2.0.0b1
========

- breaking change: config not ini anymore, but json
- add support for secure-config (experimental)

v1.0.0b3
========

- add support for simple Postgres Cluster as backend
- add support for sentry (https://sentry.io)
- bugfix: varchar(50) field in the DB too small for hostname

v0.1.9
======
Empty file modified MANIFEST.in
100755 → 100644
Empty file.
116 changes: 109 additions & 7 deletions README.rst
100755 → 100644
Original file line number Diff line number Diff line change
@@ -16,7 +16,12 @@ Postgraas is a super simple PostgreSQL-as-a-service
What is Postgraas?
==================

Postgraas offers `CRUD <https://de.wikipedia.org/wiki/CRUD>`_ operations for complete PostgreSQL database instances via a simple REST api. The database instances are docker containers and the api server is a few hundred LoC Flask application. It is of not meant as a production ready solution, but more a proof-of-concept to spread the idea of creating "as-a-service" services easily yourself and should inspire you to start working on your own cloud infrastructure today. But in fact, it proofs the concept very well and it turned out to be super useful for delivering a PostgreSQL instance if you need one fast: for integration tests, for playing around with fancy ShowHN projects or other experiments. The CRUD management via REST api is of course also a necessary prequisite for building an automated continuous delivery pipeline for a modern software project.
Postgraas offers `CRUD <https://de.wikipedia.org/wiki/CRUD>`_ operations for complete PostgreSQL database instances via a simple REST api.
The database instances are docker containers and the API server is a few hundred LoC Flask application.
It is not meant as a production ready solution, but more as a proof-of-concept to spread the idea of creating "as-a-service" services easily yourself and should inspire you to start working on your own cloud infrastructure today.
But in fact, it proofs the concept very well and it turned out to be super useful for delivering a PostgreSQL instance if you need one fast, e.g. for integration tests, for playing around with fancy ShowHN projects or other experiments.
The CRUD management via REST api is of course also a necessary prerequisite for building an automated continuous delivery pipeline for a modern software project.


Installation
============
@@ -25,16 +30,18 @@ You can find detailed instructions in the `docs <http://postgraas-server.readthe
Install via pip::

pip install postgraas_server
And start the wsgi api server for example with gunicorn::

Start the WSGI api server for example via gunicorn::

pip install gunicorn
gunicorn -w 4 -b 0.0.0.0:8080 postgraas_server.postgraas_api:app


Usage
=====

We need to send all the required parameters for the creation as an http request. This is quite convenient by creating a file e.g. ``my_postgraas.json``::
We need to send all the required parameters for the creation as an http request.
This is quite convenient by creating a file e.g. ``my_postgraas.json``::

{
"postgraas_instance_name": "my_postgraas",
@@ -53,14 +60,109 @@ now your instance is created and as a response you get the details of your insta
"postgraas_instance_id": 1,
"container_id": "193f0d94d49fa26626fdbdb583e9453f923468b01eac59207b4852831a105c03",
"db_pwd": "secret",
"host": "not imlemented yet",
"host": "not implemented yet",
"db_name": "my_db",
"db_username": "db_user",
"port": 54648
}

We are now able to connect to the database for exaple with psql::
We are now able to connect to the database for example via ``psql``::

psql -h localhost -p 54648 -U db_user my_db

Awesome, isn’t it?

Development
===========

You can follow the next steps in order to host postgraas_server locally and be able to develop features or bug fixes:

Clone repository::

git clone https://github.com/blue-yonder/postgraas_server

Install all the project dependencies::

pip install -r requirements_dev.txt
pip install -r requirements_docker.in
pip install -r requirements_prometheus.in
pip install gunicorn
pip install -e .

Docker
------

Pull the right docker image::

docker pull postgres:9.4

Your application.cfg file should look like this::

{
"metadb":
{
"db_name": "postgres",
"db_username": "postgres",
"db_pwd": "mysecret",
"host": "localhost",
"port": "5432"
},
"backend":
{
"type": "docker"
}
}

Initialize a postgres DB within a docker container::

sh setup_integration_test_docker.sh

Run a Docker container with the postgres image::

postgraas_init

Postgres Cluster
----------------

If you don't want to use Docker as the backend you could create a local postgres cluster

Your application.cfg file should look like this::

{
"metadb":
{
"db_name": "postgres",
"db_username": "postgres",
"db_pwd": "mysecret",
"host": "localhost",
"port": "5432"
},
"backend":
{
"type": "pg_cluster",
"database": "postgres",
"username": "postgres",
"password": "mysecret",
"host": "localhost",
"port": "5432"
}
}

Run postgres server::

postgres -D /usr/local/var/postgres

Execute application locally
---------------------------

Run the Flask application by executing this command::

python postgraas_server/postgraas_api.py

After this your application should be started and you can perform GET/POST/DELETE actions to this endppoint::

http://localhost:5000/api/v2/postgraas_instances

Alternatively, you can run your unit and integration tests to verify your new code::

pytest tests/
2 changes: 1 addition & 1 deletion deploy/templates/postgraas_server.cfg.j2
Original file line number Diff line number Diff line change
@@ -3,4 +3,4 @@ db_name = postgraas
db_username = postgraas
db_pwd = postgraas12
host = localhost
port = 5432
port = 5432
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
@@ -45,7 +45,7 @@
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinx.ext.todo',
'sphinx.ext.autosummary', 'sphinx.ext.viewcode', 'sphinx.ext.coverage',
'sphinx.ext.doctest', 'sphinx.ext.ifconfig', 'sphinx.ext.pngmath',
'sphinx.ext.doctest', 'sphinx.ext.ifconfig', 'sphinx.ext.imgmath',
'sphinx.ext.napoleon']

# Add any paths that contain templates here, relative to this directory.
6 changes: 2 additions & 4 deletions postgraas_server/backends/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import ConfigParser

from .docker import DockerBackend
from .postgres_cluster import PGClusterBackend

@@ -9,8 +7,8 @@
def get_backend(config):
backend_config = {}
try:
backend_config = dict(config.items('backend'))
backend_config = config['backend']
backend = backend_config['type']
except ConfigParser.NoSectionError:
except KeyError:
backend = 'docker'
return BACKENDS[backend](backend_config)
12 changes: 8 additions & 4 deletions postgraas_server/backends/docker/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#from . import postgres_instance_driver as pg
# from . import postgres_instance_driver as pg
from ..exceptions import PostgraasApiException


@@ -11,15 +11,19 @@ def create(self, entity, connection_info):
from . import postgres_instance_driver as pg
try:
return pg.create_postgres_instance(entity.postgraas_instance_name, connection_info)
except APIError as e:
except (APIError, ValueError) as e:
raise PostgraasApiException(str(e))

def delete(self, entity):
from docker.errors import APIError
from docker.errors import APIError, NullResource, NotFound
from . import postgres_instance_driver as pg
if not entity.container_id:
raise PostgraasApiException("container ID not provided")
try:
return pg.delete_postgres_instance(entity.container_id)
except APIError as e:
except NotFound as e:
raise PostgraasApiException("Could not delete, does not exist {}".format(entity.container_id))
except (APIError, NullResource) as e:
raise PostgraasApiException(str(e))

def exists(self, entity):
17 changes: 9 additions & 8 deletions postgraas_server/backends/docker/create_db.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
from postgraas_server.backends.docker import postgres_instance_driver as pg
from postgraas_server.configuration import get_config
from postgraas_server.configuration import get_config, get_user, get_password
from postgraas_server.utils import wait_for_postgres


def create_db_container():
config = get_config()
print(config)
db_credentials = {
"db_name": config.get('metadb', 'db_name'),
"db_username": config.get('metadb', 'db_username'),
"db_pwd": config.get('metadb', 'db_pwd'),
"host": config.get('metadb', 'host'),
"port": config.get('metadb', 'port')
"db_name": config['metadb']['db_name'],
"db_username": get_user(config),
"db_pwd": get_password(config),
"host": config['metadb']['host'],
"port": config['metadb']['port']
}
if pg.check_container_exists('postgraas_master_db'):
print "warning container already exists"
print("warning container already exists")
postgraas_db = pg.get_container_by_name('postgraas_master_db')
db_credentials['container_id'] = postgraas_db.id
else:
@@ -24,7 +25,7 @@ def create_db_container():


def main():
print "creating container for the management db"
print("creating container for the management db")
db_credentials = create_db_container()
wait_for_postgres(
db_credentials['db_name'], db_credentials['db_username'], db_credentials['db_pwd'],
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@

def get_hostname():
# mmmh, how should this be done? need nome kind ouf routing...
return 'not imlemented yet'
return 'not implemented yet'


def _docker_client():
Loading