Skip to content

Commit

Permalink
Merge branch 'item-postgres'
Browse files Browse the repository at this point in the history
closes #58
  • Loading branch information
trehn committed May 2, 2015
2 parents ff73a80 + f4d9ca1 commit 08ece1b
Show file tree
Hide file tree
Showing 7 changed files with 864 additions and 31 deletions.
70 changes: 39 additions & 31 deletions doc/bundles.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ Bundles
item_pkg_pip
item_pkg_yum
item_pkg_zypper
item_postgres_db
item_postgres_role
item_svc_upstart
item_svc_systemd
item_svc_systemv
Expand Down Expand Up @@ -65,37 +67,43 @@ This table lists all item types included in BundleWrap along with the bundle att

<style type="text/css">.wy-table-responsive table td { vertical-align: top !important; white-space: normal !important; }</style>

+---------------------------------------+------------------+----------------------------------------------------------------------------------------+
| Type name | Bundle attribute | Purpose |
+=======================================+==================+========================================================================================+
| :doc:`action <item_action>` | ``actions`` | Actions allow you to run commands on every ``bw apply`` |
+---------------------------------------+------------------+----------------------------------------------------------------------------------------+
| :doc:`directory <item_directory>` | ``directories`` | Manages permissions and ownership for directories |
+---------------------------------------+------------------+----------------------------------------------------------------------------------------+
| :doc:`file <item_file>` | ``files`` | Manages contents, permissions, and ownership for files |
+---------------------------------------+------------------+----------------------------------------------------------------------------------------+
| :doc:`group <item_group>` | ``groups`` | Manages groups by wrapping ``groupadd``, ``groupmod`` and ``groupdel`` |
+---------------------------------------+------------------+----------------------------------------------------------------------------------------+
| :doc:`pkg_apt <item_pkg_apt>` | ``pkg_apt`` | Installs and removes packages with APT |
+---------------------------------------+------------------+----------------------------------------------------------------------------------------+
| :doc:`pkg_pacman <item_pkg_pacman>` | ``pkg_pacman`` | Installs and removes packages with pacman |
+---------------------------------------+------------------+----------------------------------------------------------------------------------------+
| :doc:`pkg_pip <item_pkg_pip>` | ``pkg_pip`` | Installs and removes Python packages with pip |
+---------------------------------------+------------------+----------------------------------------------------------------------------------------+
| :doc:`pkg_yum <item_pkg_yum>` | ``pkg_yum`` | Installs and removes packages with yum |
+---------------------------------------+------------------+----------------------------------------------------------------------------------------+
| :doc:`pkg_zypper <item_pkg_zypper>` | ``pkg_zypper`` | Installs and removes packages with zypper |
+---------------------------------------+------------------+----------------------------------------------------------------------------------------+
| :doc:`svc_upstart <item_svc_upstart>` | ``svc_upstart`` | Starts and stops services with Upstart |
+---------------------------------------+------------------+----------------------------------------------------------------------------------------+
| :doc:`svc_systemd <item_svc_systemd>` | ``svc_systemd`` | Starts and stops services with systemd |
+---------------------------------------+------------------+----------------------------------------------------------------------------------------+
| :doc:`svc_systemv <item_svc_systemv>` | ``svc_systemv`` | Starts and stops services with traditional System V init scripts |
+---------------------------------------+------------------+----------------------------------------------------------------------------------------+
| :doc:`symlink <item_symlink>` | ``symlinks`` | Manages symbolic links and their ownership |
+---------------------------------------+------------------+----------------------------------------------------------------------------------------+
| :doc:`user <item_user>` | ``users`` | Manages users by wrapping ``useradd``, ``usermod`` and ``userdel`` |
+---------------------------------------+------------------+----------------------------------------------------------------------------------------+
+-------------------------------------------+--------------------+----------------------------------------------------------------------------------------+
| Type name | Bundle attribute | Purpose |
+===========================================+====================+========================================================================================+
| :doc:`action <item_action>` | ``actions`` | Actions allow you to run commands on every ``bw apply`` |
+-------------------------------------------+--------------------+----------------------------------------------------------------------------------------+
| :doc:`directory <item_directory>` | ``directories`` | Manages permissions and ownership for directories |
+-------------------------------------------+--------------------+----------------------------------------------------------------------------------------+
| :doc:`file <item_file>` | ``files`` | Manages contents, permissions, and ownership for files |
+-------------------------------------------+--------------------+----------------------------------------------------------------------------------------+
| :doc:`group <item_group>` | ``groups`` | Manages groups by wrapping ``groupadd``, ``groupmod`` and ``groupdel`` |
+-------------------------------------------+--------------------+----------------------------------------------------------------------------------------+
| :doc:`pkg_apt <item_pkg_apt>` | ``pkg_apt`` | Installs and removes packages with APT |
+-------------------------------------------+--------------------+----------------------------------------------------------------------------------------+
| :doc:`pkg_pacman <item_pkg_pacman>` | ``pkg_pacman`` | Installs and removes packages with pacman |
+-------------------------------------------+--------------------+----------------------------------------------------------------------------------------+
| :doc:`pkg_pip <item_pkg_pip>` | ``pkg_pip`` | Installs and removes Python packages with pip |
+-------------------------------------------+--------------------+----------------------------------------------------------------------------------------+
| :doc:`pkg_yum <item_pkg_yum>` | ``pkg_yum`` | Installs and removes packages with yum |
+-------------------------------------------+--------------------+----------------------------------------------------------------------------------------+
| :doc:`pkg_zypper <item_pkg_zypper>` | ``pkg_zypper`` | Installs and removes packages with zypper |
+-------------------------------------------+--------------------+----------------------------------------------------------------------------------------+
| :doc:`postgres_db <item_postgres_db>` | ``postgres_dbs`` | Manages Postgres databases |
+-------------------------------------------+--------------------+----------------------------------------------------------------------------------------+
| :doc:`postgres_role <item_postgres_role>` | ``postgres_roles`` | Manages Postgres roles |
+-------------------------------------------+--------------------+----------------------------------------------------------------------------------------+
| :doc:`pkg_pip <item_pkg_pip>` | ``pkg_pip`` | Installs and removes Python packages with pip |
+-------------------------------------------+--------------------+----------------------------------------------------------------------------------------+
| :doc:`svc_upstart <item_svc_upstart>` | ``svc_upstart`` | Starts and stops services with Upstart |
+-------------------------------------------+--------------------+----------------------------------------------------------------------------------------+
| :doc:`svc_systemd <item_svc_systemd>` | ``svc_systemd`` | Starts and stops services with systemd |
+-------------------------------------------+--------------------+----------------------------------------------------------------------------------------+
| :doc:`svc_systemv <item_svc_systemv>` | ``svc_systemv`` | Starts and stops services with traditional System V init scripts |
+-------------------------------------------+--------------------+----------------------------------------------------------------------------------------+
| :doc:`symlink <item_symlink>` | ``symlinks`` | Manages symbolic links and their ownership |
+-------------------------------------------+--------------------+----------------------------------------------------------------------------------------+
| :doc:`user <item_user>` | ``users`` | Manages users by wrapping ``useradd``, ``usermod`` and ``userdel`` |
+-------------------------------------------+--------------------+----------------------------------------------------------------------------------------+

