initial commit

This commit is contained in:
Kevin Glisson
2015-06-22 13:47:27 -07:00
commit 4330ac9c05
228 changed files with 16656 additions and 0 deletions

View File

43
lemur/listeners/models.py Normal file
View File

@ -0,0 +1,43 @@
"""
.. module: lemur.elbs.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>
"""
from sqlalchemy import Column, Integer, BigInteger, String, ForeignKey, DateTime, PassiveDefault, func
from lemur.database import db
from lemur.certificates import service as cert_service
from lemur.certificates.models import Certificate, get_name_from_arn
class Listener(db.Model):
__tablename__ = 'listeners'
id = Column(BigInteger, primary_key=True)
certificate_id = Column(Integer, ForeignKey(Certificate.id), index=True)
elb_id = Column(BigInteger, ForeignKey("elbs.id"), index=True)
instance_port = Column(Integer)
instance_protocol = Column(String(16))
load_balancer_port = Column(Integer)
load_balancer_protocol = Column(String(16))
date_created = Column(DateTime, PassiveDefault(func.now()), nullable=False)
def __init__(self, listener):
self.load_balancer_port = listener.load_balancer_port
self.load_balancer_protocol = listener.protocol
self.instance_port = listener.instance_port
self.instance_protocol = listener.instance_protocol
if listener.ssl_certificate_id not in ["Invalid-Certificate", None]:
self.certificate_id = cert_service.get_by_name(get_name_from_arn(listener.ssl_certificate_id)).id
def as_dict(self):
return {c.name: getattr(self, c.name) for c in self.__table__.columns}
def serialize(self):
blob = self.as_dict()
del blob['date_created']
return blob

162
lemur/listeners/service.py Normal file
View File

