initial commit
This commit is contained in:
0
lemur/listeners/__init__.py
Normal file
0
lemur/listeners/__init__.py
Normal file
43
lemur/listeners/models.py
Normal file
43
lemur/listeners/models.py
Normal 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
162
lemur/listeners/service.py
Normal 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
128
lemur/listeners/views.py
Normal 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')
|
Reference in New Issue
Block a user