Projet

Général

Profil

0001-manage-availability-check-through-the-UI-29965.patch

Emmanuel Cazenave, 05 février 2019 15:39

Télécharger (12,9 ko)

Voir les différences:

Subject: [PATCH] manage availability check through the UI (#29965)

 .../migrations/0011_auto_20190205_1126.py     | 30 +++++++++++
 passerelle/base/models.py                     | 27 ++++++++++
 passerelle/base/urls.py                       |  7 ++-
 passerelle/base/views.py                      | 52 ++++++++++++++++++-
 .../manage/manage_availability_form.html      | 17 ++++++
 .../passerelle/manage/service_view.html       |  3 ++
 tests/test_availability.py                    | 20 +++++++
 tests/test_manager.py                         | 52 ++++++++++++++++++-
 8 files changed, 204 insertions(+), 4 deletions(-)
 create mode 100644 passerelle/base/migrations/0011_auto_20190205_1126.py
 create mode 100644 passerelle/templates/passerelle/manage/manage_availability_form.html
passerelle/base/migrations/0011_auto_20190205_1126.py
1
# -*- coding: utf-8 -*-
2
# Generated by Django 1.11.17 on 2019-02-05 10:26
3
from __future__ import unicode_literals
4

  
5
from django.db import migrations, models
6
import django.db.models.deletion
7

  
8

  
9
class Migration(migrations.Migration):
10

  
11
    dependencies = [
12
        ('contenttypes', '0002_remove_content_type_name'),
13
        ('base', '0010_loggingparameters_trace_emails'),
14
    ]
15

  
16
    operations = [
17
        migrations.CreateModel(
18
            name='AvailibityParameters',
19
            fields=[
20
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
21
                ('resource_pk', models.PositiveIntegerField()),
22
                ('disable_check', models.BooleanField(default=False, verbose_name='Disable availiblity check')),
23
                ('resource_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')),
24
            ],
25
        ),
26
        migrations.AlterUniqueTogether(
27
            name='availibityparameters',
28
            unique_together=set([('resource_type', 'resource_pk')]),
29
        ),
30
    ]
passerelle/base/models.py
176 176
        parameters.log_level = value
177 177
        parameters.save()
178 178

  
179
    @property
180
    def availability_parameters(self):
181
        resource_type = ContentType.objects.get_for_model(self)
182
        try:
183
            return AvailibityParameters.objects.get(
184
                    resource_type=resource_type,
185
                    resource_pk=self.id)
186
        except AvailibityParameters.DoesNotExist:
187
            return AvailibityParameters(
188
                    resource_type=resource_type,
189
                    resource_pk=self.id)
190

  
179 191
    def soap_client(self, **kwargs):
180 192
        return passerelle.utils.SOAPClient(resource=self, **kwargs)
181 193

  
......
390 402

  
391 403
    def availability(self):
392 404
        # "availability" cron job to update service statuses
405

  
406
        # eventually skip it
407
        if self.availability_parameters.disable_check:
408
            return
409

  
393 410
        currently_down = self.down()
394 411
        try:
395 412
            self.check_status()
......
477 494
        unique_together = (('resource_type', 'resource_pk'))
478 495

  
479 496

  
497
class AvailibityParameters(models.Model):
498
    resource_type = models.ForeignKey(ContentType)
499
    resource_pk = models.PositiveIntegerField()
500
    resource = fields.GenericForeignKey('resource_type', 'resource_pk')
501
    disable_check = models.BooleanField(default=False, verbose_name=_('Disable availiblity check'))
502

  
503
    class Meta:
504
        unique_together = (('resource_type', 'resource_pk'))
505

  
506

  
480 507

  
481 508
class ResourceLog(models.Model):
482 509
    timestamp = models.DateTimeField(auto_now_add=True)
passerelle/base/urls.py
2 2

  
3 3
from .views import ApiUserCreateView, ApiUserUpdateView, ApiUserDeleteView, \
4 4
        ApiUserListView, AccessRightDeleteView, AccessRightCreateView, \
5
        LoggingParametersUpdateView
