Projet

Général

Profil

0002-django32-do-not-instanciate-ServiceBase-abstract-mod.patch

Emmanuel Cazenave, 16 janvier 2023 17:38

Télécharger (14,4 ko)

Voir les différences:

Subject: [PATCH 2/6] django32: do not instanciate ServiceBase abstract model
 (#67760)

 hobo/environment/models.py                | 36 +++++++++++++----------
 hobo/environment/validators.py            |  7 ++---
 tests/test_cook.py                        | 17 ++++++-----
 tests/test_environment.py                 |  5 ++--
 tests_schemas/test_cook.py                | 12 ++++----
 tests_schemas/test_rename_hobo_service.py | 10 +++----
 tests_schemas/test_rename_service.py      | 16 +++++-----
 7 files changed, 55 insertions(+), 48 deletions(-)
hobo/environment/models.py
97 97
        self._parse_value_as_json()
98 98

  
99 99

  
100
def is_resolvable(url):
101
    try:
102
        netloc = urllib.parse.urlparse(url).netloc
103
        if netloc and socket.gethostbyname(netloc):
104
            return True
105
    except socket.gaierror:
106
        return False
107

  
108

  
109
def has_valid_certificate(url):
110
    try:
111
        requests.get(url, timeout=5, verify=True, allow_redirects=False)
112
        return True
113
    except requests.exceptions.SSLError:
114
        return False
115
    except requests.exceptions.ConnectionError:
116
        return False
117

  
118

  
100 119
class ServiceBase(models.Model):
101 120
    class Meta:
102 121
        abstract = True
......
228 247
        return self.get_base_url_path() + '__provision__/'
229 248

  
230 249
    def is_resolvable(self):
231
        try:
232
            netloc = urllib.parse.urlparse(self.base_url).netloc
233
            if netloc and socket.gethostbyname(netloc):
234
                return True
235
        except socket.gaierror:
236
            return False
250
        return is_resolvable(self.base_url)
237 251

  
238 252
    def has_valid_certificate(self):
239
        if not self.is_resolvable():
240
            return False
241
        try:
242
            requests.get(self.base_url, timeout=5, verify=True, allow_redirects=False)
243
            return True
244
        except requests.exceptions.SSLError:
245
            return False
246
        except requests.exceptions.ConnectionError:
247
            return False
253
        return has_valid_certificate(self.base_url)
248 254

  
249 255
    def is_running(self):
250 256
        if not self.is_resolvable():
hobo/environment/validators.py
3 3
from django.core.exceptions import ValidationError
4 4
from django.utils.translation import gettext_lazy as _
5 5

  
6
from hobo.environment.models import ServiceBase
6
from hobo.environment import models
7 7

  
8 8

  
9 9
def validate_service_url(url):
10
    service = ServiceBase(title='dummy', base_url=url)
11
    if not service.is_resolvable():
10
    if not models.is_resolvable(url):
12 11
        raise ValidationError(
13 12
            _('Error: %(netloc)s is not resolvable in URL %(url)s'),
14 13
            code='not-resolvable',
15 14
            params={'netloc': urllib.parse.urlsplit(url).netloc, 'url': url},
16 15
        )
17
    if not service.has_valid_certificate():
16
    if not models.has_valid_certificate(url):
18 17
        raise ValidationError(
19 18
            _('Error: no valid certificate for %(url)s'), code='invalid-certificate', params={'url': url}
20 19
        )
tests/test_cook.py
9 9
from django.core.management import call_command
10 10
from django.core.management.base import CommandError
11 11

  
12
from hobo.environment import models as environment_models
12 13
from hobo.environment.management.commands.cook import Command
13 14
from hobo.environment.models import (
14 15
    Authentic,
......
57 58
    command.server_action = 'mock a server_action handler (ex: hobo-create)'
58 59
    action, action_args = 'server-action', {'url': 'https://test.org/'}
59 60

  
60
    monkeypatch.setattr(ServiceBase, 'is_resolvable', lambda x: True)
61
    monkeypatch.setattr(ServiceBase, 'has_valid_certificate', lambda x: True)
61
    monkeypatch.setattr(environment_models, 'is_resolvable', lambda x: True)
62
    monkeypatch.setattr(environment_models, 'has_valid_certificate', lambda x: True)
62 63
    command.check_action(action, action_args)
63 64
    assert True
64 65

  
......
68 69
    command.server_action = 'mock a server_action handler (ex: hobo-create)'
69 70
    action, action_args = 'not-a-server-action', {'url': 'https://test.org/'}
70 71

  
71
    monkeypatch.setattr(ServiceBase, 'is_resolvable', lambda x: True)
72
    monkeypatch.setattr(ServiceBase, 'has_valid_certificate', lambda x: True)
72
    monkeypatch.setattr(environment_models, 'is_resolvable', lambda x: True)
73
    monkeypatch.setattr(environment_models, 'has_valid_certificate', lambda x: True)
73 74
    with pytest.raises(CommandError) as e_info:
74 75
        command.check_action(action, action_args)
75 76
    assert 'Unknown action not-a-server-action' in str(e_info.value)
......
80 81
    command.server_action = 'mock a server_action handler (ex: hobo-create)'
81 82
    action, action_args = 'server-action', {'url': 'https://test.org/'}
82 83

  
83
    monkeypatch.setattr(ServiceBase, 'is_resolvable', lambda x: False)
84
    monkeypatch.setattr(ServiceBase, 'has_valid_certificate', lambda x: True)
84
    monkeypatch.setattr(environment_models, 'is_resolvable', lambda x: False)
85
    monkeypatch.setattr(environment_models, 'has_valid_certificate', lambda x: True)
85 86
    with pytest.raises(CommandError) as e_info:
86 87
        command.check_action(action, action_args)
87 88
    assert 'test.org is not resolvable in URL https://test.org/' in str(e_info.value)
......
92 93
    command.server_action = 'mock a server_action handler (ex: hobo-create)'
93 94
    action, action_args = 'server-action', {'url': 'https://test.org/'}
94 95

  
95
    monkeypatch.setattr(ServiceBase, 'is_resolvable', lambda x: True)
96
    monkeypatch.setattr(ServiceBase, 'has_valid_certificate', lambda x: False)
96
    monkeypatch.setattr(environment_models, 'is_resolvable', lambda x: True)
97
    monkeypatch.setattr(environment_models, 'has_valid_certificate', lambda x: False)
97 98
    with pytest.raises(CommandError) as e_info:
98 99
        command.check_action(action, action_args)
99 100
    assert 'no valid certificate for https://test.org/' in str(e_info.value)
tests/test_environment.py
8 8
from test_manager import login
9 9
from webtest import Upload
10 10

  
11
from hobo.environment import models as environment_models
11 12
from hobo.environment.models import AVAILABLE_SERVICES, Combo, Passerelle, ServiceBase, Variable
12 13
from hobo.environment.utils import get_installed_services_dict
13 14
from hobo.profile.models import AttributeDefinition
......
143 144
    response = form.submit()
144 145
    assert 'not resolvable' in response
145 146

  
146
    monkeypatch.setattr(ServiceBase, 'is_resolvable', lambda x: True)
147
    monkeypatch.setattr(environment_models, 'is_resolvable', lambda x: True)
147 148
    form = response.form
148 149
    response = form.submit()
149 150
    assert 'no valid certificate' in response
150 151

  
151 152
    assert not Combo.objects.exists()
152
    monkeypatch.setattr(ServiceBase, 'has_valid_certificate', lambda x: True)
153
    monkeypatch.setattr(environment_models, 'has_valid_certificate', lambda x: True)
153 154
    form = response.form
154 155
    response = form.submit()
155 156
    assert Combo.objects.exists()
tests_schemas/test_cook.py
5 5
from django.core.management.base import CommandError
6 6

  
7 7
from hobo.deploy.utils import get_hobo_json
8
from hobo.environment.models import ServiceBase
8
from hobo.environment import models as environment_models
9 9

  
10 10

  
11 11
def test_cook(db, fake_notify, monkeypatch):
12
    monkeypatch.setattr(ServiceBase, 'is_resolvable', lambda x: True)
13
    monkeypatch.setattr(ServiceBase, 'has_valid_certificate', lambda x: True)
12
    monkeypatch.setattr(environment_models, 'is_resolvable', lambda x: True)
13
    monkeypatch.setattr(environment_models, 'has_valid_certificate', lambda x: True)
14 14
    call_command('cook', 'tests_schemas/recipe.json')
15 15
    assert len(fake_notify) == 3
16 16

  
17 17

  
18 18
def test_cook_unresolvable(db, fake_notify, monkeypatch):
19
    monkeypatch.setattr(ServiceBase, 'is_resolvable', lambda x: False)
19
    monkeypatch.setattr(environment_models, 'is_resolvable', lambda x: False)
20 20
    with pytest.raises(CommandError) as e_info:
21 21
        call_command('cook', 'tests_schemas/recipe.json')
22 22
    assert 'is not resolvable' in str(e_info.value)
......
26 26
    """hobo/cook (before rabbitmq) scenario having templates.
27 27
    the resulting JSON may be helpfull to manually invoque hobo-deploy (after rabbitmq)
28 28
    """
29
    monkeypatch.setattr(ServiceBase, 'is_resolvable', lambda x: True)
30
    monkeypatch.setattr(ServiceBase, 'has_valid_certificate', lambda x: True)
29
    monkeypatch.setattr(environment_models, 'is_resolvable', lambda x: True)
30
    monkeypatch.setattr(environment_models, 'has_valid_certificate', lambda x: True)
31 31
    call_command('cook', 'tests_schemas/example_recipe.json')
32 32

  
33 33
    # notify_agents was call
tests_schemas/test_rename_hobo_service.py
5 5
from django.core.management.base import CommandError
6 6
from tenant_schemas.utils import tenant_context
7 7

  
8
from hobo.environment.models import Passerelle, ServiceBase
8
from hobo.environment import models as environment_models
9 9
from hobo.environment.utils import get_installed_services, get_or_create_local_hobo
10 10
from hobo.multitenant.middleware import TenantMiddleware, TenantNotFound
11 11

  
12 12

  
13 13
@pytest.fixture()
14 14
def hobo_tenant(db, fake_notify, monkeypatch, fake_themes):
15
    monkeypatch.setattr(ServiceBase, 'is_resolvable', lambda x: True)
16
    monkeypatch.setattr(ServiceBase, 'has_valid_certificate', lambda x: True)
15
    monkeypatch.setattr(environment_models, 'is_resolvable', lambda x: True)
16
    monkeypatch.setattr(environment_models, 'has_valid_certificate', lambda x: True)
17 17
    yield call_command('cook', 'tests_schemas/example_recipe.json')
18 18
    call_command('delete_tenant', 'hobo-instance-name.dev.signalpublik.com')
19 19

  
......
34 34

  
35 35

  
36 36
def test_rename_hobo_service_succes(db, fake_notify, monkeypatch, fake_themes):
37
    monkeypatch.setattr(ServiceBase, 'is_resolvable', lambda x: True)
38
    monkeypatch.setattr(ServiceBase, 'has_valid_certificate', lambda x: True)
37
    monkeypatch.setattr(environment_models, 'is_resolvable', lambda x: True)
38
    monkeypatch.setattr(environment_models, 'has_valid_certificate', lambda x: True)
39 39
    call_command('cook', 'tests_schemas/example_recipe.json')
40 40
    assert TenantMiddleware.get_tenant_by_hostname('hobo-instance-name.dev.signalpublik.com')
41 41
    call_command(
tests_schemas/test_rename_service.py
5 5
from django.core.management.base import CommandError
6 6
from tenant_schemas.utils import tenant_context
7 7

  
8
from hobo.environment.models import Passerelle, ServiceBase
8
from hobo.environment import models as environment_models
9 9
from hobo.environment.utils import get_installed_services
10 10
from hobo.multitenant.middleware import TenantMiddleware
11 11

  
12 12

  
13 13
@pytest.fixture()
14 14
def hobo_tenant(db, fake_notify, monkeypatch, fake_themes):
15
    monkeypatch.setattr(ServiceBase, 'is_resolvable', lambda x: True)
16
    monkeypatch.setattr(ServiceBase, 'has_valid_certificate', lambda x: True)
15
    monkeypatch.setattr(environment_models, 'is_resolvable', lambda x: True)
16
    monkeypatch.setattr(environment_models, 'has_valid_certificate', lambda x: True)
17 17
    yield call_command('cook', 'tests_schemas/example_recipe.json')
18 18
    call_command('delete_tenant', 'hobo-instance-name.dev.signalpublik.com')
19 19

  
......
35 35
    tenant = TenantMiddleware.get_tenant_by_hostname('hobo-instance-name.dev.signalpublik.com')
36 36
    with tenant_context(tenant):
37 37
        assert get_installed_services()
38
        Passerelle.objects.create(
38
        environment_models.Passerelle.objects.create(
39 39
            title='other passerelle',
40 40
            slug='other-passerelle',
41 41
            base_url='https://other-passerelle-instance-name.dev.signalpublik.com',
......
56 56
def test_rename_service_succes(hobo_tenant, monkeypatch):
57 57
    tenant = TenantMiddleware.get_tenant_by_hostname('hobo-instance-name.dev.signalpublik.com')
58 58
    with tenant_context(tenant):
59
        assert Passerelle.objects.count() == 1
60
        passerelle_service = Passerelle.objects.first()
59
        assert environment_models.Passerelle.objects.count() == 1
60
        passerelle_service = environment_models.Passerelle.objects.first()
61 61
        assert (
62 62
            passerelle_service.get_base_url_path() == 'https://passerelle-instance-name.dev.signalpublik.com/'
63 63
        )
......
69 69
            'https://passerelle-instance-name.dev.signalpublik.com/',
70 70
            'https://new-passerelle-instance-name.dev.signalpublik.com/',
71 71
        )
72
        assert Passerelle.objects.count() == 1
73
        passerelle_service = Passerelle.objects.first()
72
        assert environment_models.Passerelle.objects.count() == 1
73
        passerelle_service = environment_models.Passerelle.objects.first()
74 74
        assert (
75 75
            passerelle_service.get_base_url_path()
76 76
            == 'https://new-passerelle-instance-name.dev.signalpublik.com/'
77
-