Merge branch 'license_module_switch' into devel

* license_module_switch:
  Hide eula if stub license is used
  Fix up some issues on feature validation for licenses
  Remove any references to internal licensing utilities
  Switch out existing obfuscated license with external module
This commit is contained in:
Matthew Jones
2017-07-13 11:08:47 -04:00
12 changed files with 64 additions and 253 deletions
-29
View File
@@ -29,7 +29,6 @@ from django.utils.encoding import force_text
# AWX
from awx.main.models import * # noqa
from awx.main.task_engine import TaskEnhancer
from awx.main.utils import get_ansible_version
from awx.sso.backends import LDAPSettings
from awx.main.tests.URI import URI # noqa
@@ -178,34 +177,6 @@ class BaseTestMixin(MockCommonlySlowTestMixin):
rnd_str = '____' + str(random.randint(1, 9999999))
return __name__ + '-generated-' + string + rnd_str
def create_test_license_file(self, instance_count=10000, license_date=int(time.time() + 3600), features={}):
settings.LICENSE = TaskEnhancer(
company_name='AWX',
contact_name='AWX Admin',
contact_email='awx@example.com',
license_date=license_date,
instance_count=instance_count,
license_type='enterprise',
features=features,
).enhance()
def create_basic_license_file(self, instance_count=100, license_date=int(time.time() + 3600)):
settings.LICENSE = TaskEnhancer(
company_name='AWX',
contact_name='AWX Admin',
contact_email='awx@example.com',
license_date=license_date,
instance_count=instance_count,
license_type='basic',
).enhance()
def create_expired_license_file(self, instance_count=1000, grace_period=False):
license_date = time.time() - 1
if not grace_period:
license_date -= 2592000
self.create_test_license_file(instance_count, license_date)
os.environ['SKIP_LICENSE_FIXUP_FOR_TEST'] = '1'
def assertElapsedLessThan(self, seconds):
elapsed = time.time() - self._start_time
self.assertTrue(elapsed < seconds, 'elapsed time of %0.3fs is greater than %0.3fs' % (elapsed, seconds))
-14
View File
@@ -1,6 +1,5 @@
# Python
import time
import pytest
import mock
from contextlib import contextmanager
@@ -97,16 +96,3 @@ def get_ssh_version(mocker):
@pytest.fixture
def job_template_with_survey_passwords_unit(job_template_with_survey_passwords_factory):
return job_template_with_survey_passwords_factory(persisted=False)
@pytest.fixture
def enterprise_license():
from awx.main.task_engine import TaskEnhancer
return TaskEnhancer(
company_name='AWX',
contact_name='AWX Admin',
contact_email='awx@example.com',
license_date=int(time.time() + 3600),
instance_count=10000,
license_type='enterprise',
).enhance()
+4 -35
View File
@@ -29,26 +29,6 @@ def mock_no_license_file(mocker):
return None
@pytest.mark.django_db
def test_license_cannot_be_removed_via_system_settings(mock_no_license_file, get, put, patch, delete, admin, enterprise_license):
url = reverse('api:setting_singleton_detail', kwargs={'category_slug': 'system'})
response = get(url, user=admin, expect=200)
assert not response.data['LICENSE']
Setting.objects.create(key='TOWER_URL_BASE', value='https://towerhost')
Setting.objects.create(key='LICENSE', value=enterprise_license)
response = get(url, user=admin, expect=200)
assert response.data['LICENSE']
put(url, user=admin, data=response.data, expect=200)
response = get(url, user=admin, expect=200)
assert response.data['LICENSE']
patch(url, user=admin, data={}, expect=200)
response = get(url, user=admin, expect=200)
assert response.data['LICENSE']
delete(url, user=admin, expect=204)
response = get(url, user=admin, expect=200)
assert response.data['LICENSE']
@pytest.mark.django_db
def test_url_base_defaults_to_request(options, admin):
# If TOWER_URL_BASE is not set, default to the Tower request hostname
@@ -98,10 +78,8 @@ def test_awx_task_env_validity(get, patch, admin, value, expected):
@pytest.mark.django_db
def test_ldap_settings(get, put, patch, delete, admin, enterprise_license):
def test_ldap_settings(get, put, patch, delete, admin):
url = reverse('api:setting_singleton_detail', kwargs={'category_slug': 'ldap'})
get(url, user=admin, expect=404)
Setting.objects.create(key='LICENSE', value=enterprise_license)
get(url, user=admin, expect=200)
# The PUT below will fail at the moment because AUTH_LDAP_GROUP_TYPE
# defaults to None but cannot be set to None.
@@ -124,11 +102,8 @@ def test_ldap_settings(get, put, patch, delete, admin, enterprise_license):
'AUTH_LDAP_DENY_GROUP',
])
@pytest.mark.django_db
def test_empty_ldap_dn(get, put, patch, delete, admin, enterprise_license,
setting):
def test_empty_ldap_dn(get, put, patch, delete, admin, setting):
url = reverse('api:setting_singleton_detail', kwargs={'category_slug': 'ldap'})
Setting.objects.create(key='LICENSE', value=enterprise_license)
patch(url, user=admin, data={setting: ''}, expect=200)
resp = get(url, user=admin, expect=200)
assert resp.data[setting] is None
@@ -139,10 +114,8 @@ def test_empty_ldap_dn(get, put, patch, delete, admin, enterprise_license,
@pytest.mark.django_db
def test_radius_settings(get, put, patch, delete, admin, enterprise_license, settings):
def test_radius_settings(get, put, patch, delete, admin, settings):
url = reverse('api:setting_singleton_detail', kwargs={'category_slug': 'radius'})
get(url, user=admin, expect=404)
Setting.objects.create(key='LICENSE', value=enterprise_license)
response = get(url, user=admin, expect=200)
put(url, user=admin, data=response.data, expect=200)
# Set secret via the API.
@@ -173,13 +146,9 @@ def test_radius_settings(get, put, patch, delete, admin, enterprise_license, set
@pytest.mark.django_db
def test_ui_settings(get, put, patch, delete, admin, enterprise_license):
def test_ui_settings(get, put, patch, delete, admin):
url = reverse('api:setting_singleton_detail', kwargs={'category_slug': 'ui'})
response = get(url, user=admin, expect=200)
assert 'CUSTOM_LOGO' not in response.data
assert 'CUSTOM_LOGIN_INFO' not in response.data
Setting.objects.create(key='LICENSE', value=enterprise_license)
response = get(url, user=admin, expect=200)
assert not response.data['CUSTOM_LOGO']
assert not response.data['CUSTOM_LOGIN_INFO']
put(url, user=admin, data=response.data, expect=200)
+7 -100
View File
@@ -1,106 +1,13 @@
# Copyright (c) 2015 Ansible, Inc.
# All Rights Reserved.
import time
import pytest
from datetime import datetime
from awx.main.models import Host
from awx.main.task_engine import TaskEnhancer
from awx.main.utils.common import StubLicense
@pytest.mark.django_db
def test_license_writer(inventory, admin):
task_enhancer = TaskEnhancer(
company_name='acmecorp',
contact_name='Michael DeHaan',
contact_email='michael@ansibleworks.com',
license_date=25000, # seconds since epoch
instance_count=500)
def test_stub_license():
license_actual = StubLicense().validate()
assert license_actual['license_key'] == 'OPEN'
assert license_actual['valid_key']
assert license_actual['compliant']
assert license_actual['license_type'] == 'open'
data = task_enhancer.enhance()
Host.objects.bulk_create(
[
Host(
name='host.%d' % n,
inventory=inventory,
created_by=admin,
modified=datetime.now(),
created=datetime.now())
for n in range(12)
]
)
assert data['instance_count'] == 500
assert data['contact_name'] == 'Michael DeHaan'
assert data['contact_email'] == 'michael@ansibleworks.com'
assert data['license_date'] == 25000
assert data['license_key'] == "11bae31f31c6a6cdcb483a278cdbe98bd8ac5761acd7163a50090b0f098b3a13"
vdata = task_enhancer.validate_enhancements()
assert vdata['available_instances'] == 500
assert vdata['current_instances'] == 12
assert vdata['free_instances'] == 488
assert vdata['date_warning'] is True
assert vdata['date_expired'] is True
assert vdata['license_date'] == 25000
assert vdata['time_remaining'] < 0
assert vdata['valid_key'] is True
assert vdata['compliant'] is False
assert vdata['subscription_name']
@pytest.mark.django_db
def test_expired_licenses():
task_enhancer = TaskEnhancer(
company_name='Tower',
contact_name='Tower Admin',
contact_email='tower@ansible.com',
license_date=int(time.time() - 3600),
instance_count=100,
trial=True)
task_enhancer.enhance()
vdata = task_enhancer.validate_enhancements()
assert vdata['compliant'] is False
assert vdata['grace_period_remaining'] < 0
task_enhancer = TaskEnhancer(
company_name='Tower',
contact_name='Tower Admin',
contact_email='tower@ansible.com',
license_date=int(time.time() - 2592001),
instance_count=100,
trial=False)
task_enhancer.enhance()
vdata = task_enhancer.validate_enhancements()
assert vdata['compliant'] is False
assert vdata['grace_period_remaining'] < 0
task_enhancer = TaskEnhancer(
company_name='Tower',
contact_name='Tower Admin',
contact_email='tower@ansible.com',
license_date=int(time.time() - 3600),
instance_count=100,
trial=False)
task_enhancer.enhance()
vdata = task_enhancer.validate_enhancements()
assert vdata['compliant'] is False
assert vdata['grace_period_remaining'] > 0
@pytest.mark.django_db
def test_cloudforms_license(mocker):
with mocker.patch('awx.main.task_engine.TaskEnhancer._check_cloudforms_subscription', return_value=True):
task_enhancer = TaskEnhancer()
vdata = task_enhancer.validate_enhancements()
assert vdata['compliant'] is True
assert vdata['subscription_name'] == "Red Hat CloudForms License"
assert vdata['available_instances'] == 9999999
assert vdata['license_type'] == 'enterprise'
assert vdata['features']['ha'] is True
-36
View File
@@ -1,11 +1,9 @@
import pytest
import mock
import os
from django.contrib.auth.models import User
from django.forms.models import model_to_dict
from rest_framework.exceptions import ParseError
from rest_framework.exceptions import PermissionDenied
from awx.main.access import (
BaseAccess,
@@ -257,40 +255,6 @@ class TestWorkflowAccessMethods:
assert access.can_add({'organization': 1})
class TestCheckLicense:
@pytest.fixture
def validate_enhancements_mocker(self, mocker):
os.environ['SKIP_LICENSE_FIXUP_FOR_TEST'] = '1'
def fn(available_instances=1, free_instances=0, host_exists=False):
class MockFilter:
def exists(self):
return host_exists
mocker.patch('awx.main.tasks.TaskEnhancer.validate_enhancements', return_value={'free_instances': free_instances, 'available_instances': available_instances, 'date_warning': True})
mock_filter = MockFilter()
mocker.patch('awx.main.models.Host.objects.filter', return_value=mock_filter)
return fn
def test_check_license_add_host_duplicate(self, validate_enhancements_mocker, user_unit):
validate_enhancements_mocker(available_instances=1, free_instances=0, host_exists=True)
BaseAccess(None).check_license(add_host_name='blah', check_expiration=False)
def test_check_license_add_host_new_exceed_licence(self, validate_enhancements_mocker, user_unit, mocker):
validate_enhancements_mocker(available_instances=1, free_instances=0, host_exists=False)
exception = None
try:
BaseAccess(None).check_license(add_host_name='blah', check_expiration=False)
except PermissionDenied as e:
exception = e
assert "License count of 1 instances has been reached." == str(exception)
def test_user_capabilities_method():
"""Unit test to verify that the user_capabilities method will defer
+1 -22
View File
@@ -29,10 +29,10 @@ from awx.main.models import (
)
from awx.main import tasks
from awx.main.task_engine import TaskEnhancer
from awx.main.utils import encrypt_field
@contextmanager
def apply_patches(_patches):
[p.start() for p in _patches]
@@ -78,27 +78,6 @@ def test_send_notifications_list(mocker):
assert mock_job.notifications.add.called_with(*mock_notifications)
@pytest.mark.parametrize("current_instances,call_count", [(91, 2), (89,1)])
def test_run_admin_checks_usage(mocker, current_instances, call_count):
patches = list()
patches.append(mocker.patch('awx.main.tasks.User'))
mock_te = mocker.Mock(spec=TaskEnhancer)
mock_te.validate_enhancements.return_value = {'instance_count': 100, 'current_instances': current_instances, 'date_warning': True}
patches.append(mocker.patch('awx.main.tasks.TaskEnhancer', return_value=mock_te))
mock_sm = mocker.Mock()
patches.append(mocker.patch('awx.main.tasks.send_mail', wraps=mock_sm))
with apply_patches(patches):
tasks.run_administrative_checks()
assert mock_sm.called
if call_count == 2:
assert '90%' in mock_sm.call_args_list[0][0][0]
else:
assert 'expire' in mock_sm.call_args_list[0][0][0]
@pytest.mark.parametrize("key,value", [
('REST_API_TOKEN', 'SECRET'),
('SECRET_KEY', 'SECRET'),