{ "info": { "author": "David J Cox", "author_email": "davidjcox.at@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Environment :: Console", "Intended Audience :: Developers", "Intended Audience :: End Users/Desktop", "Intended Audience :: Information Technology", "Intended Audience :: System Administrators", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.1", "Programming Language :: Python :: 3.2", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: HTTP Servers", "Topic :: Internet :: WWW/HTTP :: Site Management", "Topic :: Internet :: WWW/HTTP :: WSGI", "Topic :: Software Development", "Topic :: System", "Topic :: System :: Installation/Setup", "Topic :: System :: Systems Administration", "Topic :: Utilities" ], "description": "=============\nwf-api-client\n=============\n\nThe WebFaction API client is a local client for interfacing to the WebFaction \nweb hosting server API. It provides class-based organization, convenience \nmethods, script execution, and HTML-formatted run reporting.\n\nIt can be used as standalone module to execute a supplied script file or as an \nimported library module within individual script files.\n\nDetailed documentation is available on http://wf-api-client.readthedocs.org/en/latest/.\n\n:Author: David J Cox\n\n:Contact: \n\n:Version: 1.0.1\n\nLet me know what you think of it...\n\nWhat's new?\n-----------\nThe client continues to be Python 2/3 compatible, as it should be. A full test \nsuite has been added, which also doubles as an example of how to write a \nstandalone script for the client.\n\nWhat's this all about?\n----------------------\n\nWebFaction provides a perfectly cromulent RESTful API for their server accounts.\nIt enables all aspects of server management to be executed remotely: CRUD \nactions for domains, websites, email, databases, etc. It even allows shell \ncommands. Excellent!\n\nHowever, despite its excellence, there are a few design decisions that cause \nmisgivings for me:\n\n- The WebFaction API uses positional arguments. \n When working with remote servers, I prefer commands to be as explicit as \n possible, because like Unix, APIs can be unforgiving. This client uses \n keyword arguments to guard against a slip of concentration wiping something \n important out. It translates the keyword arguments into positional ones \n for each API call.\n\n- The WebFaction API has small inconsistencies in calling convention.\n This is a nitpick, but one that's important when remotely administering \n servers. Some API calls define collections using lists. Others define \n collections using positional arguments only. Once again, a mistake waiting \n to be made if a call signature is recalled incorrectly. This client uses \n lists for all collections and unwraps them back into individual positional \n arguments for those API calls that require it.\n\nIn addition to these translation functions, the WebFaction API client provides \nadditional utility similar to other IT automation solutions like Ansible, Salt, \netc, by providing batching, parallelism, and reporting, described as follows.\n\nClass-based Organization\n------------------------\n\nFunctional groups are implemented as classes with API calls grouped as methods.\nWorking with descriptive class instances makes complicated scripting easier, \nespecially when driving more than one server or using more than one worker \nthread. In addition to atomic methods, batched convenience methods have been \nadded, for e.g. creating/deleting RFC 2142 email prefixes in one call.\n\nConvenience Methods\n-------------------\n\nIn addition to batch methods, convenience methods are used to speed script \nexecution by performing client-side evaluation to avoid unnecessary remote API \ncalls. Creation/deletion calls are compared against a single inventory call to \nensure that entities exist before attempting deletion or do not exist before \nattempting creation. If not, client errors are reported.\n\nScript Execution\n----------------\n\nWhy have an API if it's not being scripted against? The client provides \nscripting two ways: Scripts can be passed directly to the client in a standalone\nmodule call, or the module can be imported as a library module within standalone\nscripts. See below for examples of both approaches.\n\nHTML-formatted Run Reporting\n----------------------------\n\nSince RESTful services are stateless, they can't (shouldn't) provide history. \nThis client does. Every method call resulting in a remote API call returns the\nstatus, datetime, API call name, and call result to a log function. The running\ntally of logged actions are collected and reported as a HTMl report file. Call \nresults are color-coded green for 'success' and red for 'failure'. Elementary!\n\nTests\n-----\n\nA full test suite is provided in the `wfapiclienttests.py` file. It is \nstandalone script and, so, doubles as a fine example for standalone scripts. The \ntests must be run against a live, accessible WeFaction server using valid \ncredentials. The tests are not idempotent but can be considered nearly so in\nthat all test actions against the server will not cause side effects for the \nexisting configuration and all test create and update actions are deleted \nafterward. Should some event prevent successful completion of the tests, all \ntest objects created on the server are obviously identifiable with some \nvariation of 'wf_test' pre-pended to their name and should be considered safe \nto delete manually.\n\n\nExamples\n--------\n\nTests are executed like so::\n\n python wfapiclienttests.py \"username\" \"password\" \"/path/to/report.html\"\n\n\nStandalone scripts import the module as a library and are responsible for \ninstantiating the Runner class to log results and write out the run report. It \nis more flexible in that multiple runner objects can be created to work on \ndifferent servers at one time logging either to separate reports or to one \nshared report.\nStandalone scripts are structured like this:\n\n.. code:: python\n\n \"\"\"`create_emails` script\"\"\"\n\n import wfapiclient as wf\n\n runner1 = wf.Runner()\n runner2 = wf.Runner()\n\n #WebFaction automagically identifies target server by username/password.\n runner1.login_to_server(\"first_username\", \"first_password\")\n runner2.login_to_server(\"second_username\", \"second_password\")\n\n #Server objects are tied to runner instances for call execution and logging.\n email1 = wf.Email(runner1)\n email1.create_emails(domain=\"first.example.com\", targets=\"user1@first.example.com\")\n\n email2 = wf.Email(runner2)\n email2.create_emails(domain=\"second.example.com\", targets=\"user2@second.example.com\")\n\n #Either write report to separate report files...\n runner1.write_report_to_file(\"/tmp/create_emails1.html\")\n runner2.write_report_to_file(\"/tmp/create_emails2.html\")\n\n #...or write (append) reports to one `shared` file.\n runner1.write_report_to_file(\"/tmp/create_emails_shared.html\")\n runner2.write_report_to_file(\"/tmp/create_emails_shared.html\")\n\n #EOF - `create_emails`\n\n\nDirect module calls are invoked like this::\n\n python wfapiclient.py \"username\" \"password\" \\\n --scriptfile=/home/user/scripts/create_emails \\\n --reportfile=/tmp/create_emails.html\n\n\nScripts for importation by the module call methods directly using Python syntax.\nThe run report is automatically generated using a supplied destination file name.\nImported scripts are structured like this:\n\n.. code:: python\n\n \"\"\"`create_emails` script\"\"\"\n\n #Class object creation requires `self` reference to Runner().\n email = Email(self)\n email.create_emails(domain=\"example.com\", targets=\"user@example.com\")\n\n #EOF - `create_emails`\n\n\nThat's it. Have fun.", "description_content_type": null, "docs_url": "https://pythonhosted.org/wf-api-client/", "download_url": null, "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/davidjcox/wf-api-client", "keywords": "WebFaction webfaction webhosting web hosting API api client", "license": "BSD License", "maintainer": null, "maintainer_email": null, "name": "wf-api-client", "package_url": "https://pypi.org/project/wf-api-client/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/wf-api-client/", "project_urls": { "Homepage": "https://github.com/davidjcox/wf-api-client" }, "release_url": "https://pypi.org/project/wf-api-client/1.0.1/", "requires_dist": null, "requires_python": null, "summary": "A local client for interfacing to the WebFaction web hosting server API.", "version": "1.0.1" }, "last_serial": 1615670, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "8cc970c81347302dd053bf186a7fc37a", "sha256": "633f1d8e2cf7901c639e62f3bb5f011b94da19d4f6de4bac3bd96ac878e9bc33" }, "downloads": -1, "filename": "wf_api_client-0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "8cc970c81347302dd053bf186a7fc37a", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 11952, "upload_time": "2015-06-03T19:33:50", "url": "https://files.pythonhosted.org/packages/a8/52/3884bebbb701b837bc70b9a794c1f9caf4feb7edbdbe3097e29d60550d84/wf_api_client-0.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "039f8d74ff395093f850fffa08aedb39", "sha256": "c26dd0dd0b142c2f4b7a32358f027d7f8d994de232da2d3c4cbebce6f3aa5ec1" }, "downloads": -1, "filename": "wf-api-client-0.1.tar.gz", "has_sig": false, "md5_digest": "039f8d74ff395093f850fffa08aedb39", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9099, "upload_time": "2015-06-03T19:33:53", "url": "https://files.pythonhosted.org/packages/1d/ef/7c55797c80130ba667c495268561cfacac4d50a9853a6d25ba38c22c70bf/wf-api-client-0.1.tar.gz" } ], "0.2": [ { "comment_text": "", "digests": { "md5": "83eb129ca54dfa758f9d9a832879126a", "sha256": "753d8ddcbbcdfa02b743d7927adbd51f17b74774fbca22a7d2685805a0e911af" }, "downloads": -1, "filename": "wf_api_client-0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "83eb129ca54dfa758f9d9a832879126a", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 11968, "upload_time": "2015-06-04T03:20:02", "url": "https://files.pythonhosted.org/packages/10/1c/cb7fd51f6b61c4141295f47184090b2922bce60f2c2308230a3079ddd489/wf_api_client-0.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "d730179f26fd922e4b751c94514ca7e4", "sha256": "ae95ae365de8badae43d503d0a62367eb4bd04f8278de4ae250a8269dd63cd70" }, "downloads": -1, "filename": "wf-api-client-0.2.tar.gz", "has_sig": false, "md5_digest": "d730179f26fd922e4b751c94514ca7e4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9116, "upload_time": "2015-06-04T03:20:05", "url": "https://files.pythonhosted.org/packages/69/c3/c81482712e78f2c053b22cbc35b19be30a703f5af8bf8807982ea49ba825/wf-api-client-0.2.tar.gz" } ], "0.3": [ { "comment_text": "", "digests": { "md5": "a04627784606d5290577ad87603ad506", "sha256": "8fb53b5c5f83c47605d8018b146d4eaa05de027ed10ed1582c98a686a140d80e" }, "downloads": -1, "filename": "wf_api_client-0.3-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "a04627784606d5290577ad87603ad506", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 12623, "upload_time": "2015-06-05T01:23:01", "url": "https://files.pythonhosted.org/packages/34/29/8db3eb30311b8593feab0a8b5e433354d459e5bfd13696a4fce47cd9edf8/wf_api_client-0.3-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "55188e63f8b0c1136d7c82fd8dba26d6", "sha256": "26ac0956a564c77f2b8e41946733c4a922193e867acf0a583bd68d08ba81cd1c" }, "downloads": -1, "filename": "wf-api-client-0.3.tar.gz", "has_sig": false, "md5_digest": "55188e63f8b0c1136d7c82fd8dba26d6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9754, "upload_time": "2015-06-05T01:23:05", "url": "https://files.pythonhosted.org/packages/3e/05/dda8476926797d8c3c49283d6600f31fa8a0108eebd554e9c7162b5ecd2f/wf-api-client-0.3.tar.gz" } ], "1.0": [ { "comment_text": "", "digests": { "md5": "e82d2e50ddae785ac0e72d987be7e26a", "sha256": "27759484bb4fa303d6a595b81248b6deb84fc69c929e83fde74ad92e4a45c49b" }, "downloads": -1, "filename": "wf_api_client-1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "e82d2e50ddae785ac0e72d987be7e26a", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 17238, "upload_time": "2015-07-02T00:25:42", "url": "https://files.pythonhosted.org/packages/d2/6d/7b48b3362ef0069c07b7a6e2a6ebfd4ffeb742a553bd492a22d091baba19/wf_api_client-1.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "fe188cbb8e3a5cb78e23f7f757a80aeb", "sha256": "891160f540d10b94e9e52a48f26cd891f6760424ae1c01da7db4a2854593b6e3" }, "downloads": -1, "filename": "wf-api-client-1.0.tar.gz", "has_sig": false, "md5_digest": "fe188cbb8e3a5cb78e23f7f757a80aeb", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14099, "upload_time": "2015-07-02T00:25:45", "url": "https://files.pythonhosted.org/packages/52/8f/94b7a2f43a51450c65b7759657a262e4f87d33848fb991feec0029d63a3f/wf-api-client-1.0.tar.gz" } ], "1.0.1": [ { "comment_text": "", "digests": { "md5": "d213b425f05fd050e6d0bf2150923b30", "sha256": "2c2b7afac4b3950743c8216bf91b4be8ae8de8fe92c03288d8c5c2aed9124c1f" }, "downloads": -1, "filename": "wf_api_client-1.0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "d213b425f05fd050e6d0bf2150923b30", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 17268, "upload_time": "2015-07-02T00:39:59", "url": "https://files.pythonhosted.org/packages/cd/f2/736218a9d4351174dcc5768c301fd769bd70199b27baccb9e96047c6e8c4/wf_api_client-1.0.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "6f3b7a786679ab8e4a7a341a7d30ca04", "sha256": "a58df84c290fc2ff3f5f52c8cdf7506a88af88eb7f957e0f2ccfba2460056a02" }, "downloads": -1, "filename": "wf-api-client-1.0.1.tar.gz", "has_sig": false, "md5_digest": "6f3b7a786679ab8e4a7a341a7d30ca04", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14106, "upload_time": "2015-07-02T00:40:03", "url": "https://files.pythonhosted.org/packages/cf/fe/5bfce4371b374ded82fe39930e1d9975bc54f7cb7d3b7a5d1ff8b75b0daa/wf-api-client-1.0.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "d213b425f05fd050e6d0bf2150923b30", "sha256": "2c2b7afac4b3950743c8216bf91b4be8ae8de8fe92c03288d8c5c2aed9124c1f" }, "downloads": -1, "filename": "wf_api_client-1.0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "d213b425f05fd050e6d0bf2150923b30", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 17268, "upload_time": "2015-07-02T00:39:59", "url": "https://files.pythonhosted.org/packages/cd/f2/736218a9d4351174dcc5768c301fd769bd70199b27baccb9e96047c6e8c4/wf_api_client-1.0.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "6f3b7a786679ab8e4a7a341a7d30ca04", "sha256": "a58df84c290fc2ff3f5f52c8cdf7506a88af88eb7f957e0f2ccfba2460056a02" }, "downloads": -1, "filename": "wf-api-client-1.0.1.tar.gz", "has_sig": false, "md5_digest": "6f3b7a786679ab8e4a7a341a7d30ca04", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14106, "upload_time": "2015-07-02T00:40:03", "url": "https://files.pythonhosted.org/packages/cf/fe/5bfce4371b374ded82fe39930e1d9975bc54f7cb7d3b7a5d1ff8b75b0daa/wf-api-client-1.0.1.tar.gz" } ] }