""" .. module: lemur.endpoints.service :platform: Unix :synopsis: This module contains all of the services level functions used to administer endpoints in Lemur :copyright: (c) 2018 by Netflix Inc., see AUTHORS for more :license: Apache, see LICENSE for more details. .. moduleauthor:: Kevin Glisson """ import arrow from sqlalchemy import func from lemur import database from lemur.common.utils import truthiness from lemur.endpoints.models import Endpoint, Policy, Cipher from lemur.extensions import metrics def get_all(): """ Get all endpoints that are currently in Lemur. :rtype : List :return: """ query = database.session_query(Endpoint) return database.find_all(query, Endpoint, {}).all() def get(endpoint_id): """ Retrieves an endpoint given it's ID :param endpoint_id: :return: """ return database.get(Endpoint, endpoint_id) def get_by_name(name): """ Retrieves an endpoint given it's name. :param name: :return: """ return database.get(Endpoint, name, field='name') def get_by_dnsname(dnsname): """ Retrieves an endpoint given it's name. :param dnsname: :return: """ return database.get(Endpoint, dnsname, field='dnsname') def get_by_dnsname_and_port(dnsname, port): """ Retrieves and endpoint by it's dnsname and port. :param dnsname: :param port: :return: """ return Endpoint.query.filter(Endpoint.dnsname == dnsname).filter(Endpoint.port == port).scalar() def get_by_source(source_label): """ Retrieves all endpoints for a given source. :param source_label: :return: """ return Endpoint.query.filter(Endpoint.source.label == source_label).all() # noqa def get_all_pending_rotation(): """ Retrieves all endpoints which have certificates deployed that have been replaced. :return: """ return Endpoint.query.filter(Endpoint.replaced.any()).all() def create(**kwargs): """ Creates a new endpoint. :param kwargs: :return: """ endpoint = Endpoint(**kwargs) database.create(endpoint) metrics.send('endpoint_added', 'counter', 1, metric_tags={'source': endpoint.source.label}) return endpoint def get_or_create_policy(**kwargs): policy = database.get(Policy, kwargs['name'], field='name') if not policy: policy = Policy(**kwargs) database.create(policy) return policy def get_or_create_cipher(**kwargs): cipher = database.get(Cipher, kwargs['name'], field='name') if not cipher: cipher = Cipher(**kwargs) database.create(cipher) return cipher def update(endpoint_id, **kwargs): endpoint = database.get(Endpoint, endpoint_id) endpoint.policy = kwargs['policy'] endpoint.certificate = kwargs['certificate'] endpoint.source = kwargs['source'] endpoint.last_updated = arrow.utcnow() metrics.send('endpoint_updated', 'counter', 1, metric_tags={'source': endpoint.source.label}) database.update(endpoint) return endpoint def render(args): """ Helper that helps us render the REST Api responses. :param args: :return: """ query = database.session_query(Endpoint) filt = args.pop('filter') if filt: terms = filt.split(';') if 'active' in filt: # this is really weird but strcmp seems to not work here?? query = query.filter(Endpoint.active == truthiness(terms[1])) elif 'port' in filt: if terms[1] != 'null': # ng-table adds 'null' if a number is removed query = query.filter(Endpoint.port == terms[1]) elif 'ciphers' in filt: query = query.filter( Cipher.name == terms[1] ) else: query = database.filter(query, Endpoint, terms) return database.sort_and_page(query, Endpoint, args) def stats(**kwargs): """ Helper that defines some useful statistics about endpoints. :param kwargs: :return: """ attr = getattr(Endpoint, kwargs.get('metric')) query = database.db.session.query(attr, func.count(attr)) items = query.group_by(attr).all() keys = [] values = [] for key, count in items: keys.append(key) values.append(count) return {'labels': keys, 'values': values}