Merge pull request #3208 from quay/project/2-spaces

Fix formatting for the config app
This commit is contained in:
Sam Chow 2018-08-17 10:30:22 -04:00 committed by GitHub
commit 8eb7d73f22
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 936 additions and 913 deletions

View file

@ -2,7 +2,6 @@ import os
import re import re
import subprocess import subprocess
# Note: this currently points to the directory above, since we're in the quay config_app dir # Note: this currently points to the directory above, since we're in the quay config_app dir
# TODO(config_extract): revert to root directory rather than the one above # TODO(config_extract): revert to root directory rather than the one above
ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
@ -15,7 +14,6 @@ TEMPLATE_DIR = os.path.join(ROOT_DIR, 'templates/')
IS_KUBERNETES = 'KUBERNETES_SERVICE_HOST' in os.environ IS_KUBERNETES = 'KUBERNETES_SERVICE_HOST' in os.environ
def _get_version_number_changelog(): def _get_version_number_changelog():
try: try:
with open(os.path.join(ROOT_DIR, 'CHANGELOG.md')) as f: with open(os.path.join(ROOT_DIR, 'CHANGELOG.md')) as f:

View file

@ -28,10 +28,12 @@ config_provider = get_config_provider(OVERRIDE_CONFIG_DIRECTORY, 'config.yaml',
if is_testing: if is_testing:
from test.testconfig import TestConfig from test.testconfig import TestConfig
logger.debug('Loading test config.') logger.debug('Loading test config.')
app.config.from_object(TestConfig()) app.config.from_object(TestConfig())
else: else:
from config import DefaultConfig from config import DefaultConfig
logger.debug('Loading default config.') logger.debug('Loading default config.')
app.config.from_object(DefaultConfig()) app.config.from_object(DefaultConfig())
app.teardown_request(database.close_db_filter) app.teardown_request(database.close_db_filter)

View file

@ -3,7 +3,6 @@ from config_app.c_app import app as application
# Bind all of the blueprints # Bind all of the blueprints
import config_web import config_web
if __name__ == '__main__': if __name__ == '__main__':
logging.config.fileConfig(logfile_path(debug=True), disable_existing_loggers=False) logging.config.fileConfig(logfile_path(debug=True), disable_existing_loggers=False)
application.run(port=5000, debug=True, threaded=True, host='0.0.0.0') application.run(port=5000, debug=True, threaded=True, host='0.0.0.0')

View file

@ -7,7 +7,6 @@ from config_app.c_app import app
from config_app.config_endpoints.api import method_metadata from config_app.config_endpoints.api import method_metadata
from config_app.config_endpoints.common import fully_qualified_name, PARAM_REGEX, TYPE_CONVERTER from config_app.config_endpoints.common import fully_qualified_name, PARAM_REGEX, TYPE_CONVERTER
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -82,7 +81,8 @@ def generate_route_data():
paths[swagger_path] = path_swagger paths[swagger_path] = path_swagger
# Add any global path parameters. # Add any global path parameters.
param_data_map = view_class.__api_path_params if '__api_path_params' in dir(view_class) else {} param_data_map = view_class.__api_path_params if '__api_path_params' in dir(
view_class) else {}
if param_data_map: if param_data_map:
path_parameters_swagger = [] path_parameters_swagger = []
for path_parameter in param_data_map: for path_parameter in param_data_map:
@ -128,7 +128,8 @@ def generate_route_data():
if rule.arguments: if rule.arguments:
for path_parameter in rule.arguments: for path_parameter in rule.arguments:
description = param_data_map.get(path_parameter, {}).get('description') description = param_data_map.get(path_parameter, {}).get('description')
operation_swagger['parameters'].append(swagger_parameter(path_parameter, description)) operation_swagger['parameters'].append(
swagger_parameter(path_parameter, description))
# Add the query parameters. # Add the query parameters.
if '__api_query_params' in dir(method): if '__api_query_params' in dir(method):

View file

@ -3,7 +3,8 @@ import logging
from flask import abort, request from flask import abort, request
from config_app.config_endpoints.api.suconfig_models_pre_oci import pre_oci_model as model from config_app.config_endpoints.api.suconfig_models_pre_oci import pre_oci_model as model
from config_app.config_endpoints.api import resource, ApiResource, nickname, validate_json_request, kubernetes_only from config_app.config_endpoints.api import resource, ApiResource, nickname, validate_json_request, \
kubernetes_only
from config_app.c_app import (app, config_provider, superusers, ip_resolver, from config_app.c_app import (app, config_provider, superusers, ip_resolver,
instance_keys, INIT_SCRIPTS_LOCATION) instance_keys, INIT_SCRIPTS_LOCATION)
from config_app.config_util.k8saccessor import KubernetesAccessorSingleton from config_app.config_util.k8saccessor import KubernetesAccessorSingleton
@ -11,7 +12,8 @@ from config_app.config_util.k8saccessor import KubernetesAccessorSingleton
from data.database import configure from data.database import configure
from data.runmigration import run_alembic_migration from data.runmigration import run_alembic_migration
from util.config.configutil import add_enterprise_config_defaults from util.config.configutil import add_enterprise_config_defaults
from util.config.validator import validate_service_for_config, ValidatorContext, is_valid_config_upload_filename from util.config.validator import validate_service_for_config, ValidatorContext, \
is_valid_config_upload_filename
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -85,6 +87,7 @@ class SuperUserRegistryStatus(ApiResource):
""" Resource for determining the status of the registry, such as if config exists, """ Resource for determining the status of the registry, such as if config exists,
if a database is configured, and if it has any defined users. if a database is configured, and if it has any defined users.
""" """
@nickname('scRegistryStatus') @nickname('scRegistryStatus')
def get(self): def get(self):
""" Returns the status of the registry. """ """ Returns the status of the registry. """
@ -121,6 +124,7 @@ class _AlembicLogHandler(logging.Handler):
@resource('/v1/superuser/setupdb') @resource('/v1/superuser/setupdb')
class SuperUserSetupDatabase(ApiResource): class SuperUserSetupDatabase(ApiResource):
""" Resource for invoking alembic to setup the database. """ """ Resource for invoking alembic to setup the database. """
@nickname('scSetupDatabase') @nickname('scSetupDatabase')
def get(self): def get(self):
""" Invokes the alembic upgrade process. """ """ Invokes the alembic upgrade process. """
@ -251,7 +255,8 @@ class SuperUserConfigValidate(ApiResource):
# so we also allow it to be called if there is no valid registry configuration setup. Note that # so we also allow it to be called if there is no valid registry configuration setup. Note that
# this is also safe since this method does not access any information not given in the request. # this is also safe since this method does not access any information not given in the request.
config = request.get_json()['config'] config = request.get_json()['config']
validator_context = ValidatorContext.from_app(app, config, request.get_json().get('password', ''), validator_context = ValidatorContext.from_app(app, config,
request.get_json().get('password', ''),
instance_keys=instance_keys, instance_keys=instance_keys,
ip_resolver=ip_resolver, ip_resolver=ip_resolver,
config_provider=config_provider, config_provider=config_provider,
@ -294,6 +299,7 @@ class SuperUserKubernetesDeployment(ApiResource):
@resource('/v1/superuser/config/kubernetes') @resource('/v1/superuser/config/kubernetes')
class SuperUserKubernetesConfiguration(ApiResource): class SuperUserKubernetesConfiguration(ApiResource):
""" Resource for saving the config files to kubernetes secrets. """ """ Resource for saving the config files to kubernetes secrets. """
@kubernetes_only @kubernetes_only
@nickname('scDeployConfiguration') @nickname('scDeployConfiguration')
def post(self): def post(self):
@ -303,6 +309,7 @@ class SuperUserKubernetesConfiguration(ApiResource):
@resource('/v1/superuser/config/file/<filename>') @resource('/v1/superuser/config/file/<filename>')
class SuperUserConfigFile(ApiResource): class SuperUserConfigFile(ApiResource):
""" Resource for fetching the status of config files and overriding them. """ """ Resource for fetching the status of config files and overriding them. """
@nickname('scConfigFileExists') @nickname('scConfigFileExists')
def get(self, filename): def get(self, filename):
""" Returns whether the configuration file with the given name exists. """ """ Returns whether the configuration file with the given name exists. """
@ -313,7 +320,6 @@ class SuperUserConfigFile(ApiResource):
'exists': config_provider.volume_file_exists(filename) 'exists': config_provider.volume_file_exists(filename)
} }
@nickname('scUpdateConfigFile') @nickname('scUpdateConfigFile')
def post(self, filename): def post(self, filename):
""" Updates the configuration file with the given name. """ """ Updates the configuration file with the given name. """

View file

@ -14,9 +14,12 @@ def user_view(user):
class RepositoryBuild(namedtuple('RepositoryBuild', class RepositoryBuild(namedtuple('RepositoryBuild',
['uuid', 'logs_archived', 'repository_namespace_user_username', 'repository_name', ['uuid', 'logs_archived', 'repository_namespace_user_username',
'can_write', 'can_read', 'pull_robot', 'resource_key', 'trigger', 'display_name', 'repository_name',
'started', 'job_config', 'phase', 'status', 'error', 'archive_url'])): 'can_write', 'can_read', 'pull_robot', 'resource_key', 'trigger',
'display_name',
'started', 'job_config', 'phase', 'status', 'error',
'archive_url'])):
""" """
RepositoryBuild represents a build associated with a repostiory RepositoryBuild represents a build associated with a repostiory
:type uuid: string :type uuid: string
@ -89,7 +92,8 @@ class Approval(namedtuple('Approval', ['approver', 'approval_type', 'approved_da
} }
class ServiceKey(namedtuple('ServiceKey', ['name', 'kid', 'service', 'jwk', 'metadata', 'created_date', class ServiceKey(
namedtuple('ServiceKey', ['name', 'kid', 'service', 'jwk', 'metadata', 'created_date',
'expiration_date', 'rotation_duration', 'approval'])): 'expiration_date', 'rotation_duration', 'approval'])):
""" """
ServiceKey is an apostille signing key ServiceKey is an apostille signing key
@ -156,13 +160,12 @@ class Organization(namedtuple('Organization', ['username', 'email'])):
} }
@add_metaclass(ABCMeta) @add_metaclass(ABCMeta)
class SuperuserDataInterface(object): class SuperuserDataInterface(object):
""" """
Interface that represents all data store interactions required by a superuser api. Interface that represents all data store interactions required by a superuser api.
""" """
@abstractmethod @abstractmethod
def list_all_service_keys(self): def list_all_service_keys(self):
""" """

