pep8 fixes. Check for pep8 errors on Jenkins since now.
This commit is contained in:
parent
251f5bf976
commit
90e2a4e0dc
@ -3,9 +3,9 @@ import os
|
||||
import sys
|
||||
|
||||
if __name__ == "__main__":
|
||||
# sys.path.insert(0, os.getcwd())
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "nailgun.settings")
|
||||
# sys.path.insert(0, os.getcwd())
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "nailgun.settings")
|
||||
|
||||
from django.core.management import execute_from_command_line
|
||||
from django.core.management import execute_from_command_line
|
||||
|
||||
execute_from_command_line(sys.argv)
|
||||
execute_from_command_line(sys.argv)
|
||||
|
@ -14,101 +14,107 @@ _running = False
|
||||
_queue = Queue.Queue()
|
||||
_lock = threading.Lock()
|
||||
|
||||
|
||||
def _restart(path):
|
||||
_queue.put(True)
|
||||
prefix = 'monitor (pid=%d):' % os.getpid()
|
||||
print >> sys.stderr, '%s Change detected to \'%s\'.' % (prefix, path)
|
||||
print >> sys.stderr, '%s Triggering process restart.' % prefix
|
||||
os.kill(os.getpid(), signal.SIGINT)
|
||||
_queue.put(True)
|
||||
prefix = 'monitor (pid=%d):' % os.getpid()
|
||||
print >> sys.stderr, '%s Change detected to \'%s\'.' % (prefix, path)
|
||||
print >> sys.stderr, '%s Triggering process restart.' % prefix
|
||||
os.kill(os.getpid(), signal.SIGINT)
|
||||
|
||||
|
||||
def _modified(path):
|
||||
try:
|
||||
# If path doesn't denote a file and were previously
|
||||
# tracking it, then it has been removed or the file type
|
||||
# has changed so force a restart. If not previously
|
||||
# tracking the file then we can ignore it as probably
|
||||
# pseudo reference such as when file extracted from a
|
||||
# collection of modules contained in a zip file.
|
||||
try:
|
||||
# If path doesn't denote a file and were previously
|
||||
# tracking it, then it has been removed or the file type
|
||||
# has changed so force a restart. If not previously
|
||||
# tracking the file then we can ignore it as probably
|
||||
# pseudo reference such as when file extracted from a
|
||||
# collection of modules contained in a zip file.
|
||||
|
||||
if not os.path.isfile(path):
|
||||
return path in _times
|
||||
if not os.path.isfile(path):
|
||||
return path in _times
|
||||
|
||||
# Check for when file last modified.
|
||||
# Check for when file last modified.
|
||||
|
||||
mtime = os.stat(path).st_mtime
|
||||
if path not in _times:
|
||||
_times[path] = mtime
|
||||
mtime = os.stat(path).st_mtime
|
||||
if path not in _times:
|
||||
_times[path] = mtime
|
||||
|
||||
# Force restart when modification time has changed, even
|
||||
# if time now older, as that could indicate older file
|
||||
# has been restored.
|
||||
# Force restart when modification time has changed, even
|
||||
# if time now older, as that could indicate older file
|
||||
# has been restored.
|
||||
|
||||
if mtime != _times[path]:
|
||||
return True
|
||||
except:
|
||||
# If any exception occured, likely that file has been
|
||||
# been removed just before stat(), so force a restart.
|
||||
if mtime != _times[path]:
|
||||
return True
|
||||
except:
|
||||
# If any exception occured, likely that file has been
|
||||
# been removed just before stat(), so force a restart.
|
||||
|
||||
return True
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
return False
|
||||
|
||||
def _monitor():
|
||||
while 1:
|
||||
# Check modification times on all files in sys.modules.
|
||||
while 1:
|
||||
# Check modification times on all files in sys.modules.
|
||||
|
||||
for module in sys.modules.values():
|
||||
if not hasattr(module, '__file__'):
|
||||
continue
|
||||
path = getattr(module, '__file__')
|
||||
if not path:
|
||||
continue
|
||||
if os.path.splitext(path)[1] in ['.pyc', '.pyo', '.pyd']:
|
||||
path = path[:-1]
|
||||
if _modified(path):
|
||||
return _restart(path)
|
||||
for module in sys.modules.values():
|
||||
if not hasattr(module, '__file__'):
|
||||
continue
|
||||
path = getattr(module, '__file__')
|
||||
if not path:
|
||||
continue
|
||||
if os.path.splitext(path)[1] in ['.pyc', '.pyo', '.pyd']:
|
||||
path = path[:-1]
|
||||
if _modified(path):
|
||||
return _restart(path)
|
||||
|
||||
# Check modification times on files which have
|
||||
# specifically been registered for monitoring.
|
||||
# Check modification times on files which have
|
||||
# specifically been registered for monitoring.
|
||||
|
||||
for path in _files:
|
||||
if _modified(path):
|
||||
return _restart(path)
|
||||
for path in _files:
|
||||
if _modified(path):
|
||||
return _restart(path)
|
||||
|
||||
# Go to sleep for specified interval.
|
||||
# Go to sleep for specified interval.
|
||||
|
||||
try:
|
||||
return _queue.get(timeout=_interval)
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
return _queue.get(timeout=_interval)
|
||||
except:
|
||||
pass
|
||||
|
||||
_thread = threading.Thread(target=_monitor)
|
||||
_thread.setDaemon(True)
|
||||
|
||||
|
||||
def _exiting():
|
||||
try:
|
||||
_queue.put(True)
|
||||
except:
|
||||
pass
|
||||
_thread.join()
|
||||
try:
|
||||
_queue.put(True)
|
||||
except:
|
||||
pass
|
||||
_thread.join()
|
||||
|
||||
atexit.register(_exiting)
|
||||
|
||||
|
||||
def track(path):
|
||||
if not path in _files:
|
||||
_files.append(path)
|
||||
if not path in _files:
|
||||
_files.append(path)
|
||||
|
||||
|
||||
def start(interval=1.0):
|
||||
global _interval
|
||||
if interval < _interval:
|
||||
_interval = interval
|
||||
|
||||
global _running
|
||||
_lock.acquire()
|
||||
if not _running:
|
||||
prefix = 'monitor (pid=%d):' % os.getpid()
|
||||
print >> sys.stderr, '%s Starting change monitor.' % prefix
|
||||
_running = True
|
||||
_thread.start()
|
||||
_lock.release()\
|
||||
global _interval
|
||||
if interval < _interval:
|
||||
_interval = interval
|
||||
|
||||
global _running
|
||||
_lock.acquire()
|
||||
if not _running:
|
||||
prefix = 'monitor (pid=%d):' % os.getpid()
|
||||
print >> sys.stderr, '%s Starting change monitor.' % prefix
|
||||
_running = True
|
||||
_thread.start()
|
||||
_lock.release()
|
||||
|
@ -3,30 +3,29 @@ import urllib
|
||||
import httplib
|
||||
from urlparse import urlparse
|
||||
|
||||
|
||||
def query_api(url, method='GET', params={}):
|
||||
if method not in ('GET', 'POST', 'PUT', 'DELETE'):
|
||||
raise ValueError("Invalid method %s" % method)
|
||||
|
||||
|
||||
parsed_url = urlparse(url)
|
||||
|
||||
|
||||
body = None
|
||||
path = parsed_url.path
|
||||
if method in ('POST', 'PUT'):
|
||||
body = urllib.urlencode(params)
|
||||
elif params:
|
||||
path = "%s?%s" % (path, urllib.urlencode(params))
|
||||
|
||||
|
||||
conn = httplib.HTTPConnection(parsed_url.netloc)
|
||||
conn.request(method, path, body)
|
||||
response = conn.getresponse()
|
||||
raw_data = response.read()
|
||||
|
||||
|
||||
data = None
|
||||
try:
|
||||
data = json.loads(raw_data)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
|
||||
return (response.status, data)
|
||||
|
||||
|
@ -3,19 +3,23 @@ from django import forms
|
||||
from django.forms.fields import Field, CharField, ChoiceField
|
||||
from nailgun.models import Environment, Node, Role
|
||||
|
||||
|
||||
class EnvironmentForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Environment
|
||||
|
||||
|
||||
def validate_node_metadata(value):
|
||||
if value is not None:
|
||||
if isinstance(value, dict):
|
||||
for field in ('block_device', 'interfaces', 'cpu', 'memory'):
|
||||
if not field in value:
|
||||
raise ValidationError('Node metadata \'%s\' field is required' % field)
|
||||
raise ValidationError("Node metadata '%s' \
|
||||
field is required" % field)
|
||||
else:
|
||||
raise ValidationError('Node metadata must be a dictionary')
|
||||
|
||||
|
||||
class NodeForm(forms.Form):
|
||||
metadata = Field(required=False, validators=[validate_node_metadata])
|
||||
status = ChoiceField(required=False, choices=Node.NODE_STATUSES)
|
||||
|
@ -12,11 +12,11 @@ from forms import EnvironmentForm, NodeForm
|
||||
|
||||
|
||||
class EnvironmentHandler(BaseHandler):
|
||||
|
||||
|
||||
allowed_methods = ('GET', 'POST', 'PUT')
|
||||
model = Environment
|
||||
fields = ('id', 'name', ('nodes', ()))
|
||||
|
||||
|
||||
def read(self, request, environment_id=None):
|
||||
if environment_id:
|
||||
try:
|
||||
@ -25,7 +25,7 @@ class EnvironmentHandler(BaseHandler):
|
||||
return rc.NOT_FOUND
|
||||
else:
|
||||
return Environment.objects.all()
|
||||
|
||||
|
||||
@validate_json(EnvironmentForm)
|
||||
def create(self, request):
|
||||
environment = Environment()
|
||||
@ -38,7 +38,7 @@ class ConfigHandler(BaseHandler):
|
||||
|
||||
allowed_methods = ('POST',)
|
||||
|
||||
""" Creates JSON files for chef-solo. This should be moved to the queue. """
|
||||
""" Creates JSON files for chef-solo. This should be moved to the queue """
|
||||
def create(self, request, environment_id):
|
||||
env_id = environment_id
|
||||
nodes = Node.objects.filter(environment__id=env_id)
|
||||
@ -63,33 +63,37 @@ class ConfigHandler(BaseHandler):
|
||||
["role[" + x.name + "]" for x in n.roles.all()]
|
||||
solo_json['all_roles'] = nodes_per_role
|
||||
|
||||
filepath = os.path.join(settings.CHEF_CONF_FOLDER, n.name + '.json')
|
||||
filepath = os.path.join(settings.CHEF_CONF_FOLDER,
|
||||
n.name + '.json')
|
||||
f = open(filepath, 'w')
|
||||
f.write(json.dumps(solo_json))
|
||||
f.close()
|
||||
|
||||
|
||||
class NodeHandler(BaseHandler):
|
||||
|
||||
|
||||
allowed_methods = ('GET', 'PUT')
|
||||
model = Node
|
||||
fields = ('name', 'metadata', 'status', ('roles', ()))
|
||||
|
||||
|
||||
def read(self, request, environment_id, node_name=None):
|
||||
try:
|
||||
if node_name:
|
||||
return Node.objects.get(name=node_name, environment__id=environment_id)
|
||||
return Node.objects.get(name=node_name,
|
||||
environment__id=environment_id)
|
||||
else:
|
||||
return Node.objects.filter(environment__id=environment_id)
|
||||
except ObjectDoesNotExist:
|
||||
return rc.NOT_FOUND
|
||||
|
||||
|
||||
@validate_json(NodeForm)
|
||||
def update(self, request, environment_id, node_name):
|
||||
try:
|
||||
node = Node.objects.get(name=node_name, environment__id=environment_id)
|
||||
node = Node.objects.get(name=node_name,
|
||||
environment__id=environment_id)
|
||||
for key, value in request.form.cleaned_data.items():
|
||||
if key in request.form.data: # check if parameter is really passed by client
|
||||
# check if parameter is really passed by client
|
||||
if key in request.form.data:
|
||||
setattr(node, key, value)
|
||||
node.save()
|
||||
return node
|
||||
@ -106,29 +110,34 @@ class RoleHandler(BaseHandler):
|
||||
def read(self, request, environment_id, node_name, role_name=None):
|
||||
try:
|
||||
if role_name:
|
||||
return Role.objects.get(nodes__environment__id=environment_id, nodes__name=node_name, name=role_name)
|
||||
return Role.objects.get(nodes__environment__id=environment_id,
|
||||
nodes__name=node_name, name=role_name)
|
||||
else:
|
||||
return Role.objects.filter(nodes__environment__id=environment_id, nodes__name=node_name)
|
||||
return Role.objects.filter(
|
||||
nodes__environment__id=environment_id,
|
||||
nodes__name=node_name)
|
||||
except ObjectDoesNotExist:
|
||||
return rc.NOT_FOUND
|
||||
|
||||
def create(self, request, environment_id, node_name, role_name):
|
||||
try:
|
||||
print environment_id, node_name, role_name
|
||||
node = Node.objects.get(environment__id=environment_id, name=node_name)
|
||||
node = Node.objects.get(environment__id=environment_id,
|
||||
name=node_name)
|
||||
role = Role.objects.get(name=role_name)
|
||||
|
||||
|
||||
if role in node.roles.all():
|
||||
return rc.DUPLICATE_ENTRY
|
||||
|
||||
|
||||
node.roles.add(role)
|
||||
return role
|
||||
except ObjectDoesNotExist:
|
||||
return rc.NOT_FOUND
|
||||
|
||||
|
||||
def delete(self, request, environment_id, node_name, role_name):
|
||||
try:
|
||||
node = Node.objects.get(environment__id=environment_id, name=node_name)
|
||||
node = Node.objects.get(environment__id=environment_id,
|
||||
name=node_name)
|
||||
role = Role.objects.get(name=role_name)
|
||||
node.roles.remove(role)
|
||||
return rc.DELETED
|
||||
|
@ -1,11 +1,15 @@
|
||||
from django.conf.urls import patterns, include, url
|
||||
from piston.resource import Resource
|
||||
from handlers import EnvironmentHandler, NodeHandler, RoleHandler, ConfigHandler
|
||||
|
||||
from handlers import EnvironmentHandler, NodeHandler
|
||||
from handlers import RoleHandler, ConfigHandler
|
||||
|
||||
|
||||
class JsonResource(Resource):
|
||||
def determine_emitter(self, request, *args, **kwargs):
|
||||
return 'json'
|
||||
|
||||
|
||||
environment_handler = JsonResource(EnvironmentHandler)
|
||||
node_handler = JsonResource(NodeHandler)
|
||||
role_handler = JsonResource(RoleHandler)
|
||||
@ -14,9 +18,13 @@ config_handler = JsonResource(ConfigHandler)
|
||||
urlpatterns = patterns('',
|
||||
url(r'^environments/?$', environment_handler),
|
||||
url(r'^environments/(?P<environment_id>\d+)/?$', environment_handler),
|
||||
url(r'^environments/(?P<environment_id>\d+)/chef-config/?$', config_handler),
|
||||
url(r'^environments/(?P<environment_id>\d+)/chef-config/?$',
|
||||
config_handler),
|
||||
url(r'^environments/(?P<environment_id>\d+)/nodes/?$', node_handler),
|
||||
url(r'^environments/(?P<environment_id>\d+)/nodes/(?P<node_name>[\w\.\-]+)/?$', node_handler),
|
||||
url(r'^environments/(?P<environment_id>\d+)/nodes/(?P<node_name>[\w\.\-]+)/roles/?$', role_handler),
|
||||
url(r'^environments/(?P<environment_id>\d+)/nodes/(?P<node_name>[\w\.\-]+)/roles/(?P<role_name>\w+)/?$', role_handler),
|
||||
url(r'^environments/(?P<environment_id>\d+)/nodes/'
|
||||
r'(?P<node_name>[\w\.\-]+)/?$', node_handler),
|
||||
url(r'^environments/(?P<environment_id>\d+)/nodes/'
|
||||
r'(?P<node_name>[\w\.\-]+)/roles/?$', role_handler),
|
||||
url(r'^environments/(?P<environment_id>\d+)/nodes/'
|
||||
r'(?P<node_name>[\w\.\-]+)/roles/(?P<role_name>\w+)/?$', role_handler),
|
||||
)
|
||||
|
@ -2,6 +2,7 @@ import json
|
||||
from piston.utils import FormValidationError, HttpStatusCode, rc
|
||||
from piston.decorator import decorator
|
||||
|
||||
|
||||
def validate_json(v_form):
|
||||
@decorator
|
||||
def wrap(f, self, request, *a, **kwa):
|
||||
@ -10,9 +11,9 @@ def validate_json(v_form):
|
||||
response = rc.BAD_REQUEST
|
||||
response.content = "Invalid content type, must be application/json"
|
||||
raise HttpStatusCode(response)
|
||||
|
||||
|
||||
form = v_form(json.loads(request.body), request.FILES)
|
||||
|
||||
|
||||
if form.is_valid():
|
||||
setattr(request, 'form', form)
|
||||
return f(self, request, *a, **kwa)
|
||||
|
@ -1,5 +1,6 @@
|
||||
import traceback
|
||||
|
||||
|
||||
class ExceptionLoggingMiddleware(object):
|
||||
def process_exception(self, request, exception):
|
||||
print traceback.format_exc()
|
||||
|
@ -20,7 +20,7 @@ class Node(models.Model):
|
||||
)
|
||||
environment = models.ForeignKey(Environment, related_name='nodes')
|
||||
name = models.CharField(max_length=100, primary_key=True)
|
||||
status = models.CharField(max_length=30, choices=NODE_STATUSES, default='online')
|
||||
status = models.CharField(max_length=30, choices=NODE_STATUSES,
|
||||
default='online')
|
||||
metadata = JSONField()
|
||||
roles = models.ManyToManyField(Role, related_name='nodes')
|
||||
|
||||
|
@ -15,12 +15,12 @@ MANAGERS = ADMINS
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
|
||||
'NAME': os.path.join(PROJECT_ROOT, 'nailgun.sqlite'), # Or path to database file if using sqlite3.
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': os.path.join(PROJECT_ROOT, 'nailgun.sqlite'),
|
||||
'USER': '', # Not used with sqlite3.
|
||||
'PASSWORD': '', # Not used with sqlite3.
|
||||
'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
|
||||
'PORT': '', # Set to empty string for default. Not used with sqlite3.
|
||||
'HOST': '',
|
||||
'PORT': '',
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,7 +98,8 @@ MIDDLEWARE_CLASSES = (
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
)
|
||||
|
||||
if DEBUG: MIDDLEWARE_CLASSES += ('nailgun.middleware.ExceptionLoggingMiddleware',)
|
||||
if DEBUG:
|
||||
MIDDLEWARE_CLASSES += ('nailgun.middleware.ExceptionLoggingMiddleware',)
|
||||
|
||||
ROOT_URLCONF = 'nailgun.urls'
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
from celery.task import task
|
||||
|
||||
|
||||
@task
|
||||
def add(x, y):
|
||||
for i in xrange(1, 10):
|
||||
time.sleep(1)
|
||||
add.update_state(state="PROGRESS", meta={"current": i, "total": 10})
|
||||
return x + y
|
||||
|
||||
for i in xrange(1, 10):
|
||||
time.sleep(1)
|
||||
add.update_state(state="PROGRESS", meta={"current": i, "total": 10})
|
||||
return x + y
|
||||
|
@ -1,23 +1,26 @@
|
||||
import os
|
||||
|
||||
from django import template
|
||||
from django.contrib.staticfiles.finders import FileSystemFinder
|
||||
|
||||
|
||||
TEMPLATE_EXTENSION = '.html'
|
||||
|
||||
register = template.Library()
|
||||
finder = FileSystemFinder()
|
||||
|
||||
|
||||
@register.simple_tag
|
||||
def jst(template_name):
|
||||
template_filename = os.path.join('jst', template_name + TEMPLATE_EXTENSION)
|
||||
|
||||
|
||||
match = finder.find(template_filename)
|
||||
if not match:
|
||||
raise Exception("JS template '%s' not found" % template_filename)
|
||||
|
||||
|
||||
f = open(match, 'r')
|
||||
|
||||
|
||||
template_content = f.read()
|
||||
|
||||
|
||||
return "<script type=\"text/template\" id=\"tpl_%s\">\n%s\n</script>" % \
|
||||
(template_name, template_content)
|
||||
|
@ -20,15 +20,15 @@ class TestHandlers(TestCase):
|
||||
name=self.node_name,
|
||||
metadata=self.old_meta)
|
||||
self.node.save()
|
||||
|
||||
|
||||
self.role = Role()
|
||||
self.role.name = "myrole"
|
||||
self.role.save()
|
||||
|
||||
|
||||
self.another_role = Role()
|
||||
self.another_role.name = "myrole2"
|
||||
self.another_role.save()
|
||||
|
||||
|
||||
self.node.roles = [self.role]
|
||||
self.node.save()
|
||||
self.node_url = '/api/environments/1/nodes/' + self.node_name
|
||||
@ -134,7 +134,6 @@ class TestHandlers(TestCase):
|
||||
name=self.node_name)
|
||||
self.assertEquals(nodes_from_db[0].roles.all()[0].name, "myrole")
|
||||
|
||||
|
||||
# Tests for RoleHandler
|
||||
def test_can_get_list_of_roles_for_node(self):
|
||||
resp = self.client.get(self.node_url + '/roles')
|
||||
@ -147,12 +146,14 @@ class TestHandlers(TestCase):
|
||||
|
||||
resp = self.client.post(url, '', "plain/text")
|
||||
self.assertEquals(resp.status_code, 409)
|
||||
|
||||
|
||||
roles_from_db = Role.objects.all()
|
||||
nodes_from_db = Node.objects.filter(environment_id=1,
|
||||
name=self.node_name)
|
||||
self.assertEquals(nodes_from_db[0].roles.all()[0].name, self.role.name)
|
||||
self.assertEquals(nodes_from_db[0].roles.all()[1].name, self.another_role.name)
|
||||
self.assertEquals(nodes_from_db[0].roles.all()[0].name,
|
||||
self.role.name)
|
||||
self.assertEquals(nodes_from_db[0].roles.all()[1].name,
|
||||
self.another_role.name)
|
||||
|
||||
#def test_jsons_created_for_chef_solo(self):
|
||||
#resp = self.client.post('/api/environments/1/chef-config/')
|
||||
|
@ -45,6 +45,6 @@ class TestRolesNodesAssociation(TestCase):
|
||||
node1.roles.add(role2)
|
||||
self.assertEquals(len(node1.roles.all()), 2)
|
||||
|
||||
self.assertEquals(Node.objects.filter(roles__name__startswith="myr")[0].name,
|
||||
self.assertEquals(Node.objects.filter(
|
||||
roles__name__startswith="myr")[0].name,
|
||||
"test.example.com")
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
from django.http import HttpResponse
|
||||
from django.shortcuts import render
|
||||
|
||||
|
||||
def index(request):
|
||||
return render(request, 'index.html', {})
|
||||
|
Loading…
Reference in New Issue
Block a user