Skip to content
This repository has been archived by the owner on Nov 30, 2021. It is now read-only.

Commit

Permalink
merging layout changes with current master re #34
Browse files Browse the repository at this point in the history
  • Loading branch information
Gabriel Monroy committed Jul 26, 2013
2 parents c672ec4 + 2a14dc7 commit 0187064
Show file tree
Hide file tree
Showing 44 changed files with 516 additions and 904 deletions.
5 changes: 5 additions & 0 deletions .coveragerc
@@ -0,0 +1,5 @@
[run]
omit =
*/venv/*
*/virtualenv/*
ignore_errors = True
7 changes: 5 additions & 2 deletions .gitignore
Expand Up @@ -39,8 +39,11 @@ nosetests.xml

# Deis' config file
deis/local_settings.py

# Misc.
.DS_Store
htmlcov/
.ruby-version
venv/
.vagrant
.ruby-version
.DS_Store

9 changes: 7 additions & 2 deletions .travis.yml
Expand Up @@ -19,6 +19,7 @@ before_install:

install:
- "pip install -r requirements.txt --use-mirrors"
- "pip install coveralls --use-mirrors"

before_script:
- "psql -c 'create database deis_testing;' -U postgres"
Expand All @@ -34,7 +35,11 @@ before_script:
'PORT': '',
}
}
SECRET_KEY = ')9$y9(@_r!+ai=ub)wsp2!!vs4i67x7ke9!jaljgf1_@rw421='
SECRET_KEY = ')9$y9(@_r!+ai=ub)wsp2!!vsfaker7ke9!jaljgf1_@rw421='
EOF
script: "make test"
script:
- coverage run manage.py test api celerytasks web

after_success:
- coveralls
15 changes: 7 additions & 8 deletions Makefile
Expand Up @@ -3,15 +3,14 @@ all:

db:
python manage.py syncdb --noinput
python manage.py migrate

test:
python manage.py test api web
python manage.py test api celerytasks web

task:
python manage.py test celerytasks
coverage:
coverage run manage.py test api celerytasks web
coverage html

pep8:
pep8 api celerytasks deis web

pyflakes:
pyflakes api celerytasks deis web
flake8:
flake8
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -6,3 +6,4 @@ Your PaaS. Your Rules.

Current status:
[![Build Status](https://travis-ci.org/opdemand/deis.png)](https://travis-ci.org/opdemand/deis)
[![Coverage Status](https://coveralls.io/repos/opdemand/deis/badge.png?branch=master)](https://coveralls.io/r/opdemand/deis?branch=master)
4 changes: 3 additions & 1 deletion api/fields.py
Expand Up @@ -88,6 +88,8 @@ class ParamsField(JSONField):
A text field that accepts a JSON object, used for storing provider
API Parameters.
"""
pass


class CloudInitField(YAMLField):
"""
Expand All @@ -107,7 +109,7 @@ class NodeStatusField(JSONField):

try:
from south.modelsinspector import add_introspection_rules
# Tell the South schema migration tool to handle a UuidField.
# Tell the South schema migration tool to handle our custom fields.
add_introspection_rules([], [r'^api\.fields\.UuidField'])
add_introspection_rules([], [r'^api\.fields\.EnvVarsField'])
add_introspection_rules([], [r'^api\.fields\.DataBagField'])
Expand Down
5 changes: 4 additions & 1 deletion api/migrations/0001_initial.py
@@ -1,4 +1,7 @@
# -*- coding: utf-8 -*-

# flake8: noqa

import datetime
from south.db import db
from south.v2 import SchemaMigration
Expand Down Expand Up @@ -459,4 +462,4 @@ def backwards(self, orm):
}
}

complete_apps = ['api']
complete_apps = ['api']
@@ -1,4 +1,7 @@
# -*- coding: utf-8 -*-

# flake8: noqa

import datetime
from south.db import db
from south.v2 import SchemaMigration
Expand Down Expand Up @@ -248,4 +251,4 @@ def backwards(self, orm):
}
}

complete_apps = ['api']
complete_apps = ['api']
50 changes: 29 additions & 21 deletions api/models.py
Expand Up @@ -9,7 +9,10 @@
from __future__ import unicode_literals
import importlib
import json
import os
import yaml

from celery.canvas import group
from django.conf import settings
from django.db import models
from django.db.models.signals import post_save
Expand All @@ -19,18 +22,16 @@
from rest_framework.authtoken.models import Token

from api import fields
from celerytasks import chef, controller
from celery.canvas import group
import yaml
import os.path
from celerytasks import controller


# define custom signals
scale_signal = Signal(providing_args=['formation', 'user'])
release_signal = Signal(providing_args=['formation', 'user'])


def import_tasks(provider_type):
"Return Celery tasks for a given provider type"
"""Return Celery tasks for a given provider type"""
try:
tasks = importlib.import_module('celerytasks.'+provider_type)
except ImportError as e:
Expand Down Expand Up @@ -199,15 +200,16 @@ def publish(self, **kwargs):
'ssh_keys': {},
'admins': [],
'formations': {}
}
}
# add all ssh keys on the system
for key in Key.objects.all():
key_id = '{0}_{1}'.format(key.owner.username, key.id)
key_id = "{0}_{1}".format(key.owner.username, key.id)
databag['ssh_keys'][key_id] = key.public
# TODO: add sharing-based key lookup, for now just owner's keys
for formation in formations:
keys = databag['formations'][formation.id] = []
owner_keys = [ '{0}_{1}'.format(k.owner.username, k.id) for k in formation.owner.key_set.all() ]
owner_keys = ["{0}_{1}".format(
k.owner.username, k.id) for k in formation.owner.key_set.all()]
keys.extend(owner_keys)
# call a celery task to update gitosis
if settings.CHEF_ENABLED:
Expand Down Expand Up @@ -243,7 +245,7 @@ class Formation(UuidAuditedModel):
id = models.SlugField(max_length=64)
layers = fields.JSONField(default='{}', blank=True)
containers = fields.JSONField(default='{}', blank=True)

class Meta:
unique_together = (('owner', 'id'),)

Expand Down Expand Up @@ -325,7 +327,7 @@ def balance(self, **kwargs):
if containers_balanced:
self.converge(databag)
return databag

def _balance_containers(self, **kwargs):
runtime_nodes = self.node_set.filter(layer__id='runtime').order_by('created')
if len(runtime_nodes) < 2:
Expand Down Expand Up @@ -359,7 +361,7 @@ def _balance_containers(self, **kwargs):
type=container_type,
num=container_num,
node=n_under)
container_num +=1
container_num += 1
# delete the oldest container from the most over-utilized node
c = n_over.container_set.filter(type=container_type).order_by('created')[0]
c.delete()
Expand All @@ -369,10 +371,16 @@ def _balance_containers(self, **kwargs):
n_map.setdefault(ct, []).append(n)
changed = True
return changed

def __str__(self):
return self.id


def prepare_provider(self, *args, **kwargs):
tasks = import_tasks(self.flavor.provider.type)
args = (self.id, self.flavor.provider.creds.copy(),
self.flavor.params.copy())
return tasks.prepare_formation.subtask(args)

def calculate(self):
"Return a Chef data bag item for this formation"
release = self.release_set.all().order_by('-created')[0]
Expand All @@ -388,7 +396,7 @@ def calculate(self):
d['release']['build']['procfile'] = release.build.procfile
# calculate proxy
d['proxy'] = {}
d['proxy']['algorithm'] = 'round_robin'
d['proxy']['algorithm'] = 'round_robin'
d['proxy']['port'] = 80
d['proxy']['backends'] = []
# calculate container formation
Expand All @@ -397,7 +405,8 @@ def calculate(self):
# all container types get an exposed port starting at 5001
port = 5000 + c.num
d['containers'].setdefault(c.type, {})
d['containers'][c.type].update({ c.num: "{0}:{1}".format(c.node.id, port) })
d['containers'][c.type].update(
{c.num: "{0}:{1}".format(c.node.id, port)})
# only proxy to 'web' containers
if c.type == 'web':
d['proxy']['backends'].append("{0}:{1}".format(c.node.fqdn, port))
Expand Down Expand Up @@ -628,7 +637,7 @@ class Config(UuidAuditedModel):
owner = models.ForeignKey(settings.AUTH_USER_MODEL)
formation = models.ForeignKey('Formation')
version = models.PositiveIntegerField(default=1)

values = fields.EnvVarsField(default='{}', blank=True)

class Meta:
Expand All @@ -649,7 +658,7 @@ class Build(UuidAuditedModel):
owner = models.ForeignKey(settings.AUTH_USER_MODEL)
formation = models.ForeignKey('Formation')
version = models.PositiveIntegerField(default=1)

sha = models.CharField('SHA', max_length=255, blank=True)
output = models.TextField(blank=True)

Expand Down Expand Up @@ -678,7 +687,7 @@ class Release(UuidAuditedModel):
owner = models.ForeignKey(settings.AUTH_USER_MODEL)
formation = models.ForeignKey('Formation')
version = models.PositiveIntegerField(default=1)

config = models.ForeignKey('Config')
image = models.CharField(max_length=256, default='ubuntu')
# build only required for heroku-style apps
Expand All @@ -689,7 +698,7 @@ class Meta:

def __str__(self):
return '{0}-v{1}'.format(self.formation.id, self.version)

def rollback(self):
# create a rollback log entry
# call run
Expand All @@ -700,7 +709,7 @@ def rollback(self):
def new_release(sender, **kwargs):
formation, user = kwargs['formation'], kwargs['user']
last_release = Release.objects.filter(
formation=formation).order_by('-created')[0]
formation=formation).order_by('-created')[0]
image = kwargs.get('image', last_release.image)
config = kwargs.get('config', last_release.config)
build = kwargs.get('build', last_release.build)
Expand Down Expand Up @@ -776,4 +785,3 @@ def create_auth_token(sender, instance=None, created=False, **kwargs):
if created:
# pylint: disable=E1101
Token.objects.create(user=instance)

26 changes: 12 additions & 14 deletions api/serializers.py
Expand Up @@ -5,13 +5,11 @@

from __future__ import unicode_literals

from django.contrib.auth.models import User
from rest_framework import serializers

from api import models, utils

from django.contrib.auth.models import User



class UserSerializer(serializers.ModelSerializer):

Expand All @@ -20,8 +18,8 @@ class UserSerializer(serializers.ModelSerializer):
class Meta:
"""Metadata options for a UserSerializer."""
model = User
read_only_fields = ('is_superuser', 'is_staff', 'groups', 'user_permissions',
'last_login', 'date_joined')
read_only_fields = ('is_superuser', 'is_staff', 'groups',
'user_permissions', 'last_login', 'date_joined')

@property
def data(self):
Expand Down Expand Up @@ -63,7 +61,7 @@ class FlavorSerializer(serializers.ModelSerializer):

owner = serializers.Field(source='owner.username')
provider = serializers.SlugRelatedField(slug_field='id')

class Meta:
"""Metadata options for a FlavorSerializer."""
model = models.Flavor
Expand All @@ -76,9 +74,9 @@ class ConfigSerializer(serializers.ModelSerializer):

owner = serializers.Field(source='owner.username')
formation = serializers.SlugRelatedField(slug_field='id')
values = serializers.ModelField(model_field=models.Config()._meta.get_field('values'),
required=False)
values = serializers.ModelField(
model_field=models.Config()._meta.get_field('values'), required=False)

class Meta:
"""Metadata options for a ConfigSerializer."""
model = models.Config
Expand All @@ -91,7 +89,7 @@ class BuildSerializer(serializers.ModelSerializer):

owner = serializers.Field(source='owner.username')
formation = serializers.SlugRelatedField(slug_field='id')

class Meta:
"""Metadata options for a BuildSerializer."""
model = models.Build
Expand All @@ -106,7 +104,7 @@ class ReleaseSerializer(serializers.ModelSerializer):
formation = serializers.SlugRelatedField(slug_field='id')
config = serializers.SlugRelatedField(slug_field='uuid')
build = serializers.SlugRelatedField(slug_field='uuid', required=False)

class Meta:
"""Metadata options for a ReleaseSerializer."""
model = models.Release
Expand All @@ -119,7 +117,7 @@ class FormationSerializer(serializers.ModelSerializer):

owner = serializers.Field(source='owner.username')
id = serializers.SlugField(default=utils.generate_app_name)

class Meta:
"""Metadata options for a FormationSerializer."""
model = models.Formation
Expand Down Expand Up @@ -156,7 +154,7 @@ class NodeSerializer(serializers.ModelSerializer):
owner = serializers.Field(source='owner.username')
formation = serializers.SlugRelatedField(slug_field='id')
layer = serializers.SlugRelatedField(slug_field='id')

class Meta:
"""Metadata options for a NodeSerializer."""
model = models.Node
Expand All @@ -170,7 +168,7 @@ class ContainerSerializer(serializers.ModelSerializer):
owner = serializers.Field(source='owner.username')
formation = serializers.SlugRelatedField(slug_field='id')
node = serializers.SlugRelatedField(slug_field='uuid')

class Meta:
"""Metadata options for a ContainerSerializer."""
model = models.Container
Expand Down

0 comments on commit 0187064

Please sign in to comment.