diff --git a/hobo/environment/models.py b/hobo/environment/models.py index 31bc5de..456c211 100644 --- a/hobo/environment/models.py +++ b/hobo/environment/models.py @@ -97,6 +97,25 @@ class Variable(models.Model): self._parse_value_as_json() +def is_resolvable(url): + try: + netloc = urllib.parse.urlparse(url).netloc + if netloc and socket.gethostbyname(netloc): + return True + except socket.gaierror: + return False + + +def has_valid_certificate(url): + try: + requests.get(url, timeout=5, verify=True, allow_redirects=False) + return True + except requests.exceptions.SSLError: + return False + except requests.exceptions.ConnectionError: + return False + + class ServiceBase(models.Model): class Meta: abstract = True @@ -228,23 +247,10 @@ class ServiceBase(models.Model): return self.get_base_url_path() + '__provision__/' def is_resolvable(self): - try: - netloc = urllib.parse.urlparse(self.base_url).netloc - if netloc and socket.gethostbyname(netloc): - return True - except socket.gaierror: - return False + return is_resolvable(self.base_url) def has_valid_certificate(self): - if not self.is_resolvable(): - return False - try: - requests.get(self.base_url, timeout=5, verify=True, allow_redirects=False) - return True - except requests.exceptions.SSLError: - return False - except requests.exceptions.ConnectionError: - return False + return has_valid_certificate(self.base_url) def is_running(self): if not self.is_resolvable(): diff --git a/hobo/environment/validators.py b/hobo/environment/validators.py index 047e186..fa20c8c 100644 --- a/hobo/environment/validators.py +++ b/hobo/environment/validators.py @@ -3,18 +3,17 @@ import urllib.parse from django.core.exceptions import ValidationError from django.utils.translation import gettext_lazy as _ -from hobo.environment.models import ServiceBase +from hobo.environment import models def validate_service_url(url): - service = ServiceBase(title='dummy', base_url=url) - if not service.is_resolvable(): + if not models.is_resolvable(url): raise ValidationError( _('Error: %(netloc)s is not resolvable in URL %(url)s'), code='not-resolvable', params={'netloc': urllib.parse.urlsplit(url).netloc, 'url': url}, ) - if not service.has_valid_certificate(): + if not models.has_valid_certificate(url): raise ValidationError( _('Error: no valid certificate for %(url)s'), code='invalid-certificate', params={'url': url} ) diff --git a/tests/test_cook.py b/tests/test_cook.py index cfbad8f..f246b23 100644 --- a/tests/test_cook.py +++ b/tests/test_cook.py @@ -9,6 +9,7 @@ from django.contrib.contenttypes.models import ContentType from django.core.management import call_command from django.core.management.base import CommandError +from hobo.environment import models as environment_models from hobo.environment.management.commands.cook import Command from hobo.environment.models import ( Authentic, @@ -57,8 +58,8 @@ def test_check_action(command, monkeypatch): command.server_action = 'mock a server_action handler (ex: hobo-create)' action, action_args = 'server-action', {'url': 'https://test.org/'} - monkeypatch.setattr(ServiceBase, 'is_resolvable', lambda x: True) - monkeypatch.setattr(ServiceBase, 'has_valid_certificate', lambda x: True) + monkeypatch.setattr(environment_models, 'is_resolvable', lambda x: True) + monkeypatch.setattr(environment_models, 'has_valid_certificate', lambda x: True) command.check_action(action, action_args) assert True @@ -68,8 +69,8 @@ def test_check_action_unknown_action(command, monkeypatch): command.server_action = 'mock a server_action handler (ex: hobo-create)' action, action_args = 'not-a-server-action', {'url': 'https://test.org/'} - monkeypatch.setattr(ServiceBase, 'is_resolvable', lambda x: True) - monkeypatch.setattr(ServiceBase, 'has_valid_certificate', lambda x: True) + monkeypatch.setattr(environment_models, 'is_resolvable', lambda x: True) + monkeypatch.setattr(environment_models, 'has_valid_certificate', lambda x: True) with pytest.raises(CommandError) as e_info: command.check_action(action, action_args) assert 'Unknown action not-a-server-action' in str(e_info.value) @@ -80,8 +81,8 @@ def test_check_action_unresolvable(command, monkeypatch): command.server_action = 'mock a server_action handler (ex: hobo-create)' action, action_args = 'server-action', {'url': 'https://test.org/'} - monkeypatch.setattr(ServiceBase, 'is_resolvable', lambda x: False) - monkeypatch.setattr(ServiceBase, 'has_valid_certificate', lambda x: True) + monkeypatch.setattr(environment_models, 'is_resolvable', lambda x: False) + monkeypatch.setattr(environment_models, 'has_valid_certificate', lambda x: True) with pytest.raises(CommandError) as e_info: command.check_action(action, action_args) assert 'test.org is not resolvable in URL https://test.org/' in str(e_info.value) @@ -92,8 +93,8 @@ def test_check_action_invalid_certificat(command, monkeypatch): command.server_action = 'mock a server_action handler (ex: hobo-create)' action, action_args = 'server-action', {'url': 'https://test.org/'} - monkeypatch.setattr(ServiceBase, 'is_resolvable', lambda x: True) - monkeypatch.setattr(ServiceBase, 'has_valid_certificate', lambda x: False) + monkeypatch.setattr(environment_models, 'is_resolvable', lambda x: True) + monkeypatch.setattr(environment_models, 'has_valid_certificate', lambda x: False) with pytest.raises(CommandError) as e_info: command.check_action(action, action_args) assert 'no valid certificate for https://test.org/' in str(e_info.value) diff --git a/tests/test_environment.py b/tests/test_environment.py index 07390c9..8c5949f 100644 --- a/tests/test_environment.py +++ b/tests/test_environment.py @@ -8,6 +8,7 @@ from django.utils import timezone from test_manager import login from webtest import Upload +from hobo.environment import models as environment_models from hobo.environment.models import AVAILABLE_SERVICES, Combo, Passerelle, ServiceBase, Variable from hobo.environment.utils import get_installed_services_dict from hobo.profile.models import AttributeDefinition @@ -143,13 +144,13 @@ def test_service_creation_url_validation(app, admin_user, monkeypatch): response = form.submit() assert 'not resolvable' in response - monkeypatch.setattr(ServiceBase, 'is_resolvable', lambda x: True) + monkeypatch.setattr(environment_models, 'is_resolvable', lambda x: True) form = response.form response = form.submit() assert 'no valid certificate' in response assert not Combo.objects.exists() - monkeypatch.setattr(ServiceBase, 'has_valid_certificate', lambda x: True) + monkeypatch.setattr(environment_models, 'has_valid_certificate', lambda x: True) form = response.form response = form.submit() assert Combo.objects.exists() diff --git a/tests_schemas/test_cook.py b/tests_schemas/test_cook.py index 500e42a..7235377 100644 --- a/tests_schemas/test_cook.py +++ b/tests_schemas/test_cook.py @@ -5,18 +5,18 @@ from django.core.management import call_command, load_command_class from django.core.management.base import CommandError from hobo.deploy.utils import get_hobo_json -from hobo.environment.models import ServiceBase +from hobo.environment import models as environment_models def test_cook(db, fake_notify, monkeypatch): - monkeypatch.setattr(ServiceBase, 'is_resolvable', lambda x: True) - monkeypatch.setattr(ServiceBase, 'has_valid_certificate', lambda x: True) + monkeypatch.setattr(environment_models, 'is_resolvable', lambda x: True) + monkeypatch.setattr(environment_models, 'has_valid_certificate', lambda x: True) call_command('cook', 'tests_schemas/recipe.json') assert len(fake_notify) == 3 def test_cook_unresolvable(db, fake_notify, monkeypatch): - monkeypatch.setattr(ServiceBase, 'is_resolvable', lambda x: False) + monkeypatch.setattr(environment_models, 'is_resolvable', lambda x: False) with pytest.raises(CommandError) as e_info: call_command('cook', 'tests_schemas/recipe.json') assert 'is not resolvable' in str(e_info.value) @@ -26,8 +26,8 @@ def test_cook_example(db, fake_notify, monkeypatch, fake_themes): """hobo/cook (before rabbitmq) scenario having templates. the resulting JSON may be helpfull to manually invoque hobo-deploy (after rabbitmq) """ - monkeypatch.setattr(ServiceBase, 'is_resolvable', lambda x: True) - monkeypatch.setattr(ServiceBase, 'has_valid_certificate', lambda x: True) + monkeypatch.setattr(environment_models, 'is_resolvable', lambda x: True) + monkeypatch.setattr(environment_models, 'has_valid_certificate', lambda x: True) call_command('cook', 'tests_schemas/example_recipe.json') # notify_agents was call diff --git a/tests_schemas/test_rename_hobo_service.py b/tests_schemas/test_rename_hobo_service.py index 4e47b6e..6da1e64 100644 --- a/tests_schemas/test_rename_hobo_service.py +++ b/tests_schemas/test_rename_hobo_service.py @@ -5,15 +5,15 @@ from django.core.management import call_command from django.core.management.base import CommandError from tenant_schemas.utils import tenant_context -from hobo.environment.models import Passerelle, ServiceBase +from hobo.environment import models as environment_models from hobo.environment.utils import get_installed_services, get_or_create_local_hobo from hobo.multitenant.middleware import TenantMiddleware, TenantNotFound @pytest.fixture() def hobo_tenant(db, fake_notify, monkeypatch, fake_themes): - monkeypatch.setattr(ServiceBase, 'is_resolvable', lambda x: True) - monkeypatch.setattr(ServiceBase, 'has_valid_certificate', lambda x: True) + monkeypatch.setattr(environment_models, 'is_resolvable', lambda x: True) + monkeypatch.setattr(environment_models, 'has_valid_certificate', lambda x: True) yield call_command('cook', 'tests_schemas/example_recipe.json') call_command('delete_tenant', 'hobo-instance-name.dev.signalpublik.com') @@ -34,8 +34,8 @@ def test_unknown_service(hobo_tenant): def test_rename_hobo_service_succes(db, fake_notify, monkeypatch, fake_themes): - monkeypatch.setattr(ServiceBase, 'is_resolvable', lambda x: True) - monkeypatch.setattr(ServiceBase, 'has_valid_certificate', lambda x: True) + monkeypatch.setattr(environment_models, 'is_resolvable', lambda x: True) + monkeypatch.setattr(environment_models, 'has_valid_certificate', lambda x: True) call_command('cook', 'tests_schemas/example_recipe.json') assert TenantMiddleware.get_tenant_by_hostname('hobo-instance-name.dev.signalpublik.com') call_command( diff --git a/tests_schemas/test_rename_service.py b/tests_schemas/test_rename_service.py index e91850d..7d2e88b 100644 --- a/tests_schemas/test_rename_service.py +++ b/tests_schemas/test_rename_service.py @@ -5,15 +5,15 @@ from django.core.management import call_command from django.core.management.base import CommandError from tenant_schemas.utils import tenant_context -from hobo.environment.models import Passerelle, ServiceBase +from hobo.environment import models as environment_models from hobo.environment.utils import get_installed_services from hobo.multitenant.middleware import TenantMiddleware @pytest.fixture() def hobo_tenant(db, fake_notify, monkeypatch, fake_themes): - monkeypatch.setattr(ServiceBase, 'is_resolvable', lambda x: True) - monkeypatch.setattr(ServiceBase, 'has_valid_certificate', lambda x: True) + monkeypatch.setattr(environment_models, 'is_resolvable', lambda x: True) + monkeypatch.setattr(environment_models, 'has_valid_certificate', lambda x: True) yield call_command('cook', 'tests_schemas/example_recipe.json') call_command('delete_tenant', 'hobo-instance-name.dev.signalpublik.com') @@ -35,7 +35,7 @@ def test_secondary_service(hobo_tenant): tenant = TenantMiddleware.get_tenant_by_hostname('hobo-instance-name.dev.signalpublik.com') with tenant_context(tenant): assert get_installed_services() - Passerelle.objects.create( + environment_models.Passerelle.objects.create( title='other passerelle', slug='other-passerelle', base_url='https://other-passerelle-instance-name.dev.signalpublik.com', @@ -56,8 +56,8 @@ def test_secondary_service(hobo_tenant): def test_rename_service_succes(hobo_tenant, monkeypatch): tenant = TenantMiddleware.get_tenant_by_hostname('hobo-instance-name.dev.signalpublik.com') with tenant_context(tenant): - assert Passerelle.objects.count() == 1 - passerelle_service = Passerelle.objects.first() + assert environment_models.Passerelle.objects.count() == 1 + passerelle_service = environment_models.Passerelle.objects.first() assert ( passerelle_service.get_base_url_path() == 'https://passerelle-instance-name.dev.signalpublik.com/' ) @@ -69,8 +69,8 @@ def test_rename_service_succes(hobo_tenant, monkeypatch): 'https://passerelle-instance-name.dev.signalpublik.com/', 'https://new-passerelle-instance-name.dev.signalpublik.com/', ) - assert Passerelle.objects.count() == 1 - passerelle_service = Passerelle.objects.first() + assert environment_models.Passerelle.objects.count() == 1 + passerelle_service = environment_models.Passerelle.objects.first() assert ( passerelle_service.get_base_url_path() == 'https://new-passerelle-instance-name.dev.signalpublik.com/'