{ "info": { "author": "Marius Gedminas", "author_email": "marius@pov.lt", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "License :: OSI Approved :: MIT License" ], "description": "Fabric Helpers\n==============\n\nThis is a collection of helpers we use in Fabric_ scripts. They're primarily\nintended to manage Ubuntu servers (12.04 LTS or 14.04 LTS).\n\n.. _Fabric: http://www.fabfile.org/\n\n.. contents::\n\n\nHelpers (aka why would I want this?)\n------------------------------------\n\nAPT packages:\n\n- ``ensure_apt_not_outdated()`` - runs ``apt-get update`` at most once a day\n- ``install_packages(\"vim screen build-essential\")``\n- ``install_missing_packages(\"vim screen build-essential\")``\n- ``if not package_installed('git'): ...``\n- ``if not package_available('pov-admin-helpers'): ...``\n\nUser accounts:\n\n- ``ensure_user(\"myusername\")``\n\nSSH:\n\n- ``ensure_known_host(\"example.com ssh-rsa AAA....\")``\n\nLocales:\n\n- ``ensure_locales(\"en\", \"lt\")``\n\nFiles and directories:\n\n- ``ensure_directory(\"/srv/data\", mode=0o700)``\n- ``upload_file('crontab', '/etc/cron.d/mycrontab')``\n- ``generate_file('crontab.in', '/etc/cron.d/mycrontab', context, use_jinja=True)``\n- ``download_file('/home/user/.ssh/authorized_keys', 'https://example.com/ssh.pubkey')``\n\nGIT:\n\n- ``git_clone(\"git@github.com:ProgrammersOfVilnius/project.git\", \"/opt/project\")``\n- ``git_update(\"/opt/project\")``\n\nPostgreSQL:\n\n- ``ensure_postgresql_user(\"username\")``\n- ``ensure_postgresql_db(\"dbname\", \"owner\")``\n\nApache:\n\n- ``ensure_ssl_key(...)``\n- ``install_apache_website('apache.conf.in', 'example.com', context, use_jinja=True, modules='ssl rewrite proxy_http')```\n\nPostfix:\n\n- ``install_postfix_virtual_table('virtual', '/etc/postfix/virtual.example.com')```\n- ``make_postfix_public()``\n\nKeeping a changelog in /root/Changelog (requires\n/usr/sbin/new-changelog-entry from pov-admin-tools_)\n\n- ``changelog(\"# Installing stuff\")``\n- ``changelog_append(\"# more stuff\")``\n- ``changelog_banner(\"Installing stuff\")``\n- ``run_and_changelog(\"apt-get install stuff\")``\n\nplus many other helpers have ``changelog`` and/or ``changelog_append``\narguments to invoke these implicitly.\n\n.. _pov-admin-tools: https://github.com/ProgrammersOfVilnius/pov-admin-tools\n\n\nInstance management API\n-----------------------\n\nAll of my fabfiles can manage several *instances* of a particular service.\nExternally this looks like ::\n\n fab instance1 task1 task2 instance2 task3\n\nwhich executes Fabric tasks ``task1`` and ``task2`` on instance ``instance1``\nand then executes ``task3`` on ``instance2``.\n\nAn instance defines various parameters, such as\n\n- what server hosts it\n- where on the filesystem it lives\n- what Unix user IDs are used\n- what database is used for this instance\n- etc.\n\nTo facilitate this ``pov_fabric`` provides three things:\n\n1. An ``Instance`` class that should be subclassed to provide your own instances\n\n .. code:: python\n\n from pov_fabric import Instance as BaseInstance\n\n class Instance(BaseInstance):\n def __init__(self, name, host, home='/opt/sentry', user='sentry',\n dbname='sentry'):\n super(Instance, self).Instance.__init__(name, host)\n self.home = home\n self.user = user\n self.dbname = dbname\n\n and since that's a bit repetitive there's a helper\n\n .. code:: python\n\n from pov_fabric import Instance as BaseInstance\n\n Instance = BaseInstance.with_params(\n home='/opt/sentry',\n user='sentry',\n dbname='sentry',\n )\n\n which is equivalent to the original manual subclassing.\n\n (BTW you can also add parameters with no sensible default this way, e.g.\n ``BaseInstance.with_params(user=BaseInstance.REQUIRED)``.)\n\n2. An ``Instance.define()`` class method that defines new instances and\n creates tasks for selecting them\n\n .. code:: python\n\n Instance.define(\n name='testing',\n host='root@vagrantbox',\n )\n Instance.define(\n name='production',\n host='server1.pov.lt',\n )\n Instance.define(\n name='staging',\n host='server1.pov.lt',\n home='/opt/sentry-staging',\n user='sentry-staging',\n dbname='sentry-staging',\n )\n\n (BTW you can also define aliases with ``Instance.define_alias('prod',\n 'production')``.)\n\n3. A ``get_instance()`` function that returns the currently selected instance\n (or aborts with an error if the user didn't select one)\n\n .. code:: python\n\n from pov_fabric import get_instance\n\n @task\n def look_around():\n instance = get_instance()\n with settings(host_string=instance.host):\n run('hostname')\n\n\nPreviously I used a slightly different command style ::\n\n fab task1:instance1 task2:instance1 task3:instance2\n\nand this can still be supported if you write your tasks like this\n\n.. code:: python\n\n @task\n def look_around(instance=None):\n instance = get_instance(instance)\n with settings(host_string=instance.host):\n run('hostname')\n\nBe careful if you mix styles, e.g. ::\n\n fab instance1 task1 task2:instance2 task3\n\nwill run ``task1`` and ``task3`` on ``instance1`` and it will run ``task2`` on\n``instance2``.\n\n\nUsage\n-----\n\nGet the latest release from PyPI::\n\n pip install pov-fabric-helpers\n\nand then import the helpers you want in your ``fabfile.py``\n\n.. code:: python\n\n from fabric.api import ...\n from pov_fabric import ...\n\n\nUsage as a git submodule\n~~~~~~~~~~~~~~~~~~~~~~~~\n\nYou can add this repository as a git submodule\n\n.. code:: bash\n\n cd ~/src/project\n git submodule add https://github.com/ProgrammersOfVilnius/pov-fabric-helpers\n\nand in your ``fabfile.py`` add\n\n.. code:: python\n\n sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'pov-fabric-helpers'))\n if not os.path.exists(os.path.join(sys.path[0], 'pov_fabric.py')):\n sys.exit(\"Please run 'git submodule update --init'.\")\n from pov_fabric import ...\n\n\nTesting Fabfiles with Vagrant\n-----------------------------\n\nI don't know about you, but I was never able to write a fabfile.py that worked\non the first try. Vagrant_ was very useful for testing fabfiles without\ndestroying real servers in the process. Here's how:\n\n- Create a ``Vagrantfile`` somewhere with\n\n .. code:: ruby\n\n Vagrant.configure(\"2\") do |config|\n config.vm.box = \"ubuntu/precise64\" # Ubuntu 12.04\n config.vm.provider :virtualbox do |vb|\n vb.customize [\"modifyvm\", :id, \"--memory\", \"1024\"]\n end\n end\n\n- Run ``vagrant up``\n\n- Run ``vagrant ssh-config`` and copy the snippet to your ``~/.ssh/config``,\n but change the name to ``vagrantbox``, e.g. ::\n\n Host vagrantbox\n HostName 127.0.0.1\n User vagrant\n Port 2222\n UserKnownHostsFile /dev/null\n StrictHostKeyChecking no\n PasswordAuthentication no\n IdentityFile ~/.vagrant.d/insecure_private_key\n IdentitiesOnly yes\n LogLevel FATAL\n\n- Test that ``ssh vagrantbox`` works\n\n- In your ``fabfile.py`` create a testing instance\n\n .. code:: python\n\n Instance.define(\n name='testing',\n host='vagrant@vagrantbox',\n ...\n )\n\n- Test with ``fab testing install`` etc.\n\n.. _Vagrant: https://www.vagrantup.com/\n\n\nChangelog\n=========\n\n\n0.3 (2016-09-11)\n----------------\n\n- ``register_host_key()`` now takes ``fingerprints`` so you can specify both\n MD5 and SHA256 fingerprints.\n\n Use either ``register_host_key(key, fingerprint=md5_fprint)`` or\n ``register_host_key(key, fingerprints=[md5_fprint, sha256_fprint])``.\n\n- Low-level helper ``ssh_key_fingerprint()`` now takes ``force_md5`` so you\n can insist on MD5 instead of whatever OpenSSH gives you by default (which is\n SHA256 for modern OpenSSH).\n\n\n0.2 (2015-08-06)\n----------------\n\n- New helpers:\n\n - ``git_update()``, ``register_host_key()``,\n - ``ensure_locales()``,\n - ``changelog_banner()``, ``run_and_changelog()``,\n ``has_new_changelog_message()``,\n - ``install_missing_packages()``, ``package_available()``,\n - ``upload_file()``, ``generate_file()``, ``ensure_directory()``,\n ``download_file()``,\n - ``install_postfix_virtual_table()``,\n - ``install_apache_website()``,\n - ``ensure_ssl_key()``.\n\n- New optional arguments for existing helpers:\n\n - ``git_clone()`` now takes ``branch`` and ``changelog``.\n - ``ensure_user()`` now takes ``shell``, ``home``, ``create_home``, and\n ``changelog``.\n - ``install_packages()`` now takes ``changelog``.\n - ``changelog()`` now takes ``context``.\n - ``changelog_append()`` now takes ``context`` and ``optional``.\n - ``changelog_banner()`` now takes ``context`` and ``optional``.\n\n- Increased safety:\n\n - all helpers check their arguments for unsafe shell metacharacters.\n - changelog() and friends quote the arguments correctly.\n\n- Improved instance API:\n\n - allow ``str.format(**instance)`` (by making Instance a subclass of\n ``dict``).\n - allow instance aliases defined via ``Instance.define_alias(alias, name)``\n static method.\n\n- Bugfixes:\n\n - ``ensure_postgresql_db()`` now works correctly on Ubuntu 14.04.\n - ``run_as_root`` now correctly handles ``env.host_string`` with no\n username part.\n\n- New low-level helpers you're probably not interested in, unless you're\n writing your own helpers:\n\n - ``aslist()``, ``assert_shell_safe()``,\n - ``ssh_key_fingerprint()``,\n - ``render_jinja2()``, ``render_sinterp()``,\n - ``parse_git_repo()``,\n - ``generate_ssl_config()``, ``generate_ssl_key()``, ``generate_ssl_csr()``,\n - ``get_postfix_setting()``, ``parse_postfix_setting()``,\n ``add_postfix_virtual_map()``, ``add_postfix_setting()``,\n - ``run_as_root()``.\n\n\n0.1 (2014-11-19)\n----------------\n\n- First public release.\n\n- Helpers:\n\n - ``ensure_apt_not_outdated()``, ``package_installed()``,\n ``install_packages()``,\n - ``ensure_known_host()``, ``ensure_user()``,\n - ``git_clone()``,\n - ``ensure_postgresql_user()``, ``ensure_postgresql_db()``,\n - ``changelog()``, ``changelog_append()``.\n\n- Instance API:\n\n - ``class Instance``, ``Instance.with_params()``,\n ``Instance.REQUIRED``, ``Instance.define()``.\n - ``instance._asdict()``.\n - ``get_instance()``.\n\n- Low-level helpers you're probably not interested in, unless you're\n writing your own helpers:\n\n - ``asbool()``,\n - ``postgresql_user_exists()``, ``postgresql_db_exists()``.\n\n\n", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/ProgrammersOfVilnius/pov-fabric-helpers/", "keywords": "", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "pov-fabric-helpers", "package_url": "https://pypi.org/project/pov-fabric-helpers/", "platform": "", "project_url": "https://pypi.org/project/pov-fabric-helpers/", "project_urls": { "Homepage": "https://github.com/ProgrammersOfVilnius/pov-fabric-helpers/" }, "release_url": "https://pypi.org/project/pov-fabric-helpers/0.3/", "requires_dist": [ "Fabric" ], "requires_python": "", "summary": "Fabric helpers we use at PoV", "version": "0.3" }, "last_serial": 2335892, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "3cdaea535498fc52af09cedbe847ef29", "sha256": "696f4cb7d949ce209582ad7d47e102039c70fb606d7237de96210f695062b0f3" }, "downloads": -1, "filename": "pov-fabric-helpers-0.1.tar.gz", "has_sig": false, "md5_digest": "3cdaea535498fc52af09cedbe847ef29", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7258, "upload_time": "2014-11-19T06:55:12", "url": "https://files.pythonhosted.org/packages/75/8e/1c66099dff740951d4df000bd5807a8dc3dbf6959517ea36918d898bd148/pov-fabric-helpers-0.1.tar.gz" } ], "0.2": [ { "comment_text": "", "digests": { "md5": "ac4ec50029d62c3fb2d03c1461c013b8", "sha256": "55ec2e44c8b77b862d5e695a4c1960b6f482a22777aedd7af5ebb6a4accd1b3d" }, "downloads": -1, "filename": "pov-fabric-helpers-0.2.tar.gz", "has_sig": false, "md5_digest": "ac4ec50029d62c3fb2d03c1461c013b8", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21465, "upload_time": "2015-08-06T09:19:41", "url": "https://files.pythonhosted.org/packages/d8/67/5b2222edc4837e7c54b5246293cfa9b5a23c7d1f1b5e8f542b7fab5011ba/pov-fabric-helpers-0.2.tar.gz" } ], "0.3": [ { "comment_text": "", "digests": { "md5": "b274375b58b8f187eae9845b8633f6a3", "sha256": "9b21ec409f7d718a68d5d75a968ecff981a513e4f9c0b3772a7a8944359af3ca" }, "downloads": -1, "filename": "pov_fabric_helpers-0.3-py2-none-any.whl", "has_sig": false, "md5_digest": "b274375b58b8f187eae9845b8633f6a3", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 22022, "upload_time": "2016-09-11T07:18:22", "url": "https://files.pythonhosted.org/packages/a0/85/671478cf55f81c86ec0eb1c1f969c0b00e2b39e872ddbf2d719696921a77/pov_fabric_helpers-0.3-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "71adee9f8d325b7c6a61b5905b1992c2", "sha256": "133a5c763ab0f2f34e3338578675f92a0c44f5eb074692dab7929751065fe7e8" }, "downloads": -1, "filename": "pov-fabric-helpers-0.3.tar.gz", "has_sig": false, "md5_digest": "71adee9f8d325b7c6a61b5905b1992c2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 23357, "upload_time": "2016-09-11T07:18:25", "url": "https://files.pythonhosted.org/packages/b5/79/11e01dcfc8f280106832565ef7bc8c99e08db9ae0a68cad183d569ad43e4/pov-fabric-helpers-0.3.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "b274375b58b8f187eae9845b8633f6a3", "sha256": "9b21ec409f7d718a68d5d75a968ecff981a513e4f9c0b3772a7a8944359af3ca" }, "downloads": -1, "filename": "pov_fabric_helpers-0.3-py2-none-any.whl", "has_sig": false, "md5_digest": "b274375b58b8f187eae9845b8633f6a3", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 22022, "upload_time": "2016-09-11T07:18:22", "url": "https://files.pythonhosted.org/packages/a0/85/671478cf55f81c86ec0eb1c1f969c0b00e2b39e872ddbf2d719696921a77/pov_fabric_helpers-0.3-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "71adee9f8d325b7c6a61b5905b1992c2", "sha256": "133a5c763ab0f2f34e3338578675f92a0c44f5eb074692dab7929751065fe7e8" }, "downloads": -1, "filename": "pov-fabric-helpers-0.3.tar.gz", "has_sig": false, "md5_digest": "71adee9f8d325b7c6a61b5905b1992c2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 23357, "upload_time": "2016-09-11T07:18:25", "url": "https://files.pythonhosted.org/packages/b5/79/11e01dcfc8f280106832565ef7bc8c99e08db9ae0a68cad183d569ad43e4/pov-fabric-helpers-0.3.tar.gz" } ] }