| @ -0,0 +1,9 @@ | |||
| .coverage | |||
| .cache | |||
| .ropeproject | |||
| *.py[co] | |||
| *.log | |||
| build | |||
| dist | |||
| docs/_* | |||
| *.egg-info | |||
| @ -0,0 +1,21 @@ | |||
| The MIT License (MIT) | |||
| Copyright (c) 2013 Brett Langdon <brett@blangdon.com> | |||
| Permission is hereby granted, free of charge, to any person obtaining a copy | |||
| of this software and associated documentation files (the "Software"), to deal | |||
| in the Software without restriction, including without limitation the rights | |||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
| copies of the Software, and to permit persons to whom the Software is | |||
| furnished to do so, subject to the following conditions: | |||
| The above copyright notice and this permission notice shall be included in | |||
| all copies or substantial portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||
| THE SOFTWARE. | |||
| @ -0,0 +1,4 @@ | |||
| include README.* setup.py setup.cfg | |||
| recursive-include employ *.py | |||
| global-exclude *.pyc | |||
| global-exclude *.pyo | |||
| @ -0,0 +1,7 @@ | |||
| employ | |||
| ====== | |||
| A distributed one time ec2 command execution and result aggregation framework. | |||
| What? Basically it is like [beeswithmachineguns](https://github.com/newsapps/beeswithmachineguns.git), but more generic. | |||
| This tool can be used for running commands other than `ab`. | |||
| @ -0,0 +1,77 @@ | |||
| #!/usr/bin/env python | |||
| """ | |||
| Employ instance to do your bidding | |||
| Usage: | |||
| employ help (commands | command <command> | regions) | |||
| employ run <command> [options] [<command_options> ...] | |||
| Global Options: | |||
| -h --help Show this message | |||
| --version Show the version number | |||
| Run Options: | |||
| -i NUM, --instances NUM Number of instances to start [default: 1] | |||
| -r REGION, --region REGION Which region to start the instances up on [default: us-east-1] | |||
| -n NAME, --name NAME Which name to assign to each new instance [default: employed] | |||
| Help Commands: | |||
| commands List all available commands | |||
| command <command> Print the docstring for the provided command | |||
| regions List all available regions names | |||
| """ | |||
| import sys | |||
| from docopt import docopt | |||
| import employ | |||
| import employ.manager | |||
| def command_doc(command): | |||
| all_commands = employ.manager.Manager.available_commands() | |||
| if all_commands.get(command): | |||
| print all_commands[command].__doc__ | |||
| else: | |||
| sys.exit("Unknown command: '%s'" % command) | |||
| def list_commands(command=None): | |||
| all_commands = employ.manager.Manager.available_commands() | |||
| print "List of Available Commands:" | |||
| for cls in all_commands: | |||
| print " %s" % cls | |||
| def list_regions(): | |||
| print "List of Available Regions:" | |||
| for region in sorted(employ.manager.Manager.available_regions()): | |||
| print " %s" % region | |||
| def run(arguments): | |||
| all_commands = employ.manager.Manager.available_commands() | |||
| if arguments["<command>"] not in all_commands: | |||
| sys.exit("Unknown command '%s'" % command) | |||
| command_cls = all_commands[arguments["<command>"]] | |||
| command = command_cls(*arguments["<command_options>"]) | |||
| manager = employ.manager.Manager( | |||
| num_instances=arguments["--instances"], | |||
| name=arguments["--name"], | |||
| region=arguments["--region"], | |||
| ) | |||
| with manager: | |||
| manager.run(command) | |||
| arguments = docopt(__doc__, help=True, version="employ %s" % employ.__version__) | |||
| if arguments["help"]: | |||
| if arguments["commands"]: | |||
| list_commands() | |||
| elif arguments["command"] and arguments["<command>"]: | |||
| command_doc(arguments["<command>"]) | |||
| elif arguments["regions"]: | |||
| list_regions() | |||
| elif arguments["run"]: | |||
| run(arguments) | |||
| @ -0,0 +1 @@ | |||
| __version__ = "0.1.0" | |||
| @ -0,0 +1,3 @@ | |||
| __all__ = ["ABCommand", "Command"] | |||
| from employ.commands.base import Command | |||
| from employ.commands.ab import ABCommand | |||
| @ -0,0 +1,29 @@ | |||
| from employ.commands import Command | |||
| class ABCommand(Command): | |||
| """ | |||
| Command used to run ApacheBench (ab) | |||
| Command Options: | |||
| <target> <requests> [<concurrency> <extra_args>] | |||
| Examples: | |||
| employ run ab http://127.0.0.1/test.html 1000 | |||
| employ run ab https://127.0.0.1:8000/test.html 1000 10 | |||
| employ run ab https://127.0.0.1:8000/test.html 1000 10 "-k -C 'cookie=1234'" | |||
| """ | |||
| name = "ab" | |||
| def __init__(self, target, requests, concurrency=1, extra_args=""): | |||
| self.target = target | |||
| self.requests = requests | |||
| self.concurrency = concurrency | |||
| self.extra_args = extra_args | |||
| super(ABCommand, self).__init__() | |||
| def command(self): | |||
| return "ab %s -n %s -c %s %s" % (self.target, self.requests, self.concurrency, self.extra_args) | |||
| def aggregate(self, results): | |||
| pass | |||
| @ -0,0 +1,5 @@ | |||
| class Command(object): | |||
| name = "command" | |||
| def run(self): | |||
| raise NotImplementedError() | |||
| @ -0,0 +1,40 @@ | |||
| import boto.ec2 | |||
| from employ import commands | |||
| class Manager(object): | |||
| def __init__(self, num_instances=1, name="deployed", region="us-east-1"): | |||
| self.instances = [] | |||
| self.num_instances = num_instances | |||
| self.name = name | |||
| self.region = region | |||
| def setup_instances(self): | |||
| print "starting %s instances named %s in region %s" % (self.num_instances, self.name, self.region) | |||
| __enter__ = setup_instances | |||
| def cleanup_instances(self): | |||
| print "tearing down instances" | |||
| def __exit__(self, type, value, traceback): | |||
| self.cleanup_instances() | |||
| @classmethod | |||
| def available_regions(cls): | |||
| for region in boto.ec2.regions(): | |||
| yield region.name | |||
| @classmethod | |||
| def available_commands(cls): | |||
| all_commands = {} | |||
| for cls in commands.__all__: | |||
| the_cls = getattr(commands, cls) | |||
| if the_cls.name == "command": | |||
| continue | |||
| all_commands[the_cls.name] = the_cls | |||
| return all_commands | |||
| def run(self, command): | |||
| print "running command '%s'" % command.command() | |||
| @ -0,0 +1,2 @@ | |||
| boto>=2.13.0 | |||
| docopt>=0.6.0 | |||
| @ -0,0 +1,28 @@ | |||
| #!/usr/bin/env python | |||
| from setuptools import setup, find_packages | |||
| from employ import __version__ | |||
| setup( | |||
| name="employ", | |||
| version=__version__, | |||
| author="Brett Langdon", | |||
| author_email="brett@blangdon.com", | |||
| packages=find_packages(), | |||
| install_requires=[ | |||
| "docopt>=0.6.0", | |||
| "boto>=2.13.0", | |||
| ], | |||
| setup_requires=[], | |||
| description="Distributed one time command execution and aggregation tool", | |||
| license="MIT", | |||
| url='https://github.com/brettlangdon/employ', | |||
| classifiers=[ | |||
| "Intended Audience :: Developers", | |||
| "Programming Language :: Python", | |||
| "Programming Language :: Python :: 2.6", | |||
| "Programming Language :: Python :: 2.7", | |||
| "License :: OSI Approved :: MIT License", | |||
| ], | |||
| ) | |||