applications: shortcut to update an app (#71398)
gitea-wip/hobo/pipeline/head There was a failure building this commit Details
gitea/hobo/pipeline/head Something is wrong with the build of this commit Details

This commit is contained in:
Lauréline Guérin 2022-11-17 17:55:27 +01:00
parent e4fa439f49
commit 8ea3ded995
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
5 changed files with 88 additions and 4 deletions

View File

@ -17,7 +17,11 @@
</h2>
<span class="actions">
<a class="extra-actions-menu-opener"></a>
{% if app.editable %}<a rel="popup" href="{% url 'application-metadata' app_slug=app.slug %}">{% trans 'Metadata' %}</a>{% endif %}
{% if app.editable %}
<a rel="popup" href="{% url 'application-metadata' app_slug=app.slug %}">{% trans 'Metadata' %}</a>
{% else %}
<a rel="popup" href="{% url 'application-update' app_slug=app.slug %}">{% trans 'Update' %}</a>
{% endif %}
<ul class="extra-actions-menu">
<li><a href="{% url 'application-versions' app_slug=app.slug %}">{% trans 'See all versions' %}</a></li>
</ul>

View File

@ -0,0 +1,17 @@
{% extends "hobo/base.html" %}
{% load i18n %}
{% block appbar %}
<h2>{% trans "Update" %}</h2>
{% endblock %}
{% block content %}
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<div class="buttons">
<button class="submit-button">{% trans 'Update' %}</button>
<a class="cancel" href="{% url 'application-manifest' app.slug %}">{% trans 'Cancel' %}</a>
</div>
</form>
{% endblock %}

View File

@ -24,6 +24,7 @@ urlpatterns = [
path('install/', views.install, name='application-install'),
re_path(r'^manifest/(?P<slug>[\w-]+)/delete/$', views.delete, name='application-delete'),
re_path(r'^manifest/(?P<app_slug>[\w-]+)/$', views.manifest, name='application-manifest'),
re_path(r'^manifest/(?P<app_slug>[\w-]+)/update/$', views.update, name='application-update'),
re_path(r'^manifest/(?P<app_slug>[\w-]+)/versions/$', views.versions, name='application-versions'),
re_path(r'^manifest/(?P<app_slug>[\w-]+)/metadata/$', views.metadata, name='application-metadata'),
re_path(r'^manifest/(?P<app_slug>[\w-]+)/scandeps/$', views.scandeps, name='application-scandeps'),

View File

@ -289,11 +289,17 @@ class Install(FormView):
form_class = InstallForm
template_name = 'hobo/applications/install.html'
success_url = reverse_lazy('applications-home')
application = None
def form_valid(self, form):
tar_io = io.BytesIO(self.request.FILES['bundle'].read())
tar = tarfile.open(fileobj=tar_io)
manifest = json.loads(tar.extractfile('manifest.json').read().decode())
if self.application and self.application.slug != manifest.get('slug'):
form.add_error(
'bundle', _('Can not update this application, wrong slug (%s).') % manifest.get('slug')
)
return self.form_invalid(form)
app, created = Application.objects.get_or_create(
slug=manifest.get('slug'), defaults={'name': manifest.get('application')}
)
@ -358,6 +364,21 @@ class Install(FormView):
install = Install.as_view()
class Update(Install):
template_name = 'hobo/applications/update.html'
def get_context_data(self, **kwargs):
kwargs['app'] = self.application
return super().get_context_data(**kwargs)
def dispatch(self, request, *args, **kwargs):
self.application = get_object_or_404(Application, slug=kwargs['app_slug'], editable=False)
return super().dispatch(request, *args, **kwargs)
update = Update.as_view()
class AppDeleteView(DeleteView):
model = Application
template_name = 'hobo/applications/app_confirm_delete.html'

View File

@ -783,7 +783,8 @@ def get_bundle(with_icon=False):
return tar_io.getvalue()
def test_deploy_application(app, admin_user, settings, app_bundle, app_bundle_with_icon):
@pytest.mark.parametrize('action', ['Install', 'Update'])
def test_deploy_application(app, admin_user, settings, app_bundle, app_bundle_with_icon, action):
Application.objects.all().delete()
Wcs.objects.create(base_url='https://wcs.example.invalid', slug='foobar', title='Foobar')
@ -800,8 +801,11 @@ def test_deploy_application(app, admin_user, settings, app_bundle, app_bundle_wi
login(app)
if action == 'Update':
Application.objects.create(name='Test', slug='test', editable=False)
def install(resp, bundle):
resp = resp.click('Install')
resp = resp.click(action)
resp.form['bundle'] = Upload('app.tar', bundle, 'application/x-tar')
with HTTMock(mocked_http):
resp = resp.form.submit().follow()
@ -827,6 +831,9 @@ def test_deploy_application(app, admin_user, settings, app_bundle, app_bundle_wi
return version
resp = app.get('/applications/')
if action == 'Update':
with HTTMock(mocked_http):
resp = resp.click(href='/manifest/test/')
version1 = install(resp, app_bundle)
assert version1.application.version_set.count() == 1
version2 = install(resp, app_bundle)
@ -854,7 +861,11 @@ def test_deploy_application(app, admin_user, settings, app_bundle, app_bundle_wi
return {'status_code': 500}
return mocked_http(url, request)
resp = app.get('/applications/install/')
resp = app.get('/applications/')
if action == 'Update':
with HTTMock(mocked_http):
resp = resp.click(href='manifest/test/')
resp = resp.click(action)
resp.form['bundle'] = Upload('app.tar', app_bundle, 'application/x-tar')
with HTTMock(response_content):
with pytest.raises(DeploymentError) as e:
@ -865,6 +876,36 @@ def test_deploy_application(app, admin_user, settings, app_bundle, app_bundle_wi
assert job.exception == 'Failed to deploy module wcs (500)'
def test_update_application(app, admin_user, settings, app_bundle):
Wcs.objects.create(base_url='https://wcs.example.invalid', slug='foobar', title='Foobar')
settings.KNOWN_SERVICES = {
'wcs': {
'foobar': {
'title': 'Foobar',
'url': 'https://wcs.example.invalid/',
'orig': 'example.org',
'secret': 'xxx',
}
}
}
login(app)
application = Application.objects.create(name='Test', slug='test', editable=True)
app.get('/applications/manifest/test/update/', status=404)
application.editable = False
application.slug = 'wrong'
application.save()
resp = app.get('/applications/manifest/wrong/update/')
resp.form['bundle'] = Upload('app.tar', app_bundle, 'application/x-tar')
resp = resp.form.submit()
assert resp.context['form'].errors == {'bundle': ['Can not update this application, wrong slug (test).']}
@pytest.fixture
def app_bundle_roles():
tar_io = io.BytesIO()