diff --git a/util/config/validator.py b/util/config/validator.py index 860e67254..4395221af 100644 --- a/util/config/validator.py +++ b/util/config/validator.py @@ -7,7 +7,6 @@ from hashlib import sha1 import ldap import peewee -import redis from flask import Flask from flask_mail import Mail, Message @@ -32,6 +31,7 @@ from util.security.ssl import load_certificate, CertInvalidException, KeyInvalid from util.config.validators.database import DatabaseValidator from util.config.validators.buildlogredis import RedisValidator +from util.config.validators.registrystorage import StorageValidator logger = logging.getLogger(__name__) @@ -50,19 +50,6 @@ CONFIG_FILENAMES = (SSL_FILENAMES + DB_SSL_FILENAMES + JWT_FILENAMES + ACI_CERT_ LDAP_FILENAMES) EXTRA_CA_DIRECTORY = 'extra_ca_certs' -def get_storage_providers(config): - storage_config = config.get('DISTRIBUTED_STORAGE_CONFIG', {}) - - drivers = {} - - try: - for name, parameters in storage_config.items(): - drivers[name] = (parameters[0], get_storage_driver(None, None, None, parameters)) - except TypeError: - logger.exception('Missing required storage configuration provider') - raise ConfigValidationException('Missing required parameter(s) for storage %s' % name) - - return drivers def validate_service_for_config(service, config, password=None): """ Attempts to validate the configuration for the given service. """ @@ -95,29 +82,6 @@ def _validate_database(config, user_obj, _): raise ex -def _validate_registry_storage(config, user_obj, _): - """ Validates registry storage. """ - replication_enabled = config.get('FEATURE_STORAGE_REPLICATION', False) - - providers = get_storage_providers(config).items() - if not providers: - raise ConfigValidationException('Storage configuration required') - - for name, (storage_type, driver) in providers: - try: - if replication_enabled and storage_type == 'LocalStorage': - raise ConfigValidationException('Locally mounted directory not supported ' + - 'with storage replication') - - # Run validation on the driver. - driver.validate(app.config['HTTPCLIENT']) - - # Run setup on the driver if the read/write succeeded. - driver.setup() - except Exception as ex: - raise ConfigValidationException('Invalid storage configuration: %s: %s' % (name, str(ex))) - - def _validate_mailing(config, user_obj, _): """ Validates sending email. """ test_app = Flask("mail-test-app") @@ -517,7 +481,7 @@ def _validate_bittorrent(config, user_obj, _): VALIDATORS = { DatabaseValidator.name: DatabaseValidator.validate, RedisValidator.name: RedisValidator.validate, - 'registry-storage': _validate_registry_storage, + StorageValidator.name: StorageValidator.validate, 'mail': _validate_mailing, 'github-login': _validate_github('GITHUB_LOGIN_CONFIG'), 'github-trigger': _validate_github('GITHUB_TRIGGER_CONFIG'), diff --git a/util/config/validators/registrystorage.py b/util/config/validators/registrystorage.py new file mode 100644 index 000000000..ca2f79ed5 --- /dev/null +++ b/util/config/validators/registrystorage.py @@ -0,0 +1,42 @@ +from app import app +from storage import get_storage_driver +from util.config.validators import BaseValidator, ConfigValidationException + +class StorageValidator(BaseValidator): + name = "registry-storage" + + @classmethod + def validate(cls, config, user, user_password): + """ Validates registry storage. """ + replication_enabled = config.get('FEATURE_STORAGE_REPLICATION', False) + + providers = _get_storage_providers(config).items() + if not providers: + raise ConfigValidationException('Storage configuration required') + + for name, (storage_type, driver) in providers: + try: + if replication_enabled and storage_type == 'LocalStorage': + raise ConfigValidationException('Locally mounted directory not supported ' + + 'with storage replication') + + # Run validation on the driver. + driver.validate(app.config['HTTPCLIENT']) + + # Run setup on the driver if the read/write succeeded. + driver.setup() + except Exception as ex: + raise ConfigValidationException('Invalid storage configuration: %s: %s' % (name, str(ex))) + + +def _get_storage_providers(config): + storage_config = config.get('DISTRIBUTED_STORAGE_CONFIG', {}) + drivers = {} + + try: + for name, parameters in storage_config.items(): + drivers[name] = (parameters[0], get_storage_driver(None, None, None, parameters)) + except TypeError: + raise ConfigValidationException('Missing required parameter(s) for storage %s' % name) + + return drivers diff --git a/util/config/validators/test/test_registrystorage.py b/util/config/validators/test/test_registrystorage.py new file mode 100644 index 000000000..0d5406500 --- /dev/null +++ b/util/config/validators/test/test_registrystorage.py @@ -0,0 +1,18 @@ +import pytest + +from util.config.validators import ConfigValidationException +from util.config.validators.registrystorage import StorageValidator + +@pytest.mark.parametrize('unvalidated_config, expected', [ + ({}, ConfigValidationException), + ({'DISTRIBUTED_STORAGE_CONFIG': {}}, ConfigValidationException), + ({'DISTRIBUTED_STORAGE_CONFIG': {'local': None}}, ConfigValidationException), + ({'DISTRIBUTED_STORAGE_CONFIG': {'local': ['FakeStorage', {}]}}, None), +]) +def test_validate_storage(unvalidated_config, expected): + validator = StorageValidator() + if expected is not None: + with pytest.raises(expected): + validator.validate(unvalidated_config, None, None) + else: + validator.validate(unvalidated_config, None, None)