applications: mark element as in error on scan failure (#70981)
This commit is contained in:
parent
f699c76306
commit
25d01c5567
|
@ -0,0 +1,23 @@
|
|||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('applications', '0007_asyncjob'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='element',
|
||||
name='error',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='element',
|
||||
name='error_status',
|
||||
field=models.CharField(
|
||||
choices=[('notfound', 'Not Found'), ('error', 'Error')], max_length=100, null=True
|
||||
),
|
||||
),
|
||||
]
|
|
@ -98,12 +98,14 @@ class Application(models.Model):
|
|||
continue
|
||||
response = requests.get(dependencies_url)
|
||||
if not response.ok:
|
||||
el.set_error(response.status_code)
|
||||
raise ScanError(
|
||||
_(
|
||||
'Failed to scan "%s" (type %s, slug %s) dependencies (%s)'
|
||||
% (el.name, el.type, el.slug, response.status_code)
|
||||
)
|
||||
)
|
||||
el.reset_error()
|
||||
for dependency in response.json()['data']:
|
||||
if (dependency['type'], dependency['id']) in elements:
|
||||
continue
|
||||
|
@ -127,6 +129,15 @@ class Element(models.Model):
|
|||
slug = models.SlugField(max_length=500, verbose_name=_('Slug'))
|
||||
name = models.CharField(max_length=500, verbose_name=_('Name'))
|
||||
cache = JSONField(blank=True, default=dict)
|
||||
error = models.BooleanField(default=False)
|
||||
error_status = models.CharField(
|
||||
max_length=100,
|
||||
choices=[
|
||||
('notfound', _('Not Found')),
|
||||
('error', _('Error')),
|
||||
],
|
||||
null=True,
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return '<Element %s/%s>' % (self.type, self.slug)
|
||||
|
@ -141,6 +152,16 @@ class Element(models.Model):
|
|||
if self.cache['urls'].get('export'):
|
||||
return '%sredirect/' % self.cache['urls']['export']
|
||||
|
||||
def set_error(self, http_status_code):
|
||||
self.error = True
|
||||
self.error_status = 'notfound' if http_status_code == 404 else 'error'
|
||||
self.save()
|
||||
|
||||
def reset_error(self):
|
||||
self.error = False
|
||||
self.error_status = None
|
||||
self.save()
|
||||
|
||||
|
||||
class Relation(models.Model):
|
||||
application = models.ForeignKey(Application, on_delete=models.CASCADE)
|
||||
|
|
|
@ -26,11 +26,14 @@
|
|||
|
||||
{% block content %}
|
||||
|
||||
<ul class="objects-list single-links">
|
||||
<ul class="objects-list single-links application-content">
|
||||
{% for relation in relations %}
|
||||
{% if not relation.auto_dependency %}
|
||||
<li>
|
||||
<a {% if relation.element.get_redirect_url %}href="{{ relation.element.get_redirect_url }}"{% endif %}>{{ relation.element.name }} <span class="extra-info">- {{ relation.element.type_label }}</span></a>
|
||||
<a {% if relation.element.get_redirect_url %}href="{{ relation.element.get_redirect_url }}"{% endif %}>
|
||||
{% if relation.element.error %}<span class="tag tag-error">{{ relation.element.get_error_status_display }}</span>{% endif %}
|
||||
{{ relation.element.name }} <span class="extra-info">- {{ relation.element.type_label }}</span>
|
||||
</a>
|
||||
{% if app.editable %}<a rel="popup" class="delete" href="{% url 'application-delete-element' app_slug=app.slug pk=relation.id %}">{% trans "remove" %}</a>{% endif %}
|
||||
</li>
|
||||
{% endif %}
|
||||
|
|
|
@ -343,6 +343,12 @@ h2.application-title {
|
|||
}
|
||||
}
|
||||
|
||||
ul.objects-list.application-content {
|
||||
span.tag-error {
|
||||
background: #CD2026;
|
||||
}
|
||||
}
|
||||
|
||||
#versions {
|
||||
.version {
|
||||
background: white;
|
||||
|
|
|
@ -382,6 +382,33 @@ def test_scandeps_on_unknown_element(app, admin_user, settings):
|
|||
job = AsyncJob.objects.latest('pk')
|
||||
assert job.status == 'failed'
|
||||
assert job.exception == 'Failed to scan "Unknown" (type forms, slug unknown) dependencies (404)'
|
||||
element.refresh_from_db()
|
||||
assert element.error is True
|
||||
assert element.error_status == 'notfound'
|
||||
|
||||
def response_content(url, request):
|
||||
if url.path == '/api/export-import/forms/unknown/dependencies/':
|
||||
return {'status_code': 500}
|
||||
return mocked_http(url, request)
|
||||
|
||||
with HTTMock(response_content):
|
||||
with pytest.raises(ScanError) as e:
|
||||
app.get('/applications/manifest/test/scandeps/').follow()
|
||||
assert str(e.value) == 'Failed to scan "Unknown" (type forms, slug unknown) dependencies (500)'
|
||||
job = AsyncJob.objects.latest('pk')
|
||||
assert job.status == 'failed'
|
||||
assert job.exception == 'Failed to scan "Unknown" (type forms, slug unknown) dependencies (500)'
|
||||
element.refresh_from_db()
|
||||
assert element.error is True
|
||||
assert element.error_status == 'error'
|
||||
|
||||
with HTTMock(mocked_http):
|
||||
app.get('/applications/manifest/test/scandeps/').follow()
|
||||
job = AsyncJob.objects.latest('pk')
|
||||
assert job.status == 'completed'
|
||||
element.refresh_from_db()
|
||||
assert element.error is False
|
||||
assert element.error_status is None
|
||||
|
||||
|
||||
@pytest.mark.parametrize('editable', [True, False])
|
||||
|
|
Loading…
Reference in New Issue