Refactored 'accounts' to be more general with 'destinations'

This commit is contained in:
kevgliss
2015-07-10 17:06:57 -07:00
parent b26de2b000
commit 0c7204cdb9
29 changed files with 421 additions and 708 deletions

View File

View File

@ -0,0 +1,28 @@
"""
.. module: lemur.destinations.models
:platform: unix
:copyright: (c) 2015 by Netflix Inc., see AUTHORS for more
:license: Apache, see LICENSE for more details.
.. moduleauthor:: Kevin Glisson <kglisson@netflix.com>
"""
import copy
from sqlalchemy import Column, Integer, String, Text
from sqlalchemy_utils import JSONType
from lemur.database import db
from lemur.plugins.base import plugins
class Destination(db.Model):
__tablename__ = 'destinations'
id = Column(Integer, primary_key=True)
label = Column(String(32))
options = Column(JSONType)
description = Column(Text())
plugin_name = Column(String(32))
@property
def plugin(self):
p = plugins.get(self.plugin_name)
c = copy.deepcopy(p)
c.options = self.options
return c

View File

@ -0,0 +1,110 @@
"""
.. module: lemur.destinations.service
:platform: Unix
:copyright: (c) 2015 by Netflix Inc., see AUTHORS for more
:license: Apache, see LICENSE for more details.
.. moduleauthor:: Kevin Glisson <kglisson@netflix.com>
"""
from lemur import database
from lemur.destinations.models import Destination
from lemur.certificates.models import Certificate
def create(label, plugin_name, options, description=None):
"""
Creates a new destination, that can then be used as a destination for certificates.
:param label: Destination common name
:param description:
:rtype : Destination
:return: New destination
"""
destination = Destination(label=label, options=options, plugin_name=plugin_name, description=description)
return database.create(destination)
def update(destination_id, label, options, description):
"""
Updates an existing destination.
:param destination_id: Lemur assigned ID
:param destination_number: AWS assigned ID
:param label: Destination common name
:param comments:
:rtype : Destination
:return:
"""
destination = get(destination_id)
destination.label = label
description.options = options
destination.description = description
return database.update(destination)
def delete(destination_id):
"""
Deletes an destination.
:param destination_id: Lemur assigned ID
"""
database.delete(get(destination_id))
def get(destination_id):
"""
Retrieves an destination by it's lemur assigned ID.
:param destination_id: Lemur assigned ID
:rtype : Destination
:return:
"""
return database.get(Destination, destination_id)
def get_by_label(label):
"""
Retrieves a destination by it's label
:param label:
:return:
"""
return database.get(Destination, label, field='label')
def get_all():
"""
Retrieves all destination currently known by Lemur.
:return:
"""
query = database.session_query(Destination)
return database.find_all(query, Destination, {}).all()
def render(args):
sort_by = args.pop('sort_by')
sort_dir = args.pop('sort_dir')
page = args.pop('page')
count = args.pop('count')
filt = args.pop('filter')
certificate_id = args.pop('certificate_id', None)
if certificate_id:
query = database.session_query(Destination).join(Certificate, Destination.certificate)
query = query.filter(Certificate.id == certificate_id)
else:
query = database.session_query(Destination)
if filt:
terms = filt.split(';')
query = database.filter(query, Destination, terms)
query = database.find_all(query, Destination, args)
if sort_by and sort_dir:
query = database.sort(query, Destination, sort_by, sort_dir)
return database.paginate(query, page, count)

278
lemur/destinations/views.py Normal file
View File

