Skip to content

Commit

Permalink
Merge pull request #115 from Mirantis/namespaces
Browse files Browse the repository at this point in the history
Add namespaces for database objects
  • Loading branch information
tomkukral authored Nov 13, 2017
2 parents fcf351a + d5c81ef commit 1477b60
Show file tree
Hide file tree
Showing 25 changed files with 432 additions and 117 deletions.
16 changes: 8 additions & 8 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,18 @@ python:
- '3.6'
service:
- docker


notifications:
slack:
secure: imXU/zt9IjKk5OvjZkTICTmxOTKGaZIej2kf7m5iSAKrdM7Lsjhj1m464qOViH3AMjMMZeprC1SL/jFF5azu2DNkQe5j1UlUu1ZxQpwnpmXJaLyTznDZSa76LPoY/R4sqJYozZLzfMQivnIUe6NGTP5vDX8CXpndaOgfAulDzks6xXDTw8q1dyKTtqFx8aPbAFAYRPagaNpy62j09aeNXDY8OVUSJsx8xylRmbHY+t1AH5AMkDPY5AeI0D/CJH1Hnbq88MmvdgUn8OqjvWMgiXsrDFAPZ4WdZCgJZuP2D4jrDuAsnchrOrVi6wKJWA9rNqJD8TqqF8Q8JhdeVAJ098GXAyhkJlDtfeEbh8TYIkLNgpW7e/auh5rzHk5MvH7kTVzyZjGMb7Vo+7c7nypFoWeom1m8Pg5rCT7vx7+0NhQjg1moMQ2kPWzaZkITDdblxuf6rpraEx2ydqPh6pAAto+VWXRrdbJJTGSTVIfPFDHYeqkCq+QVGfdCi2BucnnQVZJLUqEdGxnn86ICwhjJ5uC4Ah7Czd/pZOrdgFMWTT6DS9fjRiIHOnAAp1wKYzAoRBKQkhltDFMrayDxN5dp+IXDnnlQWPm14mwAyNd/zt8pWCue5hT2oK7oeuQsNfSemSPg92DCZRZNZ684UbJGKn0RJlSpXLyQRjja0IjA+Kk=
on_success: change
on_failure: change
on_pull_requests: false
stages:
- name: test
- name: publish
if: tag =~ ^v.*
- name: verify
if: branch = master AND type = push

jobs:
include:
- stage: test
Expand All @@ -25,15 +28,13 @@ jobs:
- python3 -m flake8
- python3 -m pytest --cov=. --cov-report=term-missing:skip-covered
- coveralls

- pip3 install --editable .
- python3 -m kqueen &
- sleep 2
- wget -O - http://localhost:5000/api/v1/health

- stage: publish
script:
- /bin/true
- "/bin/true"
deploy:
provider: pypi
user: tomkukral
Expand All @@ -42,13 +43,12 @@ jobs:
on:
tags: true
repo: Mirantis/kqueen

- stage: verify
before_install:
- docker-compose -f docker-compose.yml -f docker-compose.kubernetes.yml up -d
install:
- pip3 install --upgrade kqueen
script:
- ./entrypoint.sh &
- "./entrypoint.sh &"
- sleep 2
- wget -O - http://localhost:5000/api/v1/health
6 changes: 6 additions & 0 deletions devenv.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