View file

@ -1,6 +1,8 @@
from data import model from data import model
from config_app.config_endpoints.api.superuser_models_interface import SuperuserDataInterface, User, ServiceKey, Approval from config_app.config_endpoints.api.superuser_models_interface import (SuperuserDataInterface, User, ServiceKey,
Approval)
def _create_user(user): def _create_user(user):
if user is None: if user is None:
@ -11,12 +13,15 @@ def _create_user(user):
def _create_key(key): def _create_key(key):
approval = None approval = None
if key.approval is not None: if key.approval is not None:
approval = Approval(_create_user(key.approval.approver), key.approval.approval_type, key.approval.approved_date, approval = Approval(_create_user(key.approval.approver), key.approval.approval_type,
key.approval.approved_date,
key.approval.notes) key.approval.notes)
return ServiceKey(key.name, key.kid, key.service, key.jwk, key.metadata, key.created_date, key.expiration_date, return ServiceKey(key.name, key.kid, key.service, key.jwk, key.metadata, key.created_date,
key.expiration_date,
key.rotation_duration, approval) key.rotation_duration, approval)
class ServiceKeyDoesNotExist(Exception): class ServiceKeyDoesNotExist(Exception):
pass pass
@ -30,6 +35,7 @@ class PreOCIModel(SuperuserDataInterface):
PreOCIModel implements the data model for the SuperUser using a database schema PreOCIModel implements the data model for the SuperUser using a database schema
before it was changed to support the OCI specification. before it was changed to support the OCI specification.
""" """
def list_all_service_keys(self): def list_all_service_keys(self):
keys = model.service_keys.list_all_keys() keys = model.service_keys.list_all_keys()
return [_create_key(key) for key in keys] return [_create_key(key) for key in keys]
@ -43,8 +49,10 @@ class PreOCIModel(SuperuserDataInterface):
except model.ServiceKeyAlreadyApproved: except model.ServiceKeyAlreadyApproved:
raise ServiceKeyAlreadyApproved raise ServiceKeyAlreadyApproved
def generate_service_key(self, service, expiration_date, kid=None, name='', metadata=None, rotation_duration=None): def generate_service_key(self, service, expiration_date, kid=None, name='', metadata=None,
(private_key, key) = model.service_keys.generate_service_key(service, expiration_date, metadata=metadata, name=name) rotation_duration=None):
(private_key, key) = model.service_keys.generate_service_key(service, expiration_date,
metadata=metadata, name=name)
return private_key, key.kid return private_key, key.kid

