-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
23 changed files
with
612 additions
and
59 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,4 +6,5 @@ __pycache__/ | |
|
||
*.skippercfg | ||
/dist | ||
NOTES.md | ||
NOTES.md | ||
.coverage |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,10 @@ | ||
from flask import Flask | ||
app = Flask(__name__) | ||
|
||
|
||
@app.route("/") | ||
def hello(): | ||
return "Hello World! v2" | ||
return "Hello World! v10" | ||
|
||
if __name__ == "__main__": | ||
app.run(host='0.0.0.0', port=5000) | ||
app.run(host='0.0.0.0', port=5000) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,17 @@ | ||
name: demo | ||
services: | ||
web: | ||
build: . | ||
repo: | ||
name: cameronmaske/flask-web | ||
groups: | ||
demo: | ||
size: medium | ||
web: | ||
size: t1.m | ||
loadbalance: | ||
- "80:80" | ||
instances: 1 | ||
scale: 2 | ||
regions: | ||
- us-east-1 | ||
- us-west-1 | ||
services: | ||
web: | ||
build: . | ||
loadbalance: | ||
- "80:8000" | ||
- redis | ||
redis: | ||
image: dockerfiles/redis | ||
loadbalance: | ||
- "1234:1234" | ||
- web |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
pytest | ||
pytest-cov | ||
python-coveralls | ||
mock==1.0.1 | ||
mock==1.0.1 | ||
HTTPretty |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,19 @@ | ||
class Host(object): | ||
from skipper.hosts import BaseHost | ||
|
||
|
||
class Host(BaseHost): | ||
requirements = { | ||
'field': 'AWS', | ||
'message': """As this is your first time running skipper, we need to store your some AWS Security Credentials. | ||
Please visit https://console.aws.amazon.com/iam/home?#security_credential | ||
Under Access Keys, click Create New Access Key.""", | ||
'keys': { | ||
'ACCESS_KEY': "Enter your Access Key ID", | ||
'SECRET_KEY': "Enter your Secret Access Key", | ||
} | ||
} | ||
|
||
def __init__(self, creds=None): | ||
self.creds = creds | ||
|
||
|
||
host = Host() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import requests | ||
import docker | ||
import os | ||
|
||
from logger import capture_events, EventError | ||
|
||
|
||
class RepoNoPermission(Exception): | ||
pass | ||
|
||
|
||
class RepoNotFound(Exception): | ||
pass | ||
|
||
|
||
class Repo(object): | ||
def __init__(self, name, registry="index.docker.io", tag=None): | ||
self.name = name | ||
self.registry = registry | ||
self.tag = tag | ||
|
||
def get_tags(self): | ||
""" | ||
Attempts to retrieve all the tags associated with a repo. | ||
""" | ||
r = requests.get("https://%s/v1/repositories/%s/tags" % (self.registry, self.name)) | ||
if r.status_code == 404: | ||
raise RepoNotFound("No such repo %s (on %s)" % (self.name, self.registry)) | ||
return r.json() | ||
|
||
def upload(self, image_id, tag): | ||
""" | ||
Uploads a tagged version to the repo. | ||
""" | ||
client = docker.Client(os.environ.get('DOCKER_HOST')) | ||
client.tag(image_id, repository=self.name, tag=tag) | ||
output = client.push(self.name, stream=True) | ||
try: | ||
capture_events(output) | ||
except EventError as e: | ||
if '401' in e.message: | ||
raise RepoNoPermission('You currently do not have access to %s.\nPlease try logging in with `docker login`.' % self.name) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,29 +1,63 @@ | ||
import click | ||
from click.exceptions import FileError, ClickException | ||
|
||
from project import Project | ||
from project import Project, NoSuchService | ||
from hosts import get_host | ||
from creds import get_creds | ||
from creds import creds | ||
from conf import get_conf | ||
from logger import log | ||
from builder import RepoNoPermission | ||
|
||
|
||
class CLIProject(Project): | ||
exception = ClickException | ||
|
||
def __init__(self): | ||
try: | ||
self.conf = get_conf() | ||
except IOError as e: | ||
raise FileError(e.filename, hint='Are you in the right directory?') | ||
|
||
try: | ||
self.name = self.conf['name'] | ||
except KeyError: | ||
raise ClickException('No name in skipper.yml') | ||
|
||
self.services = [] | ||
for name, details in self.conf['services'].items(): | ||
try: | ||
self.services.append( | ||
self.make_service(name=name, **details)) | ||
except TypeError as e: | ||
raise ClickException("%s: %s" % (name, e.message)) | ||
|
||
self.host = get_host(self.conf.get('host', 'aws')) | ||
self.host.creds = creds | ||
|
||
|
||
pass_config = click.make_pass_decorator(CLIProject, ensure=True) | ||
|
||
|
||
@click.group() | ||
def cli(): | ||
@click.option('--silent', is_flag=True) | ||
@pass_config | ||
def cli(project, silent): | ||
""" | ||
Doc string describing the CLI at a glance. | ||
""" | ||
log.propagate = silent | ||
|
||
|
||
@cli.command() | ||
@click.argument('groups', nargs=-1, required=False) | ||
def deploy(groups): | ||
@click.argument('services', nargs=-1, required=False) | ||
@pass_config | ||
def build(project, services): | ||
""" | ||
Doc string describing the deploy. | ||
Build and upload service(s). | ||
""" | ||
creds = get_creds() | ||
conf = get_conf() | ||
host = get_host(conf.get('host', 'aws')) | ||
host.creds = creds | ||
project = Project(name=conf['name'], host=host) | ||
for group in conf['groups']: | ||
project.make_group(group) | ||
raise NotImplementedError("Deploy is still a work in progress.") | ||
try: | ||
services = project.filter_services(services) | ||
for service in services: | ||
service.push() | ||
except (RepoNoPermission, NoSuchService) as e: | ||
raise ClickException(e.message) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import os | ||
import docker | ||
|
||
|
||
def _docker(): | ||
""" | ||
Cached Docker client. | ||
Approach taken from https://github.com/andreasjansson/head-in-the-clouds/blob/master/headintheclouds/ec2.py#L327 | ||
""" | ||
if not hasattr(_docker, 'client'): | ||
_docker.client = docker.Client(os.environ.get('DOCKER_HOST')) | ||
return _docker.client |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,21 @@ | ||
import click | ||
from utils import contains_keys | ||
|
||
|
||
def get_host(host): | ||
""" | ||
Based on the host agrumement passed in, determine which host to pass back. | ||
""" | ||
# WIP: Only aws for now! | ||
from skipper.aws.host import host | ||
return host | ||
|
||
|
||
class BaseHost(object): | ||
def check_requirements(self): | ||
field = self.requirements['field'] | ||
if not contains_keys(self.requirements['keys'], self.creds[field]): | ||
click.utils.echo(self.requirements['message']) | ||
for key, message in self.requirements['keys'].items(): | ||
self.creds[field][key] = click.prompt(message) | ||
self.creds.save() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
def parse_port(ports_string): | ||
""" | ||
Turns "80:80" -> {80: 80} | ||
""" | ||
guest, host = ports_string.split(':') | ||
ports = {} | ||
ports[int(guest)] = int(host) | ||
return ports |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import logging | ||
import json | ||
|
||
console = logging.StreamHandler() | ||
|
||
log = logging.getLogger('skipper') | ||
log.setLevel(logging.INFO) | ||
log.addHandler(console) | ||
log.propagate = False | ||
|
||
|
||
class EventError(Exception): | ||
pass | ||
|
||
|
||
def capture_events(stream): | ||
""" | ||
Prints out the output from various Docker client commands. | ||
A stripped down version of Fig's `stream_output` | ||
""" | ||
events = [] | ||
for line in stream: | ||
try: | ||
line = json.loads(line) | ||
if line.get('stream'): | ||
log.info(line['stream'].replace('\n', '')) | ||
events.append(line['stream']) | ||
elif line.get('status'): | ||
log.info(line['status']) | ||
elif line.get('errorDetail'): | ||
raise EventError(line.get('errorDetail').get('message')) | ||
except ValueError as e: | ||
log.debug(e) | ||
return events |
Oops, something went wrong.