try:
user = User(
None,
username='admin',
password='default',
organization=organization,
Expand All @@ -46,6 +47,7 @@
# AWS + Jenkins
try:
provisioner = Provisioner(
user.namespace,
id=uuid_provisioner_jenkins,
name='Jenkins provisioner to AWS',
state='OK',
Expand All @@ -62,6 +64,7 @@

try:
cluster = Cluster(
user.namespace,
id=uuid_jenkins,
name='AWS Calico SM 33',
state='OK',
Expand All @@ -76,6 +79,7 @@
# Local cluster
try:
provisioner = Provisioner(
user.namespace,
id=uuid_provisioner_local,
name='Manual provisioner',
state='OK',
Expand All @@ -89,6 +93,7 @@

try:
cluster = Cluster(
user.namespace,
id=uuid_local,
name='local_cluster',
state='OK',
Expand All @@ -102,6 +107,7 @@
# Dummy Kubespray provisioner
try:
provisioner = Provisioner(
user.namespace,
id=uuid_provisioner_kubespray,
name='Kubespray',
state='OK',
Expand Down
4 changes: 4 additions & 0 deletions docs/kqueen.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ Example configuration files are located in `config/` directory. Default configur
* - ETCD_PORT
- 4001
- Port for etcd server
* - ETCD_PREFIX
- /kqueen
- Prefix URL for objects in etcd


* - JWT_DEFAULT_REALM
- Login Required
Expand Down
6 changes: 3 additions & 3 deletions kqueen/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ def authenticate(username, password):
user: authenticated user
"""
users = list(User.list(return_objects=True).values())
users = list(User.list(None, return_objects=True).values())
username_table = {u.username: u for u in users}
user = username_table.get(username, None)
user = username_table.get(username)
if user and safe_str_cmp(user.password.encode('utf-8'), password.encode('utf-8')):
return user

Expand All @@ -36,7 +36,7 @@ def identity(payload):
"""
user_id = payload['identity']
try:
user = User.load(user_id)
user = User.load(None, user_id)
except:
user = None
return user
29 changes: 21 additions & 8 deletions kqueen/blueprints/api/generic_views.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from flask import jsonify
from flask.views import View
from flask import abort
from flask_jwt import _jwt_required
from flask_jwt import _jwt_required, current_identity
from flask import current_app
from flask import request
from .helpers import get_object
Expand All @@ -22,7 +22,6 @@ def check_access(self):

def dispatch_request(self, *args, **kwargs):
self.check_access()

output = self.get_content(*args, **kwargs)

return jsonify(output)
Expand All @@ -32,7 +31,7 @@ class GetView(GenericView):
methods = ['GET']

def get_content(self, *args, **kwargs):
return get_object(self.get_class(), kwargs['pk'])
return get_object(self.get_class(), kwargs['pk'], current_identity)


class DeleteView(GenericView):
Expand All @@ -41,7 +40,7 @@ class DeleteView(GenericView):
def dispatch_request(self, *args, **kwargs):
self.check_access()

obj = get_object(self.get_class(), kwargs['pk'])
obj = get_object(self.get_class(), kwargs['pk'], current_identity)

try:
obj.delete()
Expand All @@ -55,17 +54,19 @@ class UpdateView(GenericView):
methods = ['PATCH']

def get_content(self, *args, **kwargs):
return get_object(self.get_class(), kwargs['pk'])
return get_object(self.get_class(), kwargs['pk'], current_identity)

def dispatch_request(self, *args, **kwargs):
self.check_access()

if not request.json:
abort(400)

data = request.json
if not isinstance(data, dict):
abort(400)

obj = get_object(self.get_class(), kwargs['pk'])
obj = get_object(self.get_class(), kwargs['pk'], current_identity)
for key, value in data.items():
setattr(obj, key, value)

Expand All @@ -81,7 +82,12 @@ class ListView(GenericView):
methods = ['GET']

def get_content(self, *args, **kwargs):
return list(self.get_class().list(return_objects=True).values())
try:
namespace = current_identity.namespace
except AttributeError:
namespace = None

return list(self.get_class().list(namespace, return_objects=True).values())


class CreateView(GenericView):
Expand All @@ -97,12 +103,19 @@ def get_content(self, *args, **kwargs):
return self.obj.get_dict(expand=True)

def dispatch_request(self, *args, **kwargs):
self.check_access()

if not request.json:
abort(400)
else:
cls = self.get_class()
self.obj = cls(**request.json)

try:
namespace = current_identity.namespace
except AttributeError:
namespace = None

self.obj = cls(namespace, **request.json)
try:
self.save_object()
self.after_save()
Expand Down
11 changes: 8 additions & 3 deletions kqueen/blueprints/api/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
from uuid import UUID


def get_object(object_class, pk):

def get_object(object_class, pk, user=None):
# read uuid
if isinstance(pk, UUID):
object_id = pk
Expand All @@ -13,9 +12,15 @@ def get_object(object_class, pk):
except ValueError:
abort(400)

# read namespace for user
try:
namespace = user.namespace
except AttributeError:
namespace = None

# load object
try:
obj = object_class.load(object_id)
obj = object_class.load(namespace, object_id)
except NameError:
abort(404)

Expand Down
12 changes: 4 additions & 8 deletions kqueen/blueprints/api/test_cluster.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from flask import url_for
from uuid import uuid4
from kqueen.conftest import cluster
from kqueen.conftest import provisioner
from .test_crud import BaseTestCRUD

import pytest
Expand All @@ -10,13 +9,9 @@

class TestClusterCRUD(BaseTestCRUD):
def get_object(self):
clu = cluster()
prov = provisioner()
prov.save()
obj = cluster()

clu.provisioner = prov

return clu
return obj

def get_edit_data(self):
return {'name': 'patched cluster'}
Expand All @@ -34,6 +29,7 @@ def test_get_dict_expanded(self):
assert dicted['provisioner']['id'] == self.obj.provisioner.id

def test_cluster_get(self):

cluster_id = self.obj.id

response = self.client.get(
Expand Down Expand Up @@ -150,7 +146,7 @@ def fake_provision(self, *args, **kwargs):
)

object_id = response.json['id']
obj = self.obj.__class__.load(object_id)
obj = self.obj.__class__.load(self.namespace, object_id)

assert response.status_code == 200
assert obj.name == 'Provisioned'
Expand Down
Loading

0 comments on commit 1477b60

Please sign in to comment.