django32: do not instanciate ServiceBase abstract model (#67760)

This commit is contained in:
Agate 2022-07-28 10:10:49 +02:00 committed by Benjamin Dauvergne
parent dbf76af91e
commit 4a1cfa5a16
7 changed files with 55 additions and 48 deletions

View File

@ -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():

View File

@ -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}
)

View File

@ -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)

View File

@ -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()

View File

@ -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

View File

@ -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(

View File

@ -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/'