Merge pull request #2948 from coreos-inc/joseph.schorr/QS-97/license-validator
Add license validation to the config validation check
This commit is contained in:
		
						commit
						db3e0307b7
					
				
					 5 changed files with 75 additions and 0 deletions
				
			
		|  | @ -19,6 +19,8 @@ angular.module("core-config-setup", ['angularFileUpload']) | |||
|         $scope.GITHOST_REGEX = '^https?://([a-zA-Z0-9]+\.?\/?)+$'; | ||||
| 
 | ||||
|         $scope.SERVICES = [ | ||||
|           {'id': 'license', 'title': 'License'}, | ||||
| 
 | ||||
|           {'id': 'redis', 'title': 'Redis'}, | ||||
| 
 | ||||
|           {'id': 'registry-storage', 'title': 'Registry Storage'}, | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ import logging | |||
| from auth.auth_context import get_authenticated_user | ||||
| from data.users import LDAP_CERT_FILENAME | ||||
| 
 | ||||
| from util.config.validators.validate_license import LicenseValidator | ||||
| from util.config.validators.validate_database import DatabaseValidator | ||||
| from util.config.validators.validate_redis import RedisValidator | ||||
| from util.config.validators.validate_storage import StorageValidator | ||||
|  | @ -40,6 +41,7 @@ CONFIG_FILENAMES = (SSL_FILENAMES + DB_SSL_FILENAMES + JWT_FILENAMES + ACI_CERT_ | |||
| EXTRA_CA_DIRECTORY = 'extra_ca_certs' | ||||
| 
 | ||||
| VALIDATORS = { | ||||
|   LicenseValidator.name: LicenseValidator.validate, | ||||
|   DatabaseValidator.name: DatabaseValidator.validate, | ||||
|   RedisValidator.name: RedisValidator.validate, | ||||
|   StorageValidator.name: StorageValidator.validate, | ||||
|  |  | |||
							
								
								
									
										48
									
								
								util/config/validators/test/test_validate_license.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								util/config/validators/test/test_validate_license.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,48 @@ | |||
| import pytest | ||||
| 
 | ||||
| from mock import patch | ||||
| 
 | ||||
| from util.config.validators import ConfigValidationException | ||||
| from util.config.validators.validate_license import LicenseValidator | ||||
| from util.morecollections import AttrDict | ||||
| from util.license import License, QUAY_DEPLOYMENTS_ENTITLEMENT, QUAY_ENTITLEMENT | ||||
| 
 | ||||
| from test.fixtures import * | ||||
| 
 | ||||
| @pytest.mark.parametrize('deployments, allowed_deployments', [ | ||||
|   (1, 1), | ||||
|   (3, 3), | ||||
|   (3, 2), | ||||
|   (3, 1), | ||||
| ]) | ||||
| def test_too_many_storage_engines(deployments, allowed_deployments, app): | ||||
|   def get_license(): | ||||
|     decoded = { | ||||
|       'expirationDate': '2157-12-1', | ||||
|       'subscriptions': { | ||||
|         'someSubscription': { | ||||
|           'serviceEnd': '2157-12-1', | ||||
|           'durationPeriod': 'yearly', | ||||
|           'entitlements': { | ||||
|             QUAY_ENTITLEMENT: 1, | ||||
|             QUAY_DEPLOYMENTS_ENTITLEMENT: allowed_deployments, | ||||
|           }, | ||||
|         }, | ||||
|       }, | ||||
|     } | ||||
|     return License(decoded) | ||||
| 
 | ||||
|   storage_configs = [(str(i), {}) for i in range(0, deployments)] | ||||
| 
 | ||||
|   with patch('app.config_provider.get_license', get_license): | ||||
|     validator = LicenseValidator() | ||||
| 
 | ||||
|     if allowed_deployments < deployments: | ||||
|       with pytest.raises(ConfigValidationException): | ||||
|         validator.validate({ | ||||
|           'DISTRIBUTED_STORAGE_CONFIG': storage_configs, | ||||
|         }, None, None) | ||||
|     else: | ||||
|       validator.validate({ | ||||
|         'DISTRIBUTED_STORAGE_CONFIG': storage_configs, | ||||
|       }, None, None) | ||||
							
								
								
									
										19
									
								
								util/config/validators/validate_license.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								util/config/validators/validate_license.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | |||
| from app import config_provider | ||||
| from util.config.validators import BaseValidator, ConfigValidationException | ||||
| from util.license import LicenseDecodeError, EntitlementStatus | ||||
| 
 | ||||
| class LicenseValidator(BaseValidator): | ||||
|   name = "license" | ||||
| 
 | ||||
|   @classmethod | ||||
|   def validate(cls, config, user, user_password): | ||||
|     try: | ||||
|       decoded_license = config_provider.get_license() | ||||
|     except LicenseDecodeError as le: | ||||
|       raise ConfigValidationException('Could not decode license: %s' % le.message) | ||||
| 
 | ||||
|     results = decoded_license.validate(config) | ||||
|     all_met = all(result.is_met() for result in results) | ||||
|     if not all_met: | ||||
|       reason = [result.description() for result in results if not result.is_met()] | ||||
|       raise ConfigValidationException('License does not match configuration: %s' % reason) | ||||
|  | @ -204,6 +204,10 @@ class EntitlementValidationResult(object): | |||
|       entitlement=repr(self.entitlement), | ||||
|     )) | ||||
| 
 | ||||
|   def description(self): | ||||
|     msg = '%s requires %s: has status %s' | ||||
|     return msg % (self.requirement.name, self.requirement.count, self.get_status()) | ||||
| 
 | ||||
|   def as_dict(self, for_private=False): | ||||
|     def req_view(): | ||||
|       return { | ||||
|  |  | |||
		Reference in a new issue