Add superuser config section for updating license
This commit is contained in:
parent
5fee4d6d19
commit
ee96693252
11 changed files with 370 additions and 34 deletions
|
@ -102,22 +102,22 @@ class BaseProvider(object):
|
|||
|
||||
def _get_license_file(self):
|
||||
""" Returns the contents of the license file. """
|
||||
if not self.has_license_file():
|
||||
msg = 'Could not find license file. Please make sure it is in your config volume.'
|
||||
raise LicenseError(msg)
|
||||
|
||||
try:
|
||||
return self.get_volume_file(LICENSE_FILENAME)
|
||||
except IOError:
|
||||
msg = 'Could not open license file. Please make sure it is in your config volume.'
|
||||
raise LicenseError(msg)
|
||||
|
||||
def validate_license(self, config):
|
||||
""" Validates that the configuration matches the license file (if any). """
|
||||
if not config.get('SETUP_COMPLETE', False):
|
||||
raise SetupIncompleteException()
|
||||
|
||||
def get_license(self):
|
||||
""" Returns the decoded license, if any. """
|
||||
with self._get_license_file() as f:
|
||||
license_file_contents = f.read()
|
||||
|
||||
self.license = decode_license(license_file_contents)
|
||||
self.license.validate(config)
|
||||
return decode_license(license_file_contents)
|
||||
|
||||
def save_license(self, license_file_contents):
|
||||
""" Saves the given contents as the license file. """
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import json
|
||||
from StringIO import StringIO
|
||||
import io
|
||||
|
||||
from util.config.provider.baseprovider import BaseProvider
|
||||
|
||||
|
@ -53,7 +53,7 @@ class TestConfigProvider(BaseProvider):
|
|||
if filename in REAL_FILES:
|
||||
return open(filename, mode=mode)
|
||||
|
||||
return StringIO(self.files[filename])
|
||||
return io.BytesIO(self.files[filename])
|
||||
|
||||
def requires_restart(self, app_config):
|
||||
return False
|
||||
|
|
|
@ -43,11 +43,26 @@ class LicenseValidationError(LicenseError):
|
|||
def _get_date(decoded, field):
|
||||
""" Retrieves the encoded date found at the given field under the decoded license block. """
|
||||
date_str = decoded.get(field)
|
||||
if date_str:
|
||||
return parser.parse(date_str).replace(tzinfo=None)
|
||||
return parser.parse(date_str).replace(tzinfo=None) if date_str else None
|
||||
|
||||
return datetime.now() - timedelta(days=2)
|
||||
|
||||
class LicenseExpirationDate(object):
|
||||
def __init__(self, title, expiration_date, grace_period=None):
|
||||
self.title = title
|
||||
self.expiration_date = expiration_date
|
||||
self.grace_period = grace_period or timedelta(seconds=0)
|
||||
|
||||
def check_expired(self, cutoff_date=None):
|
||||
return self.expiration_and_grace <= (cutoff_date or datetime.now())
|
||||
|
||||
@property
|
||||
def expiration_and_grace(self):
|
||||
return self.expiration_date + self.grace_period
|
||||
|
||||
def __str__(self):
|
||||
return 'License expiration "%s" date %s with grace %s: %s' % (self.title, self.expiration_date,
|
||||
self.grace_period,
|
||||
self.check_expired())
|
||||
|
||||
class License(object):
|
||||
""" License represents a fully decoded and validated (but potentially expired) license. """
|
||||
|
@ -65,7 +80,8 @@ class License(object):
|
|||
|
||||
@property
|
||||
def is_expired(self):
|
||||
return self._get_expired(datetime.now())
|
||||
cutoff_date = datetime.now()
|
||||
return bool([dt for dt in self._get_expiration_dates() if dt.check_expired(cutoff_date)])
|
||||
|
||||
def validate(self, config):
|
||||
""" Validates the license and all its entitlements against the given config. """
|
||||
|
@ -81,47 +97,54 @@ class License(object):
|
|||
max_regions)
|
||||
raise LicenseValidationError(msg)
|
||||
|
||||
def _get_expired(self, compare_date):
|
||||
def _get_expiration_dates(self):
|
||||
# Check if the license overall has expired.
|
||||
expiration_date = _get_date(self.decoded, 'expirationDate')
|
||||
if expiration_date <= compare_date:
|
||||
logger.debug('License expired on %s', expiration_date)
|
||||
return True
|
||||
if expiration_date is None:
|
||||
yield LicenseExpirationDate('No valid Tectonic Account License', datetime.min)
|
||||
return
|
||||
|
||||
yield LicenseExpirationDate('Tectonic Account License', expiration_date)
|
||||
|
||||
# Check for any QE subscriptions.
|
||||
sub = self.subscription
|
||||
if sub is None:
|
||||
return True
|
||||
yield LicenseExpirationDate('No Quay Enterprise Subscription', datetime.min)
|
||||
return
|
||||
|
||||
# Check for a trial-only license.
|
||||
if sub.get('trialOnly', False):
|
||||
trial_end_date = _get_date(sub, 'trialEnd')
|
||||
logger.debug('Trial-only license expires on %s', trial_end_date)
|
||||
return trial_end_date <= (compare_date - TRIAL_GRACE_PERIOD)
|
||||
if trial_end_date is None:
|
||||
yield LicenseExpirationDate('Invalid trial subscription', datetime.min)
|
||||
else:
|
||||
yield LicenseExpirationDate('Trial subscription', trial_end_date, TRIAL_GRACE_PERIOD)
|
||||
|
||||
return
|
||||
|
||||
# Check for a normal license that is in trial.
|
||||
service_end_date = _get_date(sub, 'serviceEnd')
|
||||
if service_end_date is None:
|
||||
yield LicenseExpirationDate('No valid Quay Enterprise Subscription', datetime.min)
|
||||
return
|
||||
|
||||
if sub.get('inTrial', False):
|
||||
# If the subscription is in a trial, but not a trial only
|
||||
# subscription, give 7 days after trial end to update license
|
||||
# to one which has been paid (they've put in a credit card and it
|
||||
# might auto convert, so we could assume it will auto-renew)
|
||||
logger.debug('In-trial license expires on %s', service_end_date)
|
||||
return service_end_date <= (compare_date - TRIAL_GRACE_PERIOD)
|
||||
yield LicenseExpirationDate('In-trial subscription', service_end_date, TRIAL_GRACE_PERIOD)
|
||||
|
||||
# Otherwise, check the service expiration.
|
||||
duration_period = sub.get('durationPeriod', 'months')
|
||||
|
||||
# If the subscription is monthly, give 3 months grace period
|
||||
if duration_period == "months":
|
||||
logger.debug('Monthly license expires on %s', service_end_date)
|
||||
return service_end_date <= (compare_date - MONTHLY_GRACE_PERIOD)
|
||||
yield LicenseExpirationDate('Monthly subscription', service_end_date, MONTHLY_GRACE_PERIOD)
|
||||
|
||||
if duration_period == "years":
|
||||
logger.debug('Yearly license expires on %s', service_end_date)
|
||||
return service_end_date <= (compare_date - YEARLY_GRACE_PERIOD)
|
||||
yield LicenseExpirationDate('Yearly subscription', service_end_date, YEARLY_GRACE_PERIOD)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
_PROD_LICENSE_PUBLIC_KEY_DATA = """
|
||||
|
|
Reference in a new issue