applications: check legacy elements on install (#82373)
gitea/hobo/pipeline/head This commit looks good
Details
gitea/hobo/pipeline/head This commit looks good
Details
This commit is contained in:
parent
2660050395
commit
3d1536687d
|
@ -365,11 +365,13 @@ class Version(models.Model):
|
|||
# this version was already successfully installed, check itself
|
||||
return self
|
||||
|
||||
def check_install(self, job=None):
|
||||
# search for version to check
|
||||
version_to_check = self.get_version_to_check()
|
||||
if version_to_check is None:
|
||||
return
|
||||
def check_install(self, initial=False, job=None):
|
||||
version_to_check = self
|
||||
if not initial:
|
||||
# search for version to check
|
||||
version_to_check = self.get_version_to_check()
|
||||
if version_to_check is None:
|
||||
return
|
||||
|
||||
bundle_content = version_to_check.bundle.read()
|
||||
target_url = 'api/export-import/bundle-check/'
|
||||
|
@ -547,7 +549,9 @@ class AsyncJob(models.Model):
|
|||
elif self.action == 'deploy':
|
||||
self.version.deploy(self)
|
||||
elif self.action == 'check-install':
|
||||
self.version.check_install(self)
|
||||
self.version.check_install(job=self)
|
||||
elif self.action == 'check-first-install':
|
||||
self.version.check_install(job=self, initial=True)
|
||||
except ApplicationError as e:
|
||||
self.status = 'failed'
|
||||
self.exception = e.msg
|
||||
|
@ -569,14 +573,18 @@ class AsyncJob(models.Model):
|
|||
diffs = collections.defaultdict(dict)
|
||||
not_found = collections.defaultdict(list)
|
||||
no_history = collections.defaultdict(list)
|
||||
result_legacy = []
|
||||
for service in self.details.values():
|
||||
for data in service.values():
|
||||
for diff in data.get('differences') or []:
|
||||
diffs[diff['type']][diff['slug']] = diff['url']
|
||||
for unknown in data.get('unknown_elements') or []:
|
||||
not_found[unknown['type']].append(unknown['slug'])
|
||||
for history in data.get('no_history_elements') or []:
|
||||
no_history[history['type']].append(history['slug'])
|
||||
if self.action == 'check-install':
|
||||
# don't look at differences etc on first install
|
||||
for diff in data.get('differences') or []:
|
||||
diffs[diff['type']][diff['slug']] = diff['url']
|
||||
for unknown in data.get('unknown_elements') or []:
|
||||
not_found[unknown['type']].append(unknown['slug'])
|
||||
for history in data.get('no_history_elements') or []:
|
||||
no_history[history['type']].append(history['slug'])
|
||||
result_legacy += data.get('legacy_elements') or []
|
||||
result_diffs = []
|
||||
result_not_found = []
|
||||
result_no_history = []
|
||||
|
@ -594,6 +602,9 @@ class AsyncJob(models.Model):
|
|||
relations,
|
||||
key=lambda a: (a.auto_dependency, types.index(a.element.type), slugify(a.element.name)),
|
||||
)
|
||||
for legacy in result_legacy:
|
||||
legacy['type_label'] = type_labels.get(legacy['type'])
|
||||
result_legacy = sorted(result_legacy, key=lambda a: (types.index(a['type']), slugify(a['text'])))
|
||||
# build information to display
|
||||
for relation in relations:
|
||||
diff = diffs.get(relation.element.type, {}).get(relation.element.slug)
|
||||
|
@ -603,4 +614,4 @@ class AsyncJob(models.Model):
|
|||
result_not_found.append(relation)
|
||||
if relation.element.slug in no_history.get(relation.element.type, []):
|
||||
result_no_history.append(relation)
|
||||
return result_diffs, result_not_found, result_no_history
|
||||
return result_diffs, result_not_found, result_no_history, result_legacy
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
|
||||
{% block breadcrumb %}
|
||||
{{ block.super }}
|
||||
<a href="{% url 'application-confirm-install' app_slug=app.slug version_pk=version.pk %}">{% trans "Update" %}</a>
|
||||
<a href="{% url 'application-confirm-install' app_slug=app.slug version_pk=version.pk %}">{% if last_job.action == 'check-install' %}{% trans "Update" %}{% else %}{% trans "Install" %}{% endif %}</a>
|
||||
{% endblock %}
|
||||
|
||||
{% block appbar %}
|
||||
<h2>{{ app.name }} - {% trans "Update" %}</h2>
|
||||
<h2>{{ app.name }} - {% if last_job.action == 'check-install' %}{% trans "Update" %}{% else %}{% trans "Install" %}{% endif %}</h2>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
@ -21,7 +21,7 @@
|
|||
<form method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
<div class="buttons">
|
||||
{% if last_job.status == 'completed' %}<button class="submit-button">{% trans 'Run update' %}</button>{% endif %}
|
||||
{% if last_job.status == 'completed' %}<button class="submit-button">{% if last_job.action == 'check-install' %}{% trans "Run update" %}{% else %}{% trans "Run install" %}{% endif %}</button>{% endif %}
|
||||
<a class="cancel" href="{% url 'application-manifest' app_slug=app.slug %}">{% trans 'Cancel' %}</a>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -1,23 +1,31 @@
|
|||
{% load i18n %}
|
||||
<div class="pk-information">
|
||||
{% if diffs %}
|
||||
<p>{% trans "Local changes:" %}</p>
|
||||
<ul>
|
||||
{% for relation, url in diffs %}
|
||||
<li>
|
||||
{% blocktrans with type_label=relation.element.type_label name=relation.element.name %}{{ type_label }} "{{ name }}" {% endblocktrans %}
|
||||
(<a href="{{ url }}">{% trans "see changes" %}</a>)
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<p>{% trans "If you run the update, all changes will be lost." %}</p>
|
||||
{% else %}
|
||||
<p>{% trans "No local changes found." %}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if diffs or not legacy %}
|
||||
<div class="pk-information">
|
||||
{% if diffs %}
|
||||
<p>{% trans "Local changes:" %}</p>
|
||||
<ul>
|
||||
{% for relation, url in diffs %}
|
||||
<li>
|
||||
{% blocktrans with type_label=relation.element.type_label name=relation.element.name %}{{ type_label }} "{{ name }}" {% endblocktrans %}
|
||||
(<a href="{{ url }}">{% trans "see changes" %}</a>)
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% if not is_report %}
|
||||
{% if last_job.action == 'check-install' %}
|
||||
<p>{% trans "If you run the update, all changes will be lost." %}</p>
|
||||
{% else %}
|
||||
<p>{% trans "If you run the install, all changes will be lost." %}</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<p>{% trans "No local changes found." %}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if not_found %}
|
||||
<div class="pk-attention">
|
||||
<p>{% trans "Not found elements (removed ?):" %}</p>
|
||||
<p>{% trans "Not found components (removed ?):" %}</p>
|
||||
<ul>
|
||||
{% for relation in not_found %}
|
||||
<li>
|
||||
|
@ -29,7 +37,7 @@
|
|||
{% endif %}
|
||||
{% if no_history %}
|
||||
<div class="pk-attention">
|
||||
<p>{% trans "Impossible to check local changes for these elements (no history found for this application version):" %}</p>
|
||||
<p>{% trans "Impossible to check local changes for these components (no history found for this application version):" %}</p>
|
||||
<ul>
|
||||
{% for relation in no_history %}
|
||||
<li>
|
||||
|
@ -39,3 +47,23 @@
|
|||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if legacy %}
|
||||
<div class="pk-attention">
|
||||
<p>{% trans "These components alreay exist outside the application:" %}</p>
|
||||
<ul>
|
||||
{% for element in legacy %}
|
||||
<li>
|
||||
{% blocktrans with type_label=element.type_label name=element.text %}{{ type_label }} "{{ name }}" {% endblocktrans %}
|
||||
(<a href="{{ element.url }}">{% trans "see component" %}</a>)
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% if not is_report %}
|
||||
{% if last_job.action == 'check-install' %}
|
||||
<p>{% trans "If you run the update, theese components will be reinstalled." %}</p>
|
||||
{% else %}
|
||||
<p>{% trans "If you run the install, theese components will be reinstalled." %}</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
{% endif %}
|
||||
- {% trans "status:" %} {{ job.get_status_display }}
|
||||
{% if job.status == 'failed' %}[{{ job.exception|truncatechars:50 }}]{% endif %}
|
||||
{% if job.action == 'check-install' and job.status == 'completed' %}- <a href="{% url 'application-async-job-diffs' app_slug=app.slug pk=job.pk %}">{% trans "see local changes" %}</a>{% endif %}
|
||||
{% if job.action == 'check-install' or job.action == 'check-first-install' %}{% if job.status == 'completed' %}- <a href="{% url 'application-async-job-diffs' app_slug=app.slug pk=job.pk %}">{% trans "see report" %}</a>{% endif %}{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
|
|
@ -353,19 +353,18 @@ class Install(FormView):
|
|||
version.save()
|
||||
self.version = version
|
||||
|
||||
if not created:
|
||||
# check if some objects where locally modified
|
||||
job = AsyncJob(
|
||||
label=_('Check local modifications'),
|
||||
application=self.application,
|
||||
version=self.version,
|
||||
action='check-install',
|
||||
)
|
||||
job.save()
|
||||
try:
|
||||
job.run()
|
||||
except ApplicationError:
|
||||
pass
|
||||
# check if some objects where locally modified or already exist outside the application
|
||||
job = AsyncJob(
|
||||
label=_('Check installation'),
|
||||
application=self.application,
|
||||
version=self.version,
|
||||
action='check-first-install' if created else 'check-install',
|
||||
)
|
||||
job.save()
|
||||
try:
|
||||
job.run()
|
||||
except ApplicationError:
|
||||
pass
|
||||
|
||||
return super().form_valid(form)
|
||||
|
||||
|
@ -409,35 +408,38 @@ class ConfirmInstall(TemplateView):
|
|||
kwargs['last_job'] = self.last_job
|
||||
|
||||
if self.last_job:
|
||||
diffs, not_found, no_history = self.last_job.get_diff_details()
|
||||
diffs, not_found, no_history, legacy = self.last_job.get_diff_details()
|
||||
kwargs['diffs'] = diffs
|
||||
kwargs['not_found'] = not_found
|
||||
kwargs['no_history'] = no_history
|
||||
kwargs['legacy'] = legacy
|
||||
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
if self.last_job is None or self.last_job.action != 'check-install':
|
||||
if self.last_job is None or self.last_job.action not in ['check-install', 'check-first-install']:
|
||||
return self.install()
|
||||
|
||||
if self.last_job.status == 'completed':
|
||||
no_history_only = True
|
||||
no_legacy = True
|
||||
for service in self.last_job.details.values():
|
||||
for data in service.values():
|
||||
if data.get('differences'):
|
||||
no_history_only = False
|
||||
break
|
||||
if data.get('unknown_elements'):
|
||||
no_history_only = False
|
||||
break
|
||||
if data.get('legacy_elements'):
|
||||
no_history_only = False
|
||||
no_legacy = False
|
||||
if not data.get('no_history_elements'):
|
||||
no_history_only = False
|
||||
break
|
||||
if no_history_only is False:
|
||||
break
|
||||
|
||||
if no_history_only is True:
|
||||
# legacy app, no application information found in elements history, jump to update page.
|
||||
# legacy app, no application information found in elements history, jump to update page
|
||||
return self.install()
|
||||
if self.last_job.action == 'check-first-install' and no_legacy:
|
||||
# first install, no legacy elements, jump to install page
|
||||
return self.install()
|
||||
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
@ -578,16 +580,22 @@ class AsyncJobDiffsView(DetailView):
|
|||
return (
|
||||
super()
|
||||
.get_queryset()
|
||||
.filter(application__slug=self.kwargs['app_slug'], action='check-install', status='completed')
|
||||
.filter(
|
||||
application__slug=self.kwargs['app_slug'],
|
||||
action__in=['check-install', 'check-first-install'],
|
||||
status='completed',
|
||||
)
|
||||
)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
kwargs['app'] = self.object.application
|
||||
|
||||
diffs, not_found, no_history = self.object.get_diff_details()
|
||||
diffs, not_found, no_history, legacy = self.object.get_diff_details()
|
||||
kwargs['diffs'] = diffs
|
||||
kwargs['not_found'] = not_found
|
||||
kwargs['no_history'] = no_history
|
||||
kwargs['legacy'] = legacy
|
||||
kwargs['is_report'] = True
|
||||
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
|
|
@ -233,6 +233,7 @@ def mocked_http(url, request):
|
|||
'differences': [],
|
||||
'unknown_elements': [],
|
||||
'no_history_elements': [{'type': 'forms', 'slug': 'legacy'}],
|
||||
'legacy_elements': [],
|
||||
}
|
||||
}
|
||||
),
|
||||
|
@ -904,14 +905,33 @@ def test_deploy_application(app, admin_user, settings, app_bundle, app_bundle_wi
|
|||
|
||||
login(app)
|
||||
|
||||
def mocked_http2(url, request):
|
||||
if url.path == '/api/export-import/bundle-check/':
|
||||
return {
|
||||
'content': json.dumps(
|
||||
{
|
||||
'data': {
|
||||
'differences': [],
|
||||
'unknown_elements': [],
|
||||
'no_history_elements': [{'type': 'forms', 'slug': 'legacy'}],
|
||||
'legacy_elements': [
|
||||
{'type': 'cards', 'slug': 'test', 'text': 'Test', 'url': 'http://foobar'}
|
||||
],
|
||||
}
|
||||
}
|
||||
),
|
||||
'status_code': 200,
|
||||
}
|
||||
return mocked_http(url, request)
|
||||
|
||||
if action == 'Update':
|
||||
Application.objects.create(name='Test', slug='test', editable=False)
|
||||
|
||||
def install(resp, bundle):
|
||||
resp = resp.click(action)
|
||||
resp.form['bundle'] = Upload('app.tar', bundle, 'application/x-tar')
|
||||
with StatefulHTTMock(mocked_http):
|
||||
resp = resp.form.submit().follow()
|
||||
with StatefulHTTMock(mocked_http2):
|
||||
resp = resp.form.submit()
|
||||
|
||||
assert Application.objects.count() == 1
|
||||
application = Application.objects.get(slug='test')
|
||||
|
@ -927,12 +947,44 @@ def test_deploy_application(app, admin_user, settings, app_bundle, app_bundle_wi
|
|||
else:
|
||||
assert version.number == '42.0'
|
||||
assert version.notes == 'foo bar blah'
|
||||
if action == 'Install':
|
||||
job = AsyncJob.objects.latest('pk')
|
||||
assert resp.location.endswith('/applications/manifest/test/confirm/%s/' % version.pk)
|
||||
with StatefulHTTMock(mocked_http2):
|
||||
resp = resp.follow()
|
||||
assert 'Local changes:' not in resp
|
||||
assert 'Not found components (removed ?):' not in resp
|
||||
assert 'Impossible to check local changes for these components' not in resp
|
||||
assert 'These components alreay exist outside the application' in resp
|
||||
assert 'Card Model "Test"' in resp
|
||||
assert '(<a href="http://foobar">see component</a>)' in resp
|
||||
with StatefulHTTMock(mocked_http2):
|
||||
resp = resp.form.submit()
|
||||
assert resp.location.endswith('/applications/manifest/test/')
|
||||
|
||||
with StatefulHTTMock(mocked_http2):
|
||||
resp = app.get('/applications/manifest/test/job/%s/check-diffs/' % job.pk)
|
||||
assert 'Local changes:' not in resp
|
||||
assert 'Not found components (removed ?):' not in resp
|
||||
assert 'Impossible to check local changes for these components' not in resp
|
||||
assert 'These components alreay exist outside the application' in resp
|
||||
assert 'Card Model "Test"' in resp
|
||||
assert '(<a href="http://foobar">see component</a>)' in resp
|
||||
else:
|
||||
with StatefulHTTMock(mocked_http2):
|
||||
resp = resp.follow()
|
||||
if resp.location:
|
||||
resp.follow()
|
||||
else:
|
||||
resp.form.submit()
|
||||
|
||||
assert application.elements.count() == 4
|
||||
job = AsyncJob.objects.latest('pk')
|
||||
assert job.status == 'completed'
|
||||
assert job.progression_urls == {'wcs': {'Foobar': 'https://wcs.example.invalid/api/jobs/job-uuid/'}}
|
||||
assert Parameter.objects.filter(application=application).count() == 2
|
||||
assert Variable.objects.filter(name__startswith='app_').count() == 2
|
||||
|
||||
# check forms are not marked as error (the other object types are not altered in the mocked responses
|
||||
# and would be marked as errors)
|
||||
assert [x.error for x in application.relation_set.filter(element__type='forms')] == [False]
|
||||
|
@ -940,15 +992,21 @@ def test_deploy_application(app, admin_user, settings, app_bundle, app_bundle_wi
|
|||
|
||||
resp = app.get('/applications/')
|
||||
if action == 'Update':
|
||||
with StatefulHTTMock(mocked_http):
|
||||
with StatefulHTTMock(mocked_http2):
|
||||
resp = resp.click(href='/manifest/test/')
|
||||
version1 = install(resp, app_bundle)
|
||||
if action == 'Update':
|
||||
# update, check-install job then deploy job
|
||||
assert list(AsyncJob.objects.values_list('action', flat=True)) == ['check-install', 'deploy']
|
||||
assert list(AsyncJob.objects.values_list('action', flat=True).order_by('pk')) == [
|
||||
'check-install',
|
||||
'deploy',
|
||||
]
|
||||
else:
|
||||
# first install, just deploy job
|
||||
assert list(AsyncJob.objects.values_list('action', flat=True)) == ['deploy']
|
||||
assert list(AsyncJob.objects.values_list('action', flat=True).order_by('pk')) == [
|
||||
'check-first-install',
|
||||
'deploy',
|
||||
]
|
||||
assert version1.application.version_set.count() == 1
|
||||
version2 = install(resp, app_bundle)
|
||||
assert version2.application.version_set.count() == 1
|
||||
|
@ -974,15 +1032,16 @@ def test_deploy_application(app, admin_user, settings, app_bundle, app_bundle_wi
|
|||
def response_content(url, request):
|
||||
if url.path == '/api/export-import/bundle-import/':
|
||||
return {'status_code': 500}
|
||||
return mocked_http(url, request)
|
||||
return mocked_http2(url, request)
|
||||
|
||||
resp = app.get('/applications/')
|
||||
if action == 'Update':
|
||||
with StatefulHTTMock(mocked_http):
|
||||
with StatefulHTTMock(mocked_http2):
|
||||
resp = resp.click(href='manifest/test/')
|
||||
resp = resp.click(action)
|
||||
resp.form['bundle'] = Upload('app.tar', app_bundle, 'application/x-tar')
|
||||
with StatefulHTTMock(response_content):
|
||||
resp = resp.form.submit().follow()
|
||||
with pytest.raises(DeploymentError) as e:
|
||||
resp.form.submit().follow()
|
||||
assert str(e.value) == 'Failed to deploy module wcs (500)'
|
||||
|
@ -1012,15 +1071,16 @@ def test_deploy_application(app, admin_user, settings, app_bundle, app_bundle_wi
|
|||
'content': {'data': [form_def]},
|
||||
'status_code': 200,
|
||||
}
|
||||
return mocked_http(url, request)
|
||||
return mocked_http2(url, request)
|
||||
|
||||
resp = app.get('/applications/')
|
||||
if action == 'Update':
|
||||
with StatefulHTTMock(mocked_http):
|
||||
with StatefulHTTMock(mocked_http2):
|
||||
resp = resp.click(href='manifest/test/')
|
||||
resp = resp.click(action)
|
||||
resp.form['bundle'] = Upload('app.tar', app_bundle, 'application/x-tar')
|
||||
with StatefulHTTMock(response_content):
|
||||
resp = resp.form.submit().follow()
|
||||
resp.form.submit().follow()
|
||||
application = Application.objects.get(slug='test')
|
||||
elements = application.elements.all().order_by('type')
|
||||
|
@ -1033,15 +1093,16 @@ def test_deploy_application(app, admin_user, settings, app_bundle, app_bundle_wi
|
|||
def response_content(url, request): # noqa pylint: disable=function-redefined
|
||||
if url.path == '/api/export-import/forms/':
|
||||
return {'status_code': 500}
|
||||
return mocked_http(url, request)
|
||||
return mocked_http2(url, request)
|
||||
|
||||
resp = app.get('/applications/')
|
||||
if action == 'Update':
|
||||
with StatefulHTTMock(mocked_http):
|
||||
with StatefulHTTMock(mocked_http2):
|
||||
resp = resp.click(href='manifest/test/')
|
||||
resp = resp.click(action)
|
||||
resp.form['bundle'] = Upload('app.tar', app_bundle, 'application/x-tar')
|
||||
with StatefulHTTMock(response_content):
|
||||
resp = resp.form.submit().follow()
|
||||
with pytest.raises(ScanError) as e:
|
||||
resp.form.submit().follow()
|
||||
assert str(e.value) == 'Failed to get elements of type forms (500)'
|
||||
|
@ -1052,7 +1113,7 @@ def test_deploy_application(app, admin_user, settings, app_bundle, app_bundle_wi
|
|||
# bad file format
|
||||
resp = app.get('/applications/')
|
||||
if action == 'Update':
|
||||
with StatefulHTTMock(mocked_http):
|
||||
with StatefulHTTMock(mocked_http2):
|
||||
resp = resp.click(href='manifest/test/')
|
||||
resp = resp.click(action)
|
||||
resp.form['bundle'] = Upload('app.tar', b'garbage', 'application/x-tar')
|
||||
|
@ -1101,7 +1162,9 @@ def test_update_application(app, admin_user, settings, app_bundle):
|
|||
assert resp.location.endswith('/applications/manifest/test/confirm/%s/' % last_version.pk)
|
||||
resp = resp.follow()
|
||||
assert resp.location.endswith('/applications/manifest/test/')
|
||||
assert list(AsyncJob.objects.filter(version__number='42.0').values_list('action', flat=True)) == [
|
||||
assert list(
|
||||
AsyncJob.objects.filter(version__number='42.0').values_list('action', flat=True).order_by('pk')
|
||||
) == [
|
||||
'check-install',
|
||||
'deploy',
|
||||
]
|
||||
|
@ -1115,6 +1178,9 @@ def test_update_application(app, admin_user, settings, app_bundle):
|
|||
'differences': [{'type': 'forms', 'slug': 'test', 'url': 'http://foobar'}],
|
||||
'unknown_elements': [{'type': 'workflows', 'slug': 'test'}],
|
||||
'no_history_elements': [{'type': 'blocks', 'slug': 'test'}],
|
||||
'legacy_elements': [
|
||||
{'type': 'cards', 'slug': 'test', 'text': 'Test', 'url': 'http://foobar'}
|
||||
],
|
||||
}
|
||||
}
|
||||
),
|
||||
|
@ -1130,23 +1196,28 @@ def test_update_application(app, admin_user, settings, app_bundle):
|
|||
last_version = Version.objects.latest('pk')
|
||||
assert resp.location.endswith('/applications/manifest/test/confirm/%s/' % last_version.pk)
|
||||
resp = resp.follow()
|
||||
assert list(AsyncJob.objects.filter(version__number='42.0').values_list('action', flat=True)) == [
|
||||
'check-install'
|
||||
]
|
||||
assert list(
|
||||
AsyncJob.objects.filter(version__number='42.0').values_list('action', flat=True).order_by('pk')
|
||||
) == ['check-install']
|
||||
job = AsyncJob.objects.latest('pk')
|
||||
assert 'Local changes:' in resp
|
||||
assert 'Form "test"' in resp
|
||||
assert '(<a href="http://foobar">see changes</a>)' in resp
|
||||
assert 'Not found elements (removed ?):' in resp
|
||||
assert 'Not found components (removed ?):' in resp
|
||||
assert 'Workflow "test"' in resp
|
||||
assert (
|
||||
'Impossible to check local changes for these elements (no history found for this application version):'
|
||||
'Impossible to check local changes for these components (no history found for this application version):'
|
||||
in resp
|
||||
)
|
||||
assert 'Block of fields "test"' in resp
|
||||
assert 'These components alreay exist outside the application' in resp
|
||||
assert 'Card Model "Test"' in resp
|
||||
assert '(<a href="http://foobar">see component</a>)' in resp
|
||||
resp = resp.form.submit()
|
||||
assert resp.location.endswith('/applications/manifest/test/')
|
||||
assert list(AsyncJob.objects.filter(version__number='42.0').values_list('action', flat=True)) == [
|
||||
assert list(
|
||||
AsyncJob.objects.filter(version__number='42.0').values_list('action', flat=True).order_by('pk')
|
||||
) == [
|
||||
'check-install',
|
||||
'deploy',
|
||||
]
|
||||
|
@ -1155,13 +1226,16 @@ def test_update_application(app, admin_user, settings, app_bundle):
|
|||
assert 'Local changes:' in resp
|
||||
assert 'Form "test"' in resp
|
||||
assert '(<a href="http://foobar">see changes</a>)' in resp
|
||||
assert 'Not found elements (removed ?):' in resp
|
||||
assert 'Not found components (removed ?):' in resp
|
||||
assert 'Workflow "test"' in resp
|
||||
assert (
|
||||
'Impossible to check local changes for these elements (no history found for this application version):'
|
||||
'Impossible to check local changes for these components (no history found for this application version):'
|
||||
in resp
|
||||
)
|
||||
assert 'Block of fields "test"' in resp
|
||||
assert 'These components alreay exist outside the application' in resp
|
||||
assert 'Card Model "Test"' in resp
|
||||
assert '(<a href="http://foobar">see component</a>)' in resp
|
||||
|
||||
def response_content(url, request): # noqa pylint: disable=function-redefined
|
||||
if url.path == '/api/export-import/bundle-check/':
|
||||
|
@ -1177,9 +1251,9 @@ def test_update_application(app, admin_user, settings, app_bundle):
|
|||
'/applications/manifest/test/confirm/%s/' % Version.objects.latest('pk').pk
|
||||
)
|
||||
resp = resp.follow()
|
||||
assert list(AsyncJob.objects.filter(version__number='42.0').values_list('action', flat=True)) == [
|
||||
'check-install'
|
||||
]
|
||||
assert list(
|
||||
AsyncJob.objects.filter(version__number='42.0').values_list('action', flat=True).order_by('pk')
|
||||
) == ['check-install']
|
||||
assert 'Error checking local changes, update can not be run.' in resp
|
||||
|
||||
def response_content(url, request): # noqa pylint: disable=function-redefined
|
||||
|
@ -1416,29 +1490,34 @@ def test_deploy_application_roles(app, admin_user, settings, app_bundle_roles):
|
|||
resp.form['bundle'] = Upload('app.tar', app_bundle_roles, 'application/x-tar')
|
||||
with StatefulHTTMock(httmock.remember_called(mocked_http)):
|
||||
resp = resp.form.submit().follow()
|
||||
# roles
|
||||
assert mocked_http.call['requests'][0].url.startswith(
|
||||
'https://idp.example.invalid/api/roles/?update'
|
||||
'https://wcs.example.invalid/api/export-import/bundle-check/?'
|
||||
)
|
||||
# roles
|
||||
assert mocked_http.call['requests'][1].url.startswith(
|
||||
'https://idp.example.invalid/api/provision/'
|
||||
'https://idp.example.invalid/api/roles/?update'
|
||||
)
|
||||
assert mocked_http.call['requests'][2].url.startswith(
|
||||
'https://idp.example.invalid/api/roles/?update'
|
||||
'https://idp.example.invalid/api/provision/'
|
||||
)
|
||||
assert mocked_http.call['requests'][3].url.startswith(
|
||||
'https://idp.example.invalid/api/roles/?update'
|
||||
)
|
||||
assert mocked_http.call['requests'][4].url.startswith(
|
||||
'https://idp.example.invalid/api/provision/'
|
||||
)
|
||||
# then form
|
||||
assert 'wcs.example.invalid' in mocked_http.call['requests'][4].url
|
||||
assert mocked_http.call['requests'][5].url.startswith(
|
||||
'https://wcs.example.invalid/api/export-import/bundle-import/?'
|
||||
)
|
||||
assert mocked_http.call['requests'][6].url.startswith(
|
||||
'https://wcs.example.invalid/api/export-import/?'
|
||||
)
|
||||
# then element refresh
|
||||
available_objects = [o for o in WCS_AVAILABLE_OBJECTS['data'] if o['id'] in ['forms', 'roles']]
|
||||
assert mocked_http.call['count'] == 5 + 1 + len(available_objects)
|
||||
assert mocked_http.call['count'] == 6 + 1 + len(available_objects)
|
||||
for i, object_type in enumerate(available_objects):
|
||||
assert mocked_http.call['requests'][6 + i].url.startswith(
|
||||
assert mocked_http.call['requests'][7 + i].url.startswith(
|
||||
'https://wcs.example.invalid/api/export-import/%s/?' % object_type['id']
|
||||
)
|
||||
|
||||
|
@ -1461,6 +1540,20 @@ def test_deploy_application_roles(app, admin_user, settings, app_bundle_roles):
|
|||
assert job.exception == 'Failed to create role test-role (500)'
|
||||
|
||||
def response_content(url, request): # noqa pylint: disable=function-redefined
|
||||
if url.path == '/api/export-import/bundle-check/':
|
||||
return {
|
||||
'content': json.dumps(
|
||||
{
|
||||
'data': {
|
||||
'differences': [],
|
||||
'unknown_elements': [],
|
||||
'no_history_elements': [],
|
||||
'legacy_elements': [],
|
||||
}
|
||||
}
|
||||
),
|
||||
'status_code': 200,
|
||||
}
|
||||
if url.path == '/api/provision/':
|
||||
return {'status_code': 500}
|
||||
return mocked_http(url, request)
|
||||
|
@ -1468,6 +1561,7 @@ def test_deploy_application_roles(app, admin_user, settings, app_bundle_roles):
|
|||
resp = app.get('/applications/install/')
|
||||
resp.form['bundle'] = Upload('app.tar', app_bundle_roles, 'application/x-tar')
|
||||
with StatefulHTTMock(response_content):
|
||||
resp = resp.form.submit().follow()
|
||||
with pytest.raises(DeploymentError) as e:
|
||||
resp.form.submit().follow()
|
||||
assert str(e.value) == 'Failed to provision role test-role (500)'
|
||||
|
@ -1482,12 +1576,12 @@ def test_deploy_application_roles(app, admin_user, settings, app_bundle_roles):
|
|||
resp = resp.click('Install')
|
||||
resp.form['bundle'] = Upload('app.tar', app_bundle_roles, 'application/x-tar')
|
||||
with StatefulHTTMock(httmock.remember_called(mocked_http)):
|
||||
resp.form.submit().follow()
|
||||
resp.form.submit().follow().follow()
|
||||
# ou must be specified when calling authentic API
|
||||
assert mocked_http.call['requests'][0].url.startswith(
|
||||
assert mocked_http.call['requests'][1].url.startswith(
|
||||
'https://idp.example.invalid/api/roles/?update_or_create=slug&update_or_create=ou'
|
||||
)
|
||||
assert b'"ou": "service-ou"' in mocked_http.call['requests'][0].body
|
||||
assert b'"ou": "service-ou"' in mocked_http.call['requests'][1].body
|
||||
|
||||
# test import on a default OU
|
||||
Application.objects.all().delete()
|
||||
|
@ -1498,8 +1592,8 @@ def test_deploy_application_roles(app, admin_user, settings, app_bundle_roles):
|
|||
v.service_pk = wcs.id
|
||||
v.save()
|
||||
with StatefulHTTMock(httmock.remember_called(mocked_http)):
|
||||
resp.form.submit().follow()
|
||||
assert b'"ou": "default"' in mocked_http.call['requests'][0].body
|
||||
resp.form.submit().follow().follow()
|
||||
assert b'"ou": "default"' in mocked_http.call['requests'][1].body
|
||||
|
||||
|
||||
def test_job_status_page(app, admin_user, settings):
|
||||
|
|
Loading…
Reference in New Issue