|
Expand Down
30 changes: 30 additions & 0 deletions doc/item_postgres_db.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
.. _item_postgres_db:

#######################
Postgres database items
#######################

Manages Postgres databases.

.. code-block:: python
postgres_dbs = {
"mydatabase": {
"owner": "me",
},
}
Attribute reference
-------------------

.. seealso::

:ref:`The list of generic builtin item attributes <builtin_item_attributes>`

Optional attributes
===================

``owner``
+++++++++

Name of the role which owns this database (defaults to ``"postgres"``).
48 changes: 48 additions & 0 deletions doc/item_postgres_role.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
.. _item_postgres_role:

###################
Postgres role items
###################

Manages Postgres roles.

.. code-block:: python
postgres_roles = {
"me": {
"superuser": True,
"password": "itsamemario",
},
}
Attribute reference
-------------------

.. seealso::

:ref:`The list of generic builtin item attributes <builtin_item_attributes>`

Optional attributes
===================

``superuser``
+++++++++++++

``True`` if the role should be given superuser privileges (defaults to ``False``).

|
``password``
++++++++++++

Plaintext password to set for this role (will be hashed using MD5).

.. warning::
Please do not write any passwords into your bundles. This attribute is intended to be used with an external source of passwords and filled dynamically. If you don't have or want such an elaborate setup, specify passwords using the ``password_hash`` attribute instead.