@ -0,0 +1,278 @@
"""
.. module: lemur.destinations.views
:platform: Unix
:synopsis: This module contains all of the accounts view code.
:copyright: (c) 2015 by Netflix Inc., see AUTHORS for more
:license: Apache, see LICENSE for more details.
.. moduleauthor:: Kevin Glisson <kglisson@netflix.com>
"""
from flask import Blueprint
from flask.ext.restful import Api, reqparse, fields
from lemur.destinations import service
from lemur.auth.service import AuthenticatedResource
from lemur.auth.permissions import admin_permission
from lemur.common.utils import paginated_parser, marshal_items
from lemur.plugins.views import FIELDS as PLUGIN_FIELDS
mod = Blueprint('destinations', __name__)
api = Api(mod)
FIELDS = {
'description': fields.String,
'plugin': fields.Nested(PLUGIN_FIELDS, attribute='plugin'),
'label': fields.String,
'id': fields.Integer,
}
class DestinationsList(AuthenticatedResource):
""" Defines the 'destinations' endpoint """
def __init__(self):
self.reqparse = reqparse.RequestParser()
super(DestinationsList, self).__init__()
@marshal_items(FIELDS)
def get(self):
"""
.. http:get:: /destinations
The current account list
**Example request**:
.. sourcecode:: http
GET /destinations HTTP/1.1
Host: example.com
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: text/javascript
{
"items": [
{
"id": 2,
"accountNumber": 222222222,
"label": "account2",
"comments": "this is a thing"
},
{
"id": 1,
"accountNumber": 11111111111,
"label": "account1",
"comments": "this is a thing"
},
]
"total": 2
}
:query sortBy: field to sort on
:query sortDir: acs or desc
:query page: int. default is 1
:query filter: key value pair. format is k=v;
:query limit: limit number. default is 10
:reqheader Authorization: OAuth token to authenticate
:statuscode 200: no error
"""
parser = paginated_parser.copy()
args = parser.parse_args()
return service.render(args)
@admin_permission.require(http_exception=403)
@marshal_items(FIELDS)
def post(self):
"""
.. http:post:: /destinations
Creates a new account
**Example request**:
.. sourcecode:: http
POST /destinations HTTP/1.1
Host: example.com
Accept: application/json, text/javascript
{
"accountNumber": 11111111111,
"label": "account1,
"comments": "this is a thing"
}
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: text/javascript
{
"id": 1,
"accountNumber": 11111111111,
"label": "account1",
"comments": "this is a thing"
}
:arg accountNumber: aws account number
:arg label: human readable account label
:arg comments: some description about the account
:reqheader Authorization: OAuth token to authenticate
:statuscode 200: no error
"""
self.reqparse.add_argument('label', type=str, location='json', required=True)
self.reqparse.add_argument('plugin', type=dict, location='json', required=True)
self.reqparse.add_argument('description', type=str, location='json')
args = self.reqparse.parse_args()
return service.create(args['label'], args['plugin']['slug'], args['plugin']['pluginOptions'], args['description'])
class Destinations(AuthenticatedResource):
def __init__(self):
self.reqparse = reqparse.RequestParser()
super(Destinations, self).__init__()
@marshal_items(FIELDS)
def get(self, destination_id):
"""
.. http:get:: /destinations/1
Get a specific account
**Example request**:
.. sourcecode:: http
GET /destinations/1 HTTP/1.1
Host: example.com
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: text/javascript
{
"id": 1,
"accountNumber": 11111111111,
"label": "account1",
"comments": "this is a thing"
}
:reqheader Authorization: OAuth token to authenticate
:statuscode 200: no error
"""
return service.get(destination_id)
@admin_permission.require(http_exception=403)
@marshal_items(FIELDS)
def put(self, destination_id):
"""
.. http:put:: /destinations/1
Updates an account
**Example request**:
.. sourcecode:: http
POST /destinations/1 HTTP/1.1
Host: example.com
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: text/javascript
{
"id": 1,
"accountNumber": 11111111111,
"label": "labelChanged",
"comments": "this is a thing"
}
:arg accountNumber: aws account number
:arg label: human readable account label
:arg comments: some description about the account
:reqheader Authorization: OAuth token to authenticate
:statuscode 200: no error
"""
self.reqparse.add_argument('label', type=str, location='json', required=True)
self.reqparse.add_argument('pluginOptions', type=dict, location='json', required=True)
self.reqparse.add_argument('description', type=str, location='json')
args = self.reqparse.parse_args()
return service.update(destination_id, args['label'], args['options'], args['description'])
@admin_permission.require(http_exception=403)
def delete(self, destination_id):
service.delete(destination_id)
return {'result': True}
class CertificateDestinations(AuthenticatedResource):
""" Defines the 'certificate/<int:certificate_id/destinations'' endpoint """
def __init__(self):
super(CertificateDestinations, self).__init__()
@marshal_items(FIELDS)
def get(self, certificate_id):
"""
.. http:get:: /certificates/1/destinations
The current account list for a given certificates
**Example request**:
.. sourcecode:: http
GET /certificates/1/destinations HTTP/1.1
Host: example.com
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: text/javascript
:query sortBy: field to sort on
:query sortDir: acs or desc
:query page: int. default is 1
:query filter: key value pair. format is k=v;
:query limit: limit number. default is 10
:reqheader Authorization: OAuth token to authenticate
:statuscode 200: no error
"""
parser = paginated_parser.copy()
args = parser.parse_args()
args['certificate_id'] = certificate_id
return service.render(args)
api.add_resource(DestinationsList, '/destinations', endpoint='destinations')
api.add_resource(Destinations, '/destinations/<int:destination_id>', endpoint='account')
api.add_resource(CertificateDestinations, '/certificates/<int:certificate_id>/destinations', endpoint='certificateDestinations')