@ -0,0 +1,162 @@
"""
.. module: lemur.listeners.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 sqlalchemy import func
from lemur import database
from lemur.exceptions import CertificateUnavailable
from lemur.elbs.models import ELB
from lemur.listeners.models import Listener
from lemur.elbs import service as elb_service
from lemur.certificates import service as certificate_service
from lemur.common.services.aws.elb import update_listeners, create_new_listeners, delete_listeners
def verify_attachment(certificate_id, elb_account_number):
"""
Ensures that the certificate we want ot attach to our listener is
in the same account as our listener.
:rtype : Certificate
:param certificate_id:
:param elb_account_number:
:return: :raise CertificateUnavailable:
"""
cert = certificate_service.get(certificate_id)
# we need to ensure that the specified cert is in our account
for account in cert.accounts:
if account.account_number == elb_account_number:
break
else:
raise CertificateUnavailable
return cert
def get(listener_id):
return database.get(Listener, listener_id)
def create(elb_id, instance_protocol, instance_port, load_balancer_port, load_balancer_protocol, certificate_id=None):
listener = Listener(elb_id,
instance_port,
instance_protocol,
load_balancer_port,
load_balancer_protocol
)
elb = elb_service.get(elb_id)
elb.listeners.append(listener)
account_number = elb.account.account_number
cert = verify_attachment(certificate_id, account_number)
listener_tuple = (load_balancer_port, instance_port, load_balancer_protocol, cert.get_art(account_number),)
create_new_listeners(account_number, elb.region, elb.name, [listener_tuple])
return {'message': 'Listener has been created'}
def update(listener_id, **kwargs):
listener = get(listener_id)
# if the lb_port has changed we need to make sure we are deleting
# the listener on the old port to avoid listener duplication
ports = []
if listener.load_balancer_port != kwargs.get('load_balancer_port'):
ports.append(listener.load_balancer_port)
else:
ports.append(kwargs.get('load_balancer_port'))
certificate_id = kwargs.get('certificate_id')
listener.instance_port = kwargs.get('instance_port')
listener.instance_protocol = kwargs.get('instance_protocol')
listener.load_balancer_port = kwargs.get('load_balancer_port')
listener.load_balancer_protocol = kwargs.get('load_balancer_protocol')
elb = listener.elb
account_number = listener.elb.account.account_number
arn = None
if certificate_id:
cert = verify_attachment(certificate_id, account_number)
cert.elb_listeners.append(listener)
arn = cert.get_arn(account_number)
# remove certificate that is no longer wanted
if listener.certificate and not certificate_id:
listener.certificate.remove()
database.update(listener)
listener_tuple = (listener.load_balancer_port, listener.instance_port, listener.load_balancer_protocol, arn,)
update_listeners(account_number, elb.region, elb.name, [listener_tuple], ports)
return {'message': 'Listener has been updated'}
def delete(listener_id):
# first try to delete the listener in aws
listener = get(listener_id)
delete_listeners(listener.elb.account.account_number, listener.elb.region, listener.elb.name, [listener.load_balancer_port])
# cleanup operation in lemur
database.delete(listener)
def render(args):
query = database.session_query(Listener)
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)
elb_id = args.pop('elb_id', None)
if certificate_id:
query = database.get_all(Listener, certificate_id, field='certificate_id')
if elb_id:
query = query.filter(Listener.elb_id == elb_id)
if filt:
terms = filt.split(';')
query = database.filter(query, Listener, terms)
query = database.find_all(query, Listener, args)
if sort_by and sort_dir:
query = database.sort(query, Listener, sort_by, sort_dir)
return database.paginate(query, page, count)
def stats(**kwargs):
attr = getattr(Listener, kwargs.get('metric'))
query = database.db.session.query(attr, func.count(attr))
query = query.join(Listener.elb)
if kwargs.get('account_id'):
query = query.filter(ELB.account_id == kwargs.get('account_id'))
if kwargs.get('active') == 'true':
query = query.filter(Listener.certificate_id != None)
items = query.group_by(attr).all()
results = []
for key, count in items:
if key:
results.append({"key": key, "y": count})
return results

128
lemur/listeners/views.py Normal file
View File

@ -0,0 +1,128 @@
"""
.. module: lemur.listeners.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 flask import Blueprint
from flask.ext.restful import reqparse, Api, fields
from lemur.listeners import service
from lemur.auth.service import AuthenticatedResource
from lemur.auth.permissions import admin_permission
from lemur.common.utils import marshal_items, paginated_parser
mod = Blueprint('listeners', __name__)
api = Api(mod)
FIELDS = {
'id': fields.Integer,
'elbId': fields.Integer(attribute="elb_id"),
'certificateId': fields.Integer(attribute="certificate_id"),
'instancePort': fields.Integer(attribute="instance_port"),
'instanceProtocol': fields.String(attribute="instance_protocol"),
'loadBalancerPort': fields.Integer(attribute="load_balancer_port"),
'loadBalancerProtocol': fields.String(attribute="load_balancer_protocol")
}
class ListenersList(AuthenticatedResource):
def __init__(self):
super(ListenersList, self).__init__()
@marshal_items(FIELDS)
def get(self):
parser = paginated_parser.copy()
parser.add_argument('certificateId', type=int, dest='certificate_id', location='args')
args = parser.parse_args()
return service.render(args)
class ListenersCertificateList(AuthenticatedResource):
def __init__(self):
super(ListenersCertificateList, self).__init__()
@marshal_items(FIELDS)
def get(self, certificate_id):
parser = paginated_parser.copy()
args = parser.parse_args()
args['certificate_id'] = certificate_id
return service.render(args)
class ListenersELBList(AuthenticatedResource):
def __init__(self):
super(ListenersELBList, self).__init__()
@marshal_items(FIELDS)
def get(self, elb_id):
parser = paginated_parser.copy()
args = parser.parse_args()
args['elb_id'] = elb_id
return service.render(args)
class ListenersStats(AuthenticatedResource):
def __init__(self):
self.reqparse = reqparse.RequestParser()
super(ListenersStats, self).__init__()
def get(self):
self.reqparse.add_argument('metric', type=str, location='args')
self.reqparse.add_argument('accountId', dest='account_id', location='args')
self.reqparse.add_argument('active', type=str, default='true', location='args')
args = self.reqparse.parse_args()
items = service.stats(**args)
return {"items": items, "total": len(items)}
class Listeners(AuthenticatedResource):
def __init__(self):
super(Listeners, self).__init__()
@marshal_items(FIELDS)
def get(self, listener_id):
return service.get(listener_id)
@admin_permission.require(http_exception=403)
@marshal_items(FIELDS)
def post(self):
self.reqparse.add_argument('elbId', type=str, dest='elb_id', required=True, location='json')
self.reqparse.add_argument('instanceProtocol', type=str, dest='instance_protocol', required=True, location='json')
self.reqparse.add_argument('instancePort', type=int, dest='instance_port', required=True, location='json')
self.reqparse.add_argument('loadBalancerProtocol', type=str, dest='load_balancer_protocol', required=True, location='json')
self.reqparse.add_argument('loadBalancerPort', type=int, dest='load_balancer_port', required=True, location='json')
self.reqparse.add_argument('certificateId', type=int, dest='certificate_id', location='json')
args = self.reqparse.parse_args()
return service.create(**args)
@admin_permission.require(http_exception=403)
@marshal_items(FIELDS)
def put(self, listener_id):
self.reqparse.add_argument('instanceProtocol', type=str, dest='instance_protocol', required=True, location='json')
self.reqparse.add_argument('instancePort', type=int, dest='instance_port', required=True, location='json')
self.reqparse.add_argument('loadBalancerProtocol', type=str, dest='load_balancer_protocol', required=True, location='json')
self.reqparse.add_argument('loadBalancerPort', type=int, dest='load_balancer_port', required=True, location='json')
self.reqparse.add_argument('certificateId', type=int, dest='certificate_id', location='json')
args = self.reqparse.parse_args()
return service.update(listener_id, **args)
@admin_permission.require(http_exception=403)
def delete(self, listener_id):
return service.delete(listener_id)
api.add_resource(ListenersList, '/listeners', endpoint='listeners')
api.add_resource(Listeners, '/listeners/<int:listener_id>', endpoint='listener')
api.add_resource(ListenersStats, '/listeners/stats', endpoint='listenersStats')
api.add_resource(ListenersCertificateList, '/certificates/<int:certificate_id>/listeners', endpoint='listenersCertificates')
api.add_resource(ListenersELBList, '/elbs/<int:elb_id>/listeners', endpoint='elbListeners')