|
``password_hash``
+++++++++++++++++

As an alternative to ``password``, this allows setting the raw hash as it will be stored in Postgres' internal database. Should start with "md5".
111 changes: 111 additions & 0 deletions src/bundlewrap/items/postgres_dbs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from pipes import quote

from bundlewrap.exceptions import BundleError
from bundlewrap.items import Item, ItemStatus
from bundlewrap.utils.text import bold, red
from bundlewrap.utils.text import mark_for_translation as _


def create_db(node, name, owner):
return node.run("sudo -u postgres createdb -wO {owner} {name}".format(
name=name,
owner=owner,
))


def drop_db(node, name):
return node.run("sudo -u postgres dropdb -w {}".format(quote(name)))


def get_databases(node):
output = node.run("echo '\\l' | sudo -u postgres psql -Anqt -F '|' | grep '|'").stdout
result = {}
for line in output.strip().split("\n"):
db, owner = line.strip().split("|", 2)[:2]
result[db] = {
'owner': owner,
}
return result


def set_owner(node, name, owner):
return node.run(
"echo 'ALTER DATABASE {name} OWNER TO {owner}' | "
"sudo -u postgres psql -nqw".format(
name=name,
owner=owner,
),
)


class PostgresDB(Item):
"""
A postgres database.
"""
BUNDLE_ATTRIBUTE_NAME = "postgres_dbs"
ITEM_ATTRIBUTES = {
'delete': False,
'owner': "postgres",
}
ITEM_TYPE_NAME = "postgres_db"
NEEDS_STATIC = [
"pkg_apt:",
"pkg_pacman:",
"pkg_yum:",
"pkg_zypper:",
"postgres_role:",
]
def __repr__(self):
return "<PostgresDB name:{}>".format(self.name)

def ask(self, status):
if not status.info['exists'] and not self.attributes['delete']:
return _("Doesn't exist. Do you want to create it?")
if status.info['exists'] and self.attributes['delete']:
return red(_("Will be deleted."))
if status.info['owner'] != self.attributes['owner']:
return "{} {} → {}".format(
bold(_("owner")),
status.info['owner'],
self.attributes['owner'],
)

def fix(self, status):
if 'existence' in status.info['needs_fixing']:
if self.attributes['delete']:
drop_db(self.node, self.name)
else:
create_db(self.node, self.name, self.attributes['owner'])
elif 'owner' in status.info['needs_fixing']:
set_owner(self.node, self.name, self.attributes['owner'])

def get_status(self):
databases = get_databases(self.node)
status_info = {
'exists': self.name in databases,
'needs_fixing': [],
}
status_info.update(databases[self.name])
if self.attributes['delete'] == status_info['exists']:
status_info['needs_fixing'].append('existence')
return ItemStatus(correct=False, info=status_info)
elif (
not self.attributes['delete'] and
self.attributes['owner'] != databases[self.name]['owner']
):
status_info['needs_fixing'].append('owner')
return ItemStatus(correct=False, info=status_info)
return ItemStatus(correct=True, info=status_info)

@classmethod
def validate_attributes(cls, bundle, item_id, attributes):
if not isinstance(attributes.get('delete', True), bool):
raise BundleError(_(
"expected boolean for 'delete' on {item} in bundle '{bundle}'"
).format(
bundle=bundle.name,
item=item_id,
))

0 comments on commit 08ece1b

Please sign in to comment.