5
        LoggingParametersUpdateView, ManageAvailabilityView
6 6

  
7 7
access_urlpatterns = [
8 8
    url(r'^$', ApiUserListView.as_view(), name='apiuser-list'),
......
15 15
    url(r'^accessright/add/(?P<resource_type>[\w,-]+)/(?P<resource_pk>[\w,-]+)/(?P<codename>[\w,-]+)/',
16 16
        AccessRightCreateView.as_view(), name='access-right-add'),
17 17
    url(r'logging/parameters/(?P<resource_type>[\w,-]+)/(?P<resource_pk>[\w,-]+)/$',
18
        LoggingParametersUpdateView.as_view(), name='logging-parameters')
18
        LoggingParametersUpdateView.as_view(), name='logging-parameters'),
19
    url(r'manage/availability/(?P<resource_type>[\w,-]+)/(?P<resource_pk>[\w,-]+)/$',
20
        ManageAvailabilityView.as_view(), name='manage-availability')
21

  
19 22
]
passerelle/base/views.py
5 5
from django.views.generic import *
6 6
from django.http import Http404
7 7

  
8
from .models import ApiUser, AccessRight, LoggingParameters
8
from .models import ApiUser, AccessRight, LoggingParameters, AvailibityParameters, ResourceStatus
9 9
from .forms import ApiUserForm, AccessRightForm
10 10
from ..utils import get_trusted_services
11 11

  
......
136 136
        parameters.trace_emails = form.cleaned_data['trace_emails']
137 137
        parameters.save()
138 138
        return super(LoggingParametersUpdateView, self).form_valid(form)
139

  
140

  
141
class ManageAvailabilityView(FormView):
142
    template_name = 'passerelle/manage/manage_availability_form.html'
143

  
144
    def get_context_data(self, **kwargs):
145
        context = super(ManageAvailabilityView, self).get_context_data(**kwargs)
146
        connector = self.get_resource()
147
        context['connector'] = connector
148
        context['availability_status'] = connector.get_availability_status()
149
        return context
150

  
151
    def get_form_class(self):
152
        form_class = model_forms.modelform_factory(
153
                AvailibityParameters,
154
                fields=['disable_check'])
155
        return form_class
156

  
157
    def get_initial(self):
158
        d = self.initial.copy()
159
        d['resource_type'] = self.kwargs['resource_type']
160
        d['resource_pk'] = self.kwargs['resource_pk']
161
        d['disable_check'] = self.get_resource().availability_parameters.disable_check
162
        return d
163

  
164
    def get_resource(self):
165
        content_type = ContentType.objects.get_for_id(self.kwargs['resource_type'])
166
        return content_type.model_class().objects.get(pk=self.kwargs['resource_pk'])
167

  
168
    def get_success_url(self):
169
        return self.get_resource().get_absolute_url()
170

  
171
    def form_valid(self, form):
172
        resource = self.get_resource()
173
        parameters = resource.availability_parameters
174
        disable_check = form.cleaned_data['disable_check']
175

  
176
        if resource.down() and disable_check:
177
            resource_type = ContentType.objects.get_for_model(resource)
178
            ResourceStatus(
179
                resource_type=resource_type,
180
                resource_pk=self.kwargs['resource_pk'],
181
                status='up',
182
                message='').save()
183
            resource.logger.info(
184
                u'connector "%s" (%s) put back up by user', resource, resource.__class__.__name__)
185

  
186
        parameters.disable_check = disable_check
187
        parameters.save()
188
        return super(ManageAvailabilityView, self).form_valid(form)
passerelle/templates/passerelle/manage/manage_availability_form.html
1
{% extends "passerelle/manage.html" %}
2
{% load i18n %}
3

  
4
{% block appbar %}
5
<h2>{% trans 'Connector Status' %} : {{availability_status.status}}</h2>
6
{% endblock %}
7

  
8
{% block content %}
9
<form method="post">
10
  {% csrf_token %}
11
  {{ form.as_p }}
12
  <div class="buttons">
13
    <button class="submit-button">{% trans 'Save' %}</button>
