{ "info": { "author": "Adam Cath", "author_email": "adam.cath@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Environment :: MacOS X", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 2.7", "Topic :: Software Development", "Topic :: Utilities" ], "description": "Overview\n========\n\nMicroservices are great, but running them on your dev box is annoying.\nEach one has its own commands to start and stop, check status - and how\nare you supposed to know where the logs are?\n\nads fixes this by requiring each participating service to expose a\nsimple uniform interface for the most common commands: start, stop,\nstatus, and log locations.\n\nTo use ads, drop a file called ``ads.yml`` in each service's directory:\n\n::\n\n start_cmd:\n gradle run > obscure/logs/dir/out &\n # ads can be used with any build system - cmds are just bash\n\n stop_cmd:\n pgrep -f ninja-service | xargs kill -9\n # Still the most reliable way to kill a process\n\n status_cmd:\n pgrep -f ninja-service\n # Exit status indicates whether any process matched\n\n log_paths:\n - obscure/logs/dir/*\n - even/more/secret/logs/dir/**/ninja.log\n # Note the glob support\n\n description: \n Web service that turns your ordinary app into badass rockstart tech.\n # Optional but a good idea\n\nThere are a few more fields, but this will get you started.\n\nCreate one more file called ``adsroot.yml``, in the root of your\ncodebase:\n\n::\n\n # Actually, you don't need to put anything in it yet.\n # The existence of the file is sufficient.\n\nNow you can run ads from anywhere in the codebase and get at any of the\nservices.\n\n::\n\n $ cd /anywhere/in/codebase\n $ ads list\n ninja: Web service that turns your ordinary app into badass rockstart tech.\n\nOnce you've \"adsified\" a bunch of services, ads makes it really\nconvenient to operate on several at once.\n\n::\n\n $ ads status\n --- db: not running\n --- ninja: not running\n --- pirate: not running\n\n $ ads up ninja pirate\n --- Starting [ninja, pirate]\n --- Starting ninja\n --- Starting pirate\n\nGetting started\n===============\n\nDependencies\n~~~~~~~~~~~~\n\n- ads has been tested with python 2.7.8 on Mac OS Yosemite-El Capitan\n- python\n- pip: install with ``easy_install pip``\n- shell stuff available on any Unixy OS (``find``, ``bash``, ``tail``,\n ``cat``)\n\nInstalling\n~~~~~~~~~~\n\n- ``pip install adscli``\n\nA brief tour\n~~~~~~~~~~~~\n\nIf you want to follow along, install ads (see \"Installing\") and clone\nthis repo to get the sample project\n(``git clone https://github.com/adamcath/ads``).\n\n::\n\n $ cd ads/doc/samples/intro\n\nWhat do we got here?\n\n::\n\n $ ads list\n All services in current project (intro):\n ninja: Slices and chops, mostly\n db: (No description)\n pirate: Walks the plank and shivers timbers\n ...\n # We'll come back to the rest of this stuff\n\nLet's start a service:\n\n::\n\n $ ads up -v ninja\n --- Starting [ninja]\n --- Checking if ninja is already running\n cd /intro/./ninja\n pgrep -f ninja.sh\n --- Starting ninja\n cd /intro/./ninja\n mkdir logs\n bash ninja.sh >logs/ninja.out 2>logs/ninja.err &\n --- Started ninja\n\n-v makes ads show you what it's doing. You can usually omit it.\n\nUp is idempotent, so you don't have to remember what state it was in:\n\n::\n\n $ ads up -v ninja\n --- Starting [ninja]\n --- Checking if ninja is already running\n cd /intro/./ninja\n pgrep -f ninja.sh\n 4743\n --- ninja is already running\n\nToo much chopping; let's stop ninja:\n\n::\n\n $ ads down -v ninja\n --- Checking if ninja is running\n cd /intro/./ninja\n pgrep -f ninja.sh\n 4863\n --- Stopping ninja\n cd /intro/./ninja\n pgrep -f ninja.sh | xargs kill -9\n --- Stopped ninja\n\nI forget, is ninja up?\n\n::\n\n $ ads status -v ninja\n cd /intro/./ninja\n pgrep -f ninja.sh\n --- ninja: not running\n\nAny command can take a list of services:\n\n::\n\n $ ads up -v ninja pirate\n --- Starting [ninja, pirate]\n ...\n\nIf you don't say which service, ads does 'em all (you can override this\nby setting ``default`` in adsroot.yml or ~/.ads\\_profile.yml):\n\n::\n\n $ ads status\n --- db: not running\n --- ninja: ok\n --- pirate: ok\n\nLet's tail the logs:\n\n::\n\n $ ads logs\n cd /Users/arc/Projects/ads/doc/samples/intro\n tail -F ninja/logs/ninja.err \\\n ninja/logs/ninja.out \\\n pirate/logs/treasure-chest/pirate.err \\\n pirate/logs/treasure-chest/pirate.log\n\n ==> ninja/logs/ninja.err <==\n\n ==> ninja/logs/ninja.out <==\n Chop!\n Chop!\n\n ==> pirate/logs/treasure-chest/pirate.err <==\n\n ==> pirate/logs/treasure-chest/pirate.log <==\n Arrrrr!\n Arrrrr!\n\ntail -F works pretty well with multiple log files, but if you want to\nfocus on one, just specify the service.\n\nThe logs command has some cool variants:\n\n::\n\n $ ads help logs\n usage: logs [-h] [--tail | --list | --cat] [--general | --errors]\n [service [service ...]]\n ...\n --tail (Default) Follow the logs with tail -f\n --list List the paths of all log files which exist (useful for\n pipelining)\n --cat Dump the contents of all log files to stdout\n\nFAQ\n===\n\nMy service needs some one-time setup before it runs. How do I tell ads this?\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nThis is a common scenario; for example, you may need to set up the DB\nschema before you can start anything. ads doesn't have a solution for\nthis yet. Your service should probably try to detect the missing\nprecondition, refuse to start, and direct the user to the relevant wiki\npage.\n\nDoes ads let me define dependencies?\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nNo. This is one area where ads is opinionated: in production, any\nservice could go down, and the other services would have to be able to\ndeal with that. The dependant service might go unhealthy, but it\nshouldn't crash. Therefore, starting in an arbitrary order is a special\ncase of the general problem, which you cannot avoid, of some services\nbeing up and others being down.\n\nIn other words, if a service can't even start without another running,\nthey're actually one service.\n\nWhat you *can* do is specify groups of services and easily start them\nall (see \"Groups\" below).\n\nCan I specify a \"build\" step separate from \"run\"?\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nNo. If running requires building, it should just do it. If that's slow,\nthen improve your project's build avoidance to reduce rebuilds.\n\nCan I use ads to run my services in production?\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nYou could, but it's probably not very useful. The main benefit of ads is\nthe ergonomics of running several services from source. In my\nexperience, this is not a big problem in production.\n\nWhy isn't this just...\n~~~~~~~~~~~~~~~~~~~~~~\n\npart of the build system?\n^^^^^^^^^^^^^^^^^^^^^^^^^\n\n- Building is a very general problem, and build systems are quite\n flexible. This flexibility comes at a cost: even in a well-factored\n build system, you always have to figure out which targets you're\n supposed to run. ads is a \"run\" system, not a build system, so it can\n be restricted to a fixed set of commands - the ones you need to run\n services.\n- Big projects often involve multiple languages and build systems. I\n wanted a uniform way to run them all.\n- It's fairly annoying to implement things like ``ads logs`` in most\n build systems.\n\nan init.d script (or similar)?\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nads is inspired by OS service managers, but:\n\n- I don't want to \"install\" each service on my dev box. That would\n raise awkward questions about what happens when I change the code. I\n want to run things straight from source.\n- init.d scripts are pretty fugly. Maybe other service managers are\n better; if so, I'd be curious to learn about them.\n- I suspect that if this were a good solution, people would be doing\n it.\n\nsome project-specific helper scripts?\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nIn my experience, code bases frequently evolve a set of helper scripts\nthat make it tolerable to deal with multiple projects. They work well\nwhen there's one command to rule them all, but then somebody wants a way\nto *just restart my stuff*. Now you add some commands to just do that.\nIt becomes very hard to prevent spaghetti unless you end up designing\nsomething like ads, which lets you freely compose commands with\nservices. But then...you could have just used ads!\n\ndocker/vagrant/virtualization tech x?\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nVirtualization solves a very different (and much deeper) set of problems\nthan ads. If you have multiple services running in VMs, you still need\nsomething to wrangle them. If everything you use is managed by\ndocker-compose, you might not need ads. But if some stuff is in docker,\nother is native, other in VMs, etc, ads is still useful.\n\nDevelopment\n===========\n\nInstalling from source\n~~~~~~~~~~~~~~~~~~~~~~\n\n- ``git clone https://github.com/adamcath/ads.git``\n- ``pip install -e .``\n\nRunning the automated tests\n~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n- Get the source\n- ``./unit_tests.sh && ./functional_tests.sh``\n\nAdvanced features\n=================\n\nGroups\n~~~~~~\n\nYou can define groups of services in ``adsroot.yml``:\n\n::\n\n groups:\n north-america:\n - usa\n - canada\n\nand then operate on the whole group at once:\n\n::\n\n $ ads up north-america\n\nGroups can contain other groups (but not cycles! Nice try!).", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/adamcath/ads", "keywords": "microservice tool launcher upstart init.d", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "adscli", "package_url": "https://pypi.org/project/adscli/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/adscli/", "project_urls": { "Homepage": "https://github.com/adamcath/ads" }, "release_url": "https://pypi.org/project/adscli/0.8.6/", "requires_dist": [ "pyyaml (>=3.11)" ], "requires_python": "", "summary": "Start, stop, and manage microservices in a codebase", "version": "0.8.6" }, "last_serial": 2083977, "releases": { "0.8.0": [], "0.8.1": [ { "comment_text": "", "digests": { "md5": "6a8050ddac4510a8da679409022dc3d0", "sha256": "ddc55f91309753d20e5572a17ee5bb83c8e59782690676cde960e3aa6867b39c" }, "downloads": -1, "filename": "adscli-0.8.1-py2-none-any.whl", "has_sig": false, "md5_digest": "6a8050ddac4510a8da679409022dc3d0", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 17727, "upload_time": "2016-04-09T23:28:51", "url": "https://files.pythonhosted.org/packages/98/ab/ea8fd9a9050c8f90a01748f6307c14f98dc067b29ac1422bd0b05f8255c6/adscli-0.8.1-py2-none-any.whl" } ], "0.8.2": [ { "comment_text": "", "digests": { "md5": "4a2b8cc1e70e863cd0dd6deaba5cbbf0", "sha256": "bbdb9630ef97b8abbf9e9d7bb82eb531d427bd87abf8aac1fa5ce8f12a5c01f5" }, "downloads": -1, "filename": "adscli-0.8.2-py2-none-any.whl", "has_sig": false, "md5_digest": "4a2b8cc1e70e863cd0dd6deaba5cbbf0", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 17727, "upload_time": "2016-04-09T23:45:22", "url": "https://files.pythonhosted.org/packages/2f/94/864786db8555c2a2ec2e61807859fb79f0b2352dcff2d70cfc7b2cd74fd3/adscli-0.8.2-py2-none-any.whl" } ], "0.8.3": [ { "comment_text": "", "digests": { "md5": "ea59b8bdbb695147aa2a9e42330024d4", "sha256": "d6197262cc555650ba7fa4d4ec4fe66c61528105cf4bb1352c218d4a8a1a8184" }, "downloads": -1, "filename": "adscli-0.8.3-py2-none-any.whl", "has_sig": false, "md5_digest": "ea59b8bdbb695147aa2a9e42330024d4", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 17721, "upload_time": "2016-04-09T23:53:46", "url": "https://files.pythonhosted.org/packages/8f/f7/b715446ee4bba7f9bc5915e2a11b0474f5163ff99b9eaee04bf6a71bd545/adscli-0.8.3-py2-none-any.whl" } ], "0.8.4": [ { "comment_text": "", "digests": { "md5": "2155cd89bed145c947fa2088774ef4b5", "sha256": "b0a0a1a22ed3f76501f98e581d5e514abb6af74eb713f7fb86b21b96957a8dc9" }, "downloads": -1, "filename": "adscli-0.8.4-py2-none-any.whl", "has_sig": false, "md5_digest": "2155cd89bed145c947fa2088774ef4b5", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 17729, "upload_time": "2016-04-10T00:12:47", "url": "https://files.pythonhosted.org/packages/14/7a/3b7f151d815aef3db0cb97ddcef0956a3035e6c0f1b7f78abdefacf4d88d/adscli-0.8.4-py2-none-any.whl" } ], "0.8.5": [ { "comment_text": "", "digests": { "md5": "5567dd832ab9c98669791f4326fbdfed", "sha256": "329211546936b4c22ee378dc3fe2f3aae292d0f01952b2e54b43eeda77ca928b" }, "downloads": -1, "filename": "adscli-0.8.5-py2-none-any.whl", "has_sig": false, "md5_digest": "5567dd832ab9c98669791f4326fbdfed", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 17628, "upload_time": "2016-04-10T00:21:32", "url": "https://files.pythonhosted.org/packages/31/57/07fff06566b9add0d4db5b7641d6097ae60d0bdf01d0154c2fc6d93e10be/adscli-0.8.5-py2-none-any.whl" } ], "0.8.6": [ { "comment_text": "", "digests": { "md5": "313f9d2f5e29127368da2c7575eacf5d", "sha256": "1b98d598cee827231f92e7e7c80156b012d630b24dc264d2276edc126c3fb250" }, "downloads": -1, "filename": "adscli-0.8.6-py2-none-any.whl", "has_sig": false, "md5_digest": "313f9d2f5e29127368da2c7575eacf5d", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 18113, "upload_time": "2016-04-26T03:32:51", "url": "https://files.pythonhosted.org/packages/c0/09/df1fa27fc88b5726473ac9946145dd2c9f70b456fbe029031a6a705f19f4/adscli-0.8.6-py2-none-any.whl" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "313f9d2f5e29127368da2c7575eacf5d", "sha256": "1b98d598cee827231f92e7e7c80156b012d630b24dc264d2276edc126c3fb250" }, "downloads": -1, "filename": "adscli-0.8.6-py2-none-any.whl", "has_sig": false, "md5_digest": "313f9d2f5e29127368da2c7575eacf5d", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 18113, "upload_time": "2016-04-26T03:32:51", "url": "https://files.pythonhosted.org/packages/c0/09/df1fa27fc88b5726473ac9946145dd2c9f70b456fbe029031a6a705f19f4/adscli-0.8.6-py2-none-any.whl" } ] }