View file

@ -10,6 +10,7 @@ from config_app.c_app import app, config_provider
from config_app.config_endpoints.api import resource, ApiResource, nickname from config_app.config_endpoints.api import resource, ApiResource, nickname
from config_app.config_util.tar import tarinfo_filter_partial, strip_absolute_path_and_add_trailing_dir from config_app.config_util.tar import tarinfo_filter_partial, strip_absolute_path_and_add_trailing_dir
@resource('/v1/configapp/initialization') @resource('/v1/configapp/initialization')
class ConfigInitialization(ApiResource): class ConfigInitialization(ApiResource):
""" """

View file

@ -16,4 +16,3 @@ class User(ApiResource):
# raise InvalidToken("Requires authentication", payload={'session_required': False}) # raise InvalidToken("Requires authentication", payload={'session_required': False})
return user_view(user) return user_view(user)

View file

@ -60,5 +60,3 @@ def render_page_template(name, route_data=None, js_bundle_name=DEFAULT_JS_BUNDLE
def fully_qualified_name(method_view_class): def fully_qualified_name(method_view_class):
return '%s.%s' % (method_view_class.__module__, method_view_class.__name__) return '%s.%s' % (method_view_class.__module__, method_view_class.__name__)

View file

@ -56,7 +56,6 @@ class ApiException(HTTPException):
return rv return rv
class InvalidRequest(ApiException): class InvalidRequest(ApiException):
def __init__(self, error_description, payload=None): def __init__(self, error_description, payload=None):
ApiException.__init__(self, ApiErrorType.invalid_request, 400, error_description, payload) ApiException.__init__(self, ApiErrorType.invalid_request, 400, error_description, payload)

View file

@ -5,7 +5,6 @@ from config_app.config_endpoints.common import render_page_template
from config_app.config_endpoints.api.discovery import generate_route_data from config_app.config_endpoints.api.discovery import generate_route_data
from config_app.config_endpoints.api import no_cache from config_app.config_endpoints.api import no_cache
setup_web = Blueprint('setup_web', __name__, template_folder='templates') setup_web = Blueprint('setup_web', __name__, template_folder='templates')
@ -22,5 +21,3 @@ def render_page_template_with_routedata(name, *args, **kwargs):
@setup_web.route('/', methods=['GET'], defaults={'path': ''}) @setup_web.route('/', methods=['GET'], defaults={'path': ''})
def index(path, **kwargs): def index(path, **kwargs):
return render_page_template_with_routedata('index.html', js_bundle_name='configapp', **kwargs) return render_page_template_with_routedata('index.html', js_bundle_name='configapp', **kwargs)

View file

@ -10,6 +10,7 @@ class TransientDirectoryProvider(FileConfigProvider):
from/to the file system, only using temporary directories, from/to the file system, only using temporary directories,
deleting old dirs and creating new ones as requested. deleting old dirs and creating new ones as requested.
""" """
def __init__(self, config_volume, yaml_filename, py_filename): def __init__(self, config_volume, yaml_filename, py_filename):
# Create a temp directory that will be cleaned up when we change the config path # Create a temp directory that will be cleaned up when we change the config path
# This should ensure we have no "pollution" of different configs: # This should ensure we have no "pollution" of different configs:

View file

@ -9,6 +9,7 @@ logger = logging.getLogger(__name__)
class BaseFileProvider(BaseProvider): class BaseFileProvider(BaseProvider):
""" Base implementation of the config provider that reads the data from the file system. """ """ Base implementation of the config provider that reads the data from the file system. """
def __init__(self, config_volume, yaml_filename, py_filename): def __init__(self, config_volume, yaml_filename, py_filename):
self.config_volume = config_volume self.config_volume = config_volume
self.yaml_filename = yaml_filename self.yaml_filename = yaml_filename

View file

@ -4,7 +4,6 @@ import logging
from config_app.config_util.config.baseprovider import export_yaml, CannotWriteConfigException from config_app.config_util.config.baseprovider import export_yaml, CannotWriteConfigException
from config_app.config_util.config.basefileprovider import BaseFileProvider from config_app.config_util.config.basefileprovider import BaseFileProvider
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -21,6 +20,7 @@ def _ensure_parent_dir(filepath):
class FileConfigProvider(BaseFileProvider): class FileConfigProvider(BaseFileProvider):
""" Implementation of the config provider that reads and writes the data """ Implementation of the config provider that reads and writes the data
from/to the file system. """ from/to the file system. """
def __init__(self, config_volume, yaml_filename, py_filename): def __init__(self, config_volume, yaml_filename, py_filename):
super(FileConfigProvider, self).__init__(config_volume, yaml_filename, py_filename) super(FileConfigProvider, self).__init__(config_volume, yaml_filename, py_filename)

View file

@ -1,7 +1,6 @@
import json import json
import io import io
import os import os
from datetime import datetime, timedelta
from config_app.config_util.config.baseprovider import BaseProvider from config_app.config_util.config.baseprovider import BaseProvider
@ -11,6 +10,7 @@ REAL_FILES = ['test/data/signing-private.gpg', 'test/data/signing-public.gpg', '
class TestConfigProvider(BaseProvider): class TestConfigProvider(BaseProvider):
""" Implementation of the config provider for testing. Everything is kept in-memory instead on """ Implementation of the config provider for testing. Everything is kept in-memory instead on
the real file system. """ the real file system. """
def __init__(self): def __init__(self):
self.clear() self.clear()
@ -78,4 +78,3 @@ class TestConfigProvider(BaseProvider):
def get_volume_path(self, directory, filename): def get_volume_path(self, directory, filename):
return os.path.join(directory, filename) return os.path.join(directory, filename)

View file

@ -11,6 +11,7 @@ logger = logging.getLogger(__name__)
QE_DEPLOYMENT_LABEL = 'quay-enterprise-component' QE_DEPLOYMENT_LABEL = 'quay-enterprise-component'
class KubernetesAccessorSingleton(object): class KubernetesAccessorSingleton(object):
""" Singleton allowing access to kubernetes operations """ """ Singleton allowing access to kubernetes operations """
_instance = None _instance = None
@ -79,7 +80,6 @@ class KubernetesAccessorSingleton(object):
} }
}, api_prefix='apis/extensions/v1beta1', content_type='application/strategic-merge-patch+json')) }, api_prefix='apis/extensions/v1beta1', content_type='application/strategic-merge-patch+json'))
def _assert_success(self, response): def _assert_success(self, response):
if response.status_code != 200: if response.status_code != 200:
logger.error('Kubernetes API call failed with response: %s => %s', response.status_code, logger.error('Kubernetes API call failed with response: %s => %s', response.status_code,

View file

@ -8,9 +8,11 @@ DEFAULT_QE_CONFIG_SECRET = 'quay-enterprise-config-secret'
# The name of the quay enterprise deployment (not config app) that is used to query & rollout # The name of the quay enterprise deployment (not config app) that is used to query & rollout
DEFAULT_QE_DEPLOYMENT_SELECTOR = 'app' DEFAULT_QE_DEPLOYMENT_SELECTOR = 'app'
def get_k8s_namespace(): def get_k8s_namespace():
return os.environ.get('QE_K8S_NAMESPACE', DEFAULT_QE_NAMESPACE) return os.environ.get('QE_K8S_NAMESPACE', DEFAULT_QE_NAMESPACE)
class KubernetesConfig(object): class KubernetesConfig(object):
def __init__(self, api_host='', service_account_token=SERVICE_ACCOUNT_TOKEN_PATH, def __init__(self, api_host='', service_account_token=SERVICE_ACCOUNT_TOKEN_PATH,
qe_namespace=DEFAULT_QE_NAMESPACE, qe_namespace=DEFAULT_QE_NAMESPACE,
@ -42,6 +44,3 @@ class KubernetesConfig(object):
return cls(api_host=api_host, service_account_token=service_token, qe_namespace=qe_namespace, return cls(api_host=api_host, service_account_token=service_token, qe_namespace=qe_namespace,
qe_config_secret=qe_config_secret, qe_deployment_selector=qe_deployment_selector) qe_config_secret=qe_config_secret, qe_deployment_selector=qe_deployment_selector)

View file

@ -2,10 +2,12 @@ from fnmatch import fnmatch
import OpenSSL import OpenSSL
class CertInvalidException(Exception): class CertInvalidException(Exception):
""" Exception raised when a certificate could not be parsed/loaded. """ """ Exception raised when a certificate could not be parsed/loaded. """
pass pass
class KeyInvalidException(Exception): class KeyInvalidException(Exception):
""" Exception raised when a key could not be parsed/loaded or successfully applied to a cert. """ """ Exception raised when a key could not be parsed/loaded or successfully applied to a cert. """
pass pass
@ -24,8 +26,10 @@ def load_certificate(cert_contents):
_SUBJECT_ALT_NAME = 'subjectAltName' _SUBJECT_ALT_NAME = 'subjectAltName'
class SSLCertificate(object): class SSLCertificate(object):
""" Helper class for easier working with SSL certificates. """ """ Helper class for easier working with SSL certificates. """
def __init__(self, openssl_cert): def __init__(self, openssl_cert):
self.openssl_cert = openssl_cert self.openssl_cert = openssl_cert

View file

@ -1,11 +1,13 @@
from util.config.validator import EXTRA_CA_DIRECTORY from util.config.validator import EXTRA_CA_DIRECTORY
def strip_absolute_path_and_add_trailing_dir(path): def strip_absolute_path_and_add_trailing_dir(path):
""" """
Removes the initial trailing / from the prefix path, and add the last dir one Removes the initial trailing / from the prefix path, and add the last dir one
""" """
return path[1:] + '/' return path[1:] + '/'
def tarinfo_filter_partial(prefix): def tarinfo_filter_partial(prefix):
def tarinfo_filter(tarinfo): def tarinfo_filter(tarinfo):
# remove leading directory info # remove leading directory info

View file

@ -1,23 +1,25 @@
import pytest import pytest
import re
from httmock import urlmatch, HTTMock, response from httmock import urlmatch, HTTMock, response
from config_app.config_util.k8saccessor import KubernetesAccessorSingleton from config_app.config_util.k8saccessor import KubernetesAccessorSingleton
from config_app.config_util.k8sconfig import KubernetesConfig from config_app.config_util.k8sconfig import KubernetesConfig
@pytest.mark.parametrize('kube_config, expected_api, expected_query', [ @pytest.mark.parametrize('kube_config, expected_api, expected_query', [
({'api_host': 'www.customhost.com'}, ({'api_host': 'www.customhost.com'},
'/apis/extensions/v1beta1/namespaces/quay-enterprise/deployments', 'labelSelector=quay-enterprise-component%3Dapp'), '/apis/extensions/v1beta1/namespaces/quay-enterprise/deployments', 'labelSelector=quay-enterprise-component%3Dapp'),
({'api_host': 'www.customhost.com', 'qe_deployment_selector': 'custom-selector'}, ({'api_host': 'www.customhost.com', 'qe_deployment_selector': 'custom-selector'},
'/apis/extensions/v1beta1/namespaces/quay-enterprise/deployments', 'labelSelector=quay-enterprise-component%3Dcustom-selector'), '/apis/extensions/v1beta1/namespaces/quay-enterprise/deployments',
'labelSelector=quay-enterprise-component%3Dcustom-selector'),
({'api_host': 'www.customhost.com', 'qe_namespace': 'custom-namespace'}, ({'api_host': 'www.customhost.com', 'qe_namespace': 'custom-namespace'},
'/apis/extensions/v1beta1/namespaces/custom-namespace/deployments', 'labelSelector=quay-enterprise-component%3Dapp'), '/apis/extensions/v1beta1/namespaces/custom-namespace/deployments', 'labelSelector=quay-enterprise-component%3Dapp'),
({'api_host': 'www.customhost.com', 'qe_namespace': 'custom-namespace', 'qe_deployment_selector': 'custom-selector'}, ({'api_host': 'www.customhost.com', 'qe_namespace': 'custom-namespace', 'qe_deployment_selector': 'custom-selector'},
'/apis/extensions/v1beta1/namespaces/custom-namespace/deployments', 'labelSelector=quay-enterprise-component%3Dcustom-selector'), '/apis/extensions/v1beta1/namespaces/custom-namespace/deployments',
'labelSelector=quay-enterprise-component%3Dcustom-selector'),
]) ])
def test_get_qe_deployments(kube_config, expected_api, expected_query): def test_get_qe_deployments(kube_config, expected_api, expected_query):
config = KubernetesConfig(**kube_config) config = KubernetesConfig(**kube_config)
@ -36,12 +38,15 @@ def test_get_qe_deployments(kube_config, expected_api, expected_query):
assert url_hit[0] assert url_hit[0]
@pytest.mark.parametrize('kube_config, deployment_names, expected_api_hits', [ @pytest.mark.parametrize('kube_config, deployment_names, expected_api_hits', [
({'api_host': 'www.customhost.com'}, [], []), ({'api_host': 'www.customhost.com'}, [], []),
({'api_host':'www.customhost.com'}, ['myDeployment'], ['/apis/extensions/v1beta1/namespaces/quay-enterprise/deployments/myDeployment']), ({'api_host': 'www.customhost.com'}, ['myDeployment'],
['/apis/extensions/v1beta1/namespaces/quay-enterprise/deployments/myDeployment']),
({'api_host': 'www.customhost.com', 'qe_namespace': 'custom-namespace'}, ({'api_host': 'www.customhost.com', 'qe_namespace': 'custom-namespace'},
['myDeployment', 'otherDeployment'], ['myDeployment', 'otherDeployment'],
['/apis/extensions/v1beta1/namespaces/custom-namespace/deployments/myDeployment', '/apis/extensions/v1beta1/namespaces/custom-namespace/deployments/otherDeployment']), ['/apis/extensions/v1beta1/namespaces/custom-namespace/deployments/myDeployment',
'/apis/extensions/v1beta1/namespaces/custom-namespace/deployments/otherDeployment']),
]) ])
def test_cycle_qe_deployments(kube_config, deployment_names, expected_api_hits): def test_cycle_qe_deployments(kube_config, deployment_names, expected_api_hits):
KubernetesAccessorSingleton._instance = None KubernetesAccessorSingleton._instance = None

View file

@ -6,6 +6,7 @@ from util.config.validator import EXTRA_CA_DIRECTORY
from test.fixtures import * from test.fixtures import *
class MockTarInfo: class MockTarInfo:
def __init__(self, name, isdir): def __init__(self, name, isdir):
self.name = name self.name = name
@ -14,13 +15,15 @@ class MockTarInfo:
def __eq__(self, other): def __eq__(self, other):
return other is not None and self.name == other.name return other is not None and self.name == other.name
@pytest.mark.parametrize('prefix,tarinfo,expected', [ @pytest.mark.parametrize('prefix,tarinfo,expected', [
# It should handle simple files # It should handle simple files
('Users/sam/', MockTarInfo('Users/sam/config.yaml', False), MockTarInfo('config.yaml', False)), ('Users/sam/', MockTarInfo('Users/sam/config.yaml', False), MockTarInfo('config.yaml', False)),
# It should allow the extra CA dir # It should allow the extra CA dir
('Users/sam/', MockTarInfo('Users/sam/%s' % EXTRA_CA_DIRECTORY, True), MockTarInfo('%s' % EXTRA_CA_DIRECTORY, True)), ('Users/sam/', MockTarInfo('Users/sam/%s' % EXTRA_CA_DIRECTORY, True), MockTarInfo('%s' % EXTRA_CA_DIRECTORY, True)),
# it should allow a file in that extra dir # it should allow a file in that extra dir
('Users/sam/', MockTarInfo('Users/sam/%s/cert.crt' % EXTRA_CA_DIRECTORY, False), MockTarInfo('%s/cert.crt' % EXTRA_CA_DIRECTORY, False)), ('Users/sam/', MockTarInfo('Users/sam/%s/cert.crt' % EXTRA_CA_DIRECTORY, False),
MockTarInfo('%s/cert.crt' % EXTRA_CA_DIRECTORY, False)),
# it should not allow a directory that isn't the CA dir # it should not allow a directory that isn't the CA dir
('Users/sam/', MockTarInfo('Users/sam/dirignore', True), None), ('Users/sam/', MockTarInfo('Users/sam/dirignore', True), None),
]) ])

View file

@ -2,7 +2,5 @@ from config_app.c_app import app as application
from config_app.config_endpoints.api import api_bp from config_app.config_endpoints.api import api_bp
from config_app.config_endpoints.setup_web import setup_web from config_app.config_endpoints.setup_web import setup_web
application.register_blueprint(setup_web) application.register_blueprint(setup_web)
application.register_blueprint(api_bp, url_prefix='/api') application.register_blueprint(api_bp, url_prefix='/api')