14
    <a href="{{ connector.get_absolute_url }}" class="cancel">{% trans 'Cancel' %}</a>
15
  </div>
16
</form>
17
{% endblock %}
passerelle/templates/passerelle/manage/service_view.html
15 15
    {% endwith %}
16 16
</h2>
17 17
<span class="actions">
18
{% if object|can_edit:request.user and object.get_availability_status %}
19
<a rel="popup" href="{% url 'manage-availability' resource_type=object|resource_type resource_pk=object.id %}">{% trans 'manage availability' %}</a>
20
{% endif %}
18 21
{% if object|can_edit:request.user %}
19 22
<a rel="popup" href="{% url 'logging-parameters' resource_type=object|resource_type resource_pk=object.id %}">{% trans 'logging parameters' %}</a>
20 23
{% endif %}
tests/test_availability.py
73 73
        connector.availability()
74 74
    assert connector.get_availability_status().down()
75 75
    assert '500' in connector.get_availability_status().message
76

  
77

  
78
def test_availability_disabled(app, connector):
79
    with HTTMock(up_mock):
80
        connector.availability()
81
    assert connector.get_availability_status().up()
82

  
83
    av = connector.availability_parameters
84
    av.disable_check = True
85
    av.save()
86

  
87
    with HTTMock(down_mock):
88
        connector.availability()
89
    assert connector.get_availability_status().up()
90

  
91
    av.disable_check = False
92
    av.save()
93
    with HTTMock(down_mock):
94
        connector.availability()
95
    assert connector.get_availability_status().down()
tests/test_manager.py
7 7
from django.core.files import File
8 8
import pytest
9 9

  
10
from passerelle.base.models import ApiUser, AccessRight, ResourceLog
10
from passerelle.base.models import ApiUser, AccessRight, ResourceLog, ResourceStatus
11 11
from passerelle.apps.csvdatasource.models import CsvDataSource, Query
12 12

  
13 13
pytestmark = pytest.mark.django_db
......
197 197
    resp = app.get(csv.get_absolute_url())
198 198
    resp = resp.click('logging parameters')
199 199
    assert resp.form['trace_emails'].value == 'fred@localhost'
200

  
201

  
202
def test_availability_parameters(app, admin_user):
203
    data = StringIO('1;Foo\n2;Bar\n3;Baz')
204
    csv = CsvDataSource.objects.create(
205
        csv_file=File(data, 't.csv'),
206
        columns_keynames='id, text', slug='test', title='a title', description='a description')
207
    app = login(app)
208
    resp = app.get(csv.get_absolute_url())
209

  
210
    assert not csv.availability_parameters.disable_check
211
    # No availability check so this should not show up
212
    assert 'manage availability' not in resp.text
213

  
214
    resource_type = ContentType.objects.get_for_model(csv)
215
    status = ResourceStatus(
216
        resource_type=resource_type, resource_pk=csv.pk,
217
        status='up', message='')
218
    status.save()
219
    resp = app.get(csv.get_absolute_url())
220
    assert 'manage availability' in resp.text
221

  
222
    resp = resp.click('manage availability')
223
    assert 'up' in resp.text
224
    resp.form['disable_check'] = True
225
    resp = resp.form.submit()
226
    # Connector status not changed, availibility parameters changed
227
    assert status == csv.get_availability_status()
228
    assert csv.availability_parameters.disable_check
229

  
230
    resp = app.get(csv.get_absolute_url())
231
    resp = resp.click('manage availability')
232
    resp.form['disable_check'] = False
233
    resp = resp.form.submit()
234

  
235
    # Connector down
236
    status = ResourceStatus(
237
        resource_type=resource_type, resource_pk=csv.pk,
238
        status='down', message='')
239
    status.save()
240
    assert csv.down()
241
    resp = app.get(csv.get_absolute_url())
242
    resp = resp.click('manage availability')
243
    resp.form['disable_check'] = True
244
    resp = resp.form.submit()
245
    # Connector is put backup
246
    assert csv.availability_parameters.disable_check
247
    assert not csv.down()
248
    status = csv.get_availability_status()
249
    assert status.status == 'up'
200
-