applications: add possibility to define parameters (#76463) #34
|
@ -0,0 +1,41 @@
|
|||
# Generated by Django 3.2.16 on 2023-04-10 15:53
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('applications', '0012_visible'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Parameter',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
('label', models.CharField(max_length=100, verbose_name='Label')),
|
||||
(
|
||||
'name',
|
||||
models.CharField(
|
||||
help_text='Variable name, it is useful to prefix it with an unique application identifier.',
|
||||
max_length=100,
|
||||
verbose_name='Identifier',
|
||||
),
|
||||
),
|
||||
(
|
||||
'default_value',
|
||||
models.CharField(blank=True, max_length=100, null=True, verbose_name='Default value'),
|
||||
),
|
||||
(
|
||||
'application',
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE, to='applications.application'
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
]
|
|
@ -30,6 +30,7 @@ from django.utils.text import slugify
|
|||
from django.utils.timezone import now
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from hobo.environment.models import Variable
|
||||
from hobo.environment.utils import get_installed_services
|
||||
|
||||
from .utils import Requests
|
||||
|
@ -206,6 +207,27 @@ class Application(models.Model):
|
|||
)
|
||||
|
||||
|
||||
class Parameter(models.Model):
|
||||
application = models.ForeignKey(Application, on_delete=models.CASCADE)
|
||||
label = models.CharField(max_length=100, verbose_name=_('Label'))
|
||||
name = models.CharField(
|
||||
max_length=100,
|
||||
verbose_name=_('Identifier'),
|
||||
help_text=_('Variable name, it is useful to prefix it with an unique application identifier.'),
|
||||
)
|
||||
default_value = models.CharField(max_length=100, verbose_name=_('Default value'), blank=True, null=True)
|
||||
|
||||
def as_dict(self):
|
||||
return {'label': self.label, 'name': self.name, 'default_value': self.default_value}
|
||||
|
||||
@property
|
||||
def variable(self):
|
||||
variable, _ = Variable.objects.get_or_create(
|
||||
name=self.name, defaults={'value': self.default_value or '', 'auto': True, 'label': self.label}
|
||||
)
|
||||
return variable
|
||||
|
||||
|
||||
class Element(models.Model):
|
||||
type = models.CharField(max_length=100, verbose_name=_('Type'))
|
||||
slug = models.SlugField(max_length=500, verbose_name=_('Slug'))
|
||||
|
@ -281,6 +303,7 @@ class Version(models.Model):
|
|||
'version_number': self.number,
|
||||
'version_notes': self.notes,
|
||||
'elements': [],
|
||||
'parameters': [x.as_dict() for x in self.application.parameter_set.all()],
|
||||
}
|
||||
|
||||
for element, relation in elements.values():
|
||||
|
@ -320,6 +343,7 @@ class Version(models.Model):
|
|||
|
||||
def deploy(self, job=None):
|
||||
bundle_content = self.bundle.read()
|
||||
self.deploy_parameters(bundle_content)
|
||||
self.deploy_roles(bundle_content)
|
||||
self.do_something_with_bundle(bundle_content, 'deploy', job=job)
|
||||
self.application.refresh_elements(cache_only=True)
|
||||
|
@ -365,6 +389,24 @@ class Version(models.Model):
|
|||
return service
|
||||
return None
|
||||
|
||||
def deploy_parameters(self, bundle):
|
||||
tar_io = io.BytesIO(bundle)
|
||||
with tarfile.open(fileobj=tar_io) as tar:
|
||||
manifest = json.loads(tar.extractfile('manifest.json').read().decode())
|
||||
for parameter in manifest.get('parameters') or []:
|
||||
param, _ = Parameter.objects.get_or_create(
|
||||
name=parameter.get('name'), application=self.application
|
||||
)
|
||||
param.label = parameter.get('label')
|
||||
param.default_value = parameter.get('default_value')
|
||||
param.save()
|
||||
variable, _ = Variable.objects.get_or_create(
|
||||
name=parameter.get('name'),
|
||||
defaults={'auto': True, 'value': parameter.get('default_value') or ''},
|
||||
)
|
||||
variable.label = parameter.get('label')
|
||||
variable.save()
|
||||
|
||||
def deploy_roles(self, bundle):
|
||||
tar_io = io.BytesIO(bundle)
|
||||
service = self.get_authentic_service()
|
||||
|
|
|
@ -76,5 +76,38 @@
|
|||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% with has_parameters=app.parameter_set.exists parameters_qs=app.parameter_set.all %}
|
||||
{% if app.editable or has_parameters %}
|
||||
<div class="app-parameters--section">
|
||||
<h3>{% trans "Parameters" %}
|
||||
{% if app.editable %}
|
||||
<a rel="popup" href="{% url 'application-add-parameter' app_slug=app.slug %}">({% trans "add" %})</a>
|
||||
{% endif %}
|
||||
</h3>
|
||||
{% if app.editable and has_parameters %}
|
||||
<ul class="objects-list single-links app-parameters--list">
|
||||
{% for parameter in parameters_qs %}
|
||||
<li><a rel="popup" href="{% url 'application-edit-parameter' app_slug=app.slug pk=parameter.id %}">{{ parameter.label }}</a>
|
||||
<a rel="popup" class="delete" href="{% url 'application-delete-parameter' app_slug=app.slug pk=parameter.id %}">{% trans "remove" %}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% elif app.editable %}
|
||||
<p>{% trans "No parameters defined." %}</p>
|
||||
{% endif %}
|
||||
{% if has_parameters %}
|
||||
|
||||
<div class="app-parameters--values">
|
||||
{% for parameter in parameters_qs %}
|
||||
lguerin
commented
potentiellement 2 fois le meme qs que ligne 89 potentiellement 2 fois le meme qs que ligne 89
fpeters
commented
Je l'ai posé dans le {% with %} pour que ça soit partagé, en imaginant que ça permet ainsi d'économiser la requête. Je l'ai posé dans le {% with %} pour que ça soit partagé, en imaginant que ça permet ainsi d'économiser la requête.
|
||||
<p>
|
||||
<label>{{ parameter.label }}</label>
|
||||
{{ parameter.variable.value|default:"-" }}
|
||||
(<a rel="popup" href="{% url 'application-change-parameter-value' app_slug=app.slug name=parameter.variable.name %}">{% trans 'change' %}</a>)
|
||||
</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
</aside>
|
||||
{% endblock %}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
{% extends "hobo/applications/home.html" %}
|
||||
{% load gadjo i18n %}
|
||||
|
||||
{% block appbar %}
|
||||
<h2>{% trans "New Parameter" %}</h2>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
{{ form|with_template }}
|
||||
<div class="buttons">
|
||||
<button class="submit-button">{% trans "Add" %}</button>
|
||||
<a class="cancel" href="..">{% trans "Cancel" %}</a>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -0,0 +1,20 @@
|
|||
{% extends "hobo/applications/home.html" %}
|
||||
{% load gadjo i18n %}
|
||||
|
||||
{% block appbar %}
|
||||
<h2>{% trans "Delete Parameter" %}</h2>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
<p>
|
||||
{% trans 'Are you sure you want to remove this parameter?' %}
|
||||
</p>
|
||||
<div class="buttons">
|
||||
<button class="delete-button">{% trans "Delete" %}</button>
|
||||
<a class="cancel" href="../../">{% trans "Cancel" %}</a>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
{% extends "hobo/applications/home.html" %}
|
||||
{% load gadjo i18n %}
|
||||
|
||||
{% block appbar %}
|
||||
<h2>{% trans "Edit Parameter" %}</h2>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
{{ form|with_template }}
|
||||
<div class="buttons">
|
||||
<button class="submit-button">{% trans "Save" %}</button>
|
||||
<a class="cancel" href="../../">{% trans "Cancel" %}</a>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -0,0 +1,17 @@
|
|||
{% extends "hobo/applications/home.html" %}
|
||||
{% load gadjo i18n %}
|
||||
|
||||
{% block appbar %}
|
||||
<h2>{% trans "Edit Parameter" %}</h2>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
{{ form|with_template }}
|
||||
<div class="buttons">
|
||||
<button class="submit-button">{% trans "Save" %}</button>
|
||||
<a class="cancel" href="../../">{% trans "Cancel" %}</a>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -45,6 +45,26 @@ urlpatterns = [
|
|||
views.delete_element,
|
||||
name='application-delete-element',
|
||||
),
|
||||
re_path(
|
||||
r'^manifest/(?P<app_slug>[\w-]+)/add-parameter/$',
|
||||
views.add_parameter,
|
||||
name='application-add-parameter',
|
||||
),
|
||||
re_path(
|
||||
r'^manifest/(?P<app_slug>[\w-]+)/edit-parameter/(?P<pk>\d+)/$',
|
||||
views.edit_parameter,
|
||||
name='application-edit-parameter',
|
||||
),
|
||||
re_path(
|
||||
r'^manifest/(?P<app_slug>[\w-]+)/delete-parameter/(?P<pk>\d+)/$',
|
||||
views.delete_parameter,
|
||||
name='application-delete-parameter',
|
||||
),
|
||||
re_path(
|
||||
r'^manifest/(?P<app_slug>[\w-]+)/parameter-value/(?P<name>[\w_]+)/$',
|
||||
views.change_parameter_value,
|
||||
name='application-change-parameter-value',
|
||||
),
|
||||
re_path(
|
||||
r'^manifest/(?P<app_slug>[\w-]+)/job/(?P<pk>\d+)/$',
|
||||
views.async_job,
|
||||
|
|
|
@ -31,12 +31,15 @@ from django.utils.translation import gettext_lazy as _
|
|||
from django.views.generic import DetailView, FormView, ListView, TemplateView
|
||||
from django.views.generic.edit import CreateView, DeleteView, UpdateView
|
||||
|
||||
from hobo.environment.models import Variable
|
||||
|
||||
from .forms import GenerateForm, InstallForm, MetadataForm
|
||||
from .models import (
|
||||
STATUS_CHOICES,
|
||||
Application,
|
||||
AsyncJob,
|
||||
Element,
|
||||
Parameter,
|
||||
Relation,
|
||||
UnlinkError,
|
||||
Version,
|
||||
|
@ -451,3 +454,74 @@ class AsyncJobView(DetailView):
|
|||
|
||||
|
||||
async_job = AsyncJobView.as_view()
|
||||
|
||||
|
||||
class AddParameterView(CreateView):
|
||||
template_name = 'hobo/applications/parameter-add.html'
|
||||
model = Parameter
|
||||
fields = ['label', 'name', 'default_value']
|
||||
|
||||
def dispatch(self, *args, **kwargs):
|
||||
self.application = get_object_or_404(Application, slug=kwargs['app_slug'], editable=True)
|
||||
lguerin
commented
j'aurais bien ajouté editable=True au qs :) j'aurais bien ajouté editable=True au qs :)
(et get_object_or_404 permet d'éviter une 500, au cas où)
fpeters
commented
Voilà, passé à get_object_or_404 + editable=True. Voilà, passé à get_object_or_404 + editable=True.
|
||||
return super().dispatch(*args, **kwargs)
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.application = self.application
|
||||
return super().form_valid(form)
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse('application-manifest', kwargs={'app_slug': self.kwargs['app_slug']})
|
||||
|
||||
|
||||
lguerin
commented
là aussi, restriction sur Application editable=True ? là aussi, restriction sur Application editable=True ?
fpeters
commented
Fait, différemment ici,
Fait, différemment ici,
```
+ def get_queryset(self):
+ return (
+ super()
+ .get_queryset()
+ .filter(application__editable=True, application__slug=self.kwargs['app_slug'])
+ )
```
|
||||
add_parameter = AddParameterView.as_view()
|
||||
|
||||
|
||||
class EditParameterView(UpdateView):
|
||||
template_name = 'hobo/applications/parameter-edit.html'
|
||||
model = Parameter
|
||||
fields = ['label', 'name', 'default_value']
|
||||
|
||||
def get_queryset(self):
|
||||
return (
|
||||
super()
|
||||
.get_queryset()
|
||||
lguerin
commented
idem editable = True idem editable = True
fpeters
commented
Fait de la même manière que l'update. Fait de la même manière que l'update.
|
||||
.filter(application__editable=True, application__slug=self.kwargs['app_slug'])
|
||||
)
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse('application-manifest', kwargs={'app_slug': self.kwargs['app_slug']})
|
||||
|
||||
|
||||
edit_parameter = EditParameterView.as_view()
|
||||
|
||||
|
||||
class DeleteParameterView(DeleteView):
|
||||
template_name = 'hobo/applications/parameter-confirm-delete.html'
|
||||
model = Parameter
|
||||
|
||||
def get_queryset(self):
|
||||
return (
|
||||
super()
|
||||
.get_queryset()
|
||||
.filter(application__editable=True, application__slug=self.kwargs['app_slug'])
|
||||
)
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse('application-manifest', kwargs={'app_slug': self.kwargs['app_slug']})
|
||||
|
||||
|
||||
delete_parameter = DeleteParameterView.as_view()
|
||||
|
||||
|
||||
class ChangeParameterValueView(UpdateView):
|
||||
template_name = 'hobo/applications/parameter-value-edit.html'
|
||||
model = Variable
|
||||
fields = ['value']
|
||||
slug_field = 'name'
|
||||
slug_url_kwarg = 'name'
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse('application-manifest', kwargs={'app_slug': self.kwargs['app_slug']})
|
||||
|
||||
|
||||
change_parameter_value = ChangeParameterValueView.as_view()
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: hobo 0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-04-21 10:25+0200\n"
|
||||
"PO-Revision-Date: 2023-04-17 18:00+0200\n"
|
||||
"POT-Creation-Date: 2023-05-30 08:34+0200\n"
|
||||
"PO-Revision-Date: 2023-05-30 08:36+0200\n"
|
||||
"Last-Translator: Frederic Peters <fpeters@entrouvert.com>\n"
|
||||
"Language: French\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -84,6 +84,26 @@ msgstr ""
|
|||
msgid "Failed to unlink application in module %s (%s)"
|
||||
msgstr "Erreur lors de la déliaison dans le module %s (%s)"
|
||||
|
||||
#: hobo/applications/models.py
|
||||
msgid "Label"
|
||||
msgstr "Libellé"
|
||||
|
||||
#: hobo/applications/models.py
|
||||
msgid "Identifier"
|
||||
msgstr "Identifiant"
|
||||
|
||||
#: hobo/applications/models.py
|
||||
msgid ""
|
||||
"Variable name, it is useful to prefix it with an unique application "
|
||||
"identifier."
|
||||
msgstr ""
|
||||
"Nom de variable, il peut être utile de le préfixer par un identifiant "
|
||||
"spécifique à l’application."
|
||||
|
||||
#: hobo/applications/models.py
|
||||
msgid "Default value"
|
||||
msgstr "Valeur par défaut"
|
||||
|
||||
#: hobo/applications/models.py
|
||||
msgid "Type"
|
||||
msgstr "Type"
|
||||
|
@ -150,6 +170,7 @@ msgstr "Filtrer :"
|
|||
|
||||
#: hobo/applications/templates/hobo/applications/add-element.html
|
||||
#: hobo/applications/templates/hobo/applications/manifest.html
|
||||
#: hobo/applications/templates/hobo/applications/parameter-add.html
|
||||
msgid "Add"
|
||||
msgstr "Ajouter"
|
||||
|
||||
|
@ -160,6 +181,10 @@ msgstr "Ajouter"
|
|||
#: hobo/applications/templates/hobo/applications/element_confirm_delete.html
|
||||
#: hobo/applications/templates/hobo/applications/generate.html
|
||||
#: hobo/applications/templates/hobo/applications/install.html
|
||||
#: hobo/applications/templates/hobo/applications/parameter-add.html
|
||||
#: hobo/applications/templates/hobo/applications/parameter-confirm-delete.html
|
||||
#: hobo/applications/templates/hobo/applications/parameter-edit.html
|
||||
#: hobo/applications/templates/hobo/applications/parameter-value-edit.html
|
||||
#: hobo/applications/templates/hobo/applications/update.html
|
||||
#: hobo/matomo/templates/hobo/matomo_disable.html
|
||||
#: hobo/matomo/templates/hobo/matomo_enable_auto.html
|
||||
|
@ -188,6 +213,7 @@ msgstr "Ses composants ne seront pas désinstallés."
|
|||
#: hobo/applications/templates/hobo/applications/app_confirm_delete.html
|
||||
#: hobo/applications/templates/hobo/applications/element_confirm_delete.html
|
||||
#: hobo/applications/templates/hobo/applications/manifest.html
|
||||
#: hobo/applications/templates/hobo/applications/parameter-confirm-delete.html
|
||||
msgid "Delete"
|
||||
msgstr "Supprimer"
|
||||
|
||||
|
@ -289,6 +315,50 @@ msgstr ""
|
|||
"Vous pouvez maintenant assembler les différents éléments de votre "
|
||||
"application."
|
||||
|
||||
#: hobo/applications/templates/hobo/applications/manifest.html
|
||||
msgid "Parameters"
|
||||
msgstr "Paramètres"
|
||||
|
||||
#: hobo/applications/templates/hobo/applications/manifest.html
|
||||
msgid "add"
|
||||
msgstr "ajouter"
|
||||
|
||||
#: hobo/applications/templates/hobo/applications/manifest.html
|
||||
msgid "No parameters defined."
|
||||
msgstr "Pas de paramètres définis."
|
||||
|
||||
#: hobo/applications/templates/hobo/applications/manifest.html
|
||||
msgid "change"
|
||||
msgstr "modifier"
|
||||
|
||||
#: hobo/applications/templates/hobo/applications/parameter-add.html
|
||||
msgid "New Parameter"
|
||||
msgstr "Nouveau paramètre"
|
||||
|
||||
#: hobo/applications/templates/hobo/applications/parameter-confirm-delete.html
|
||||
msgid "Delete Parameter"
|
||||
msgstr "Suppression du paramètre"
|
||||
|
||||
#: hobo/applications/templates/hobo/applications/parameter-confirm-delete.html
|
||||
msgid "Are you sure you want to remove this parameter?"
|
||||
msgstr "Êtes-vous sûr·e de vouloir supprimer ce paramètre ?"
|
||||
|
||||
#: hobo/applications/templates/hobo/applications/parameter-edit.html
|
||||
#: hobo/applications/templates/hobo/applications/parameter-value-edit.html
|
||||
msgid "Edit Parameter"
|
||||
msgstr "Modification de paramètre"
|
||||
|
||||
#: hobo/applications/templates/hobo/applications/parameter-edit.html
|
||||
#: hobo/applications/templates/hobo/applications/parameter-value-edit.html
|
||||
#: hobo/debug/templates/hobo/debug_home.html
|
||||
#: hobo/matomo/templates/hobo/matomo_home.html
|
||||
#: hobo/profile/templates/profile/attributedefinition_form.html
|
||||
#: hobo/profile/templates/profile/edit_full_name_template.html
|
||||
#: hobo/seo/templates/hobo/robots_txt.html
|
||||
#: hobo/seo/templates/hobo/seo_home.html
|
||||
msgid "Save"
|
||||
msgstr "Enregistrer"
|
||||
|
||||
#: hobo/applications/templates/hobo/applications/versions.html
|
||||
msgid "Versions"
|
||||
msgstr "Versions"
|
||||
|
@ -359,15 +429,6 @@ msgstr "Liste des adresses IP pour lesquelles activer le débogage"
|
|||
msgid "Debugging"
|
||||
msgstr "Débogage"
|
||||
|
||||
#: hobo/debug/templates/hobo/debug_home.html
|
||||
#: hobo/matomo/templates/hobo/matomo_home.html
|
||||
#: hobo/profile/templates/profile/attributedefinition_form.html
|
||||
#: hobo/profile/templates/profile/edit_full_name_template.html
|
||||
#: hobo/seo/templates/hobo/robots_txt.html
|
||||
#: hobo/seo/templates/hobo/seo_home.html
|
||||
msgid "Save"
|
||||
msgstr "Enregistrer"
|
||||
|
||||
#: hobo/debug/templates/hobo/debug_home.html
|
||||
msgid "Remove current IP"
|
||||
msgstr "Retirer votre adresse IP actuelle"
|
||||
|
|
|
@ -381,3 +381,8 @@ ul.objects-list.application-content {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
div.app-parameters--values label {
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
|
|
@ -17,11 +17,12 @@ from hobo.applications.models import (
|
|||
AsyncJob,
|
||||
DeploymentError,
|
||||
Element,
|
||||
Parameter,
|
||||
Relation,
|
||||
ScanError,
|
||||
Version,
|
||||
)
|
||||
from hobo.environment.models import Authentic, Wcs
|
||||
from hobo.environment.models import Authentic, Variable, Wcs
|
||||
|
||||
pytestmark = pytest.mark.django_db
|
||||
|
||||
|
@ -822,6 +823,10 @@ def get_bundle(with_icon=False):
|
|||
'auto-dependency': True,
|
||||
},
|
||||
],
|
||||
'parameters': [
|
||||
{'name': 'app_param1', 'label': 'Parameter 1', 'default_value': 'plop'},
|
||||
{'name': 'app_param2', 'label': 'Parameter 2', 'default_value': None},
|
||||
],
|
||||
}
|
||||
manifest_fd = io.BytesIO(json.dumps(manifest_json, indent=2).encode())
|
||||
tarinfo = tarfile.TarInfo('manifest.json')
|
||||
|
@ -883,6 +888,8 @@ def test_deploy_application(app, admin_user, settings, app_bundle, app_bundle_wi
|
|||
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
|
||||
return version
|
||||
|
||||
resp = app.get('/applications/')
|
||||
|
@ -1247,3 +1254,112 @@ def test_job_status_page(app, admin_user, settings):
|
|||
job.refresh_from_db()
|
||||
assert job.status == 'failed'
|
||||
assert job.exception == 'Failed to deploy module wcs'
|
||||
|
||||
|
||||
def test_create_application_parameters(app, admin_user, settings):
|
||||
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)
|
||||
|
||||
resp = app.get('/applications/')
|
||||
resp = resp.click('Create')
|
||||
resp.form['name'] = 'Test'
|
||||
resp = resp.form.submit()
|
||||
|
||||
with HTTMock(mocked_http):
|
||||
resp = resp.follow()
|
||||
|
||||
# add a form (an element is required to have the generate app button)
|
||||
resp = resp.click('Forms')
|
||||
resp.form.fields['elements'][4].checked = True
|
||||
resp = resp.form.submit().follow()
|
||||
|
||||
assert resp.pyquery('.app-parameters--section h3 a')
|
||||
resp = resp.click('add')
|
||||
resp.form['label'] = 'Foo'
|
||||
resp.form['name'] = 'app_foo'
|
||||
resp.form['default_value'] = 'xxx'
|
||||
resp = resp.form.submit().follow()
|
||||
assert Parameter.objects.filter(name='app_foo').exists()
|
||||
assert resp.pyquery('.app-parameters--list li')
|
||||
resp = resp.click(href=resp.pyquery('.app-parameters--list li a:not(.delete)').attr.href)
|
||||
assert resp.form['label'].value == 'Foo'
|
||||
assert resp.form['name'].value == 'app_foo'
|
||||
assert resp.form['default_value'].value == 'xxx'
|
||||
resp = resp.click('Cancel')
|
||||
|
||||
resp = resp.click(href=resp.pyquery('.app-parameters--values a').attr.href)
|
||||
assert resp.form['value'].value == 'xxx'
|
||||
resp.form['value'] = 'changed'
|
||||
resp = resp.form.submit().follow()
|
||||
assert Variable.objects.get(name='app_foo').value == 'changed'
|
||||
|
||||
resp = resp.click('Generate application bundle')
|
||||
resp.form['number'] = '1.0'
|
||||
resp.form['notes'] = 'Foo bar blah.'
|
||||
resp = resp.form.submit().follow()
|
||||
resp_download = resp.click('Download')
|
||||
assert resp_download.content_type == 'application/x-tar'
|
||||
# uncompressed tar, primitive check of contents
|
||||
assert b'app_foo' in resp_download.content
|
||||
|
||||
resp = resp.click(href=resp.pyquery('.app-parameters--list li a.delete').attr.href)
|
||||
resp = resp.form.submit().follow()
|
||||
assert not Parameter.objects.filter(name='app_foo').exists()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def app_bundle_parameters():
|
||||
tar_io = io.BytesIO()
|
||||
with tarfile.open(mode='w', fileobj=tar_io) as tar:
|
||||
manifest_json = {
|
||||
'application': 'Test',
|
||||
'slug': 'test',
|
||||
'description': '',
|
||||
'elements': [],
|
||||
'parameters': [{"label": "Foo", "name": "app_foo", "default_value": "xxx"}],
|
||||
}
|
||||
manifest_fd = io.BytesIO(json.dumps(manifest_json, indent=2).encode())
|
||||
tarinfo = tarfile.TarInfo('manifest.json')
|
||||
tarinfo.size = len(manifest_fd.getvalue())
|
||||
tar.addfile(tarinfo, fileobj=manifest_fd)
|
||||
return tar_io.getvalue()
|
||||
|
||||
|
||||
def test_deploy_application_parameters(app, admin_user, settings, app_bundle_parameters):
|
||||
Parameter.objects.all().delete()
|
||||
Variable.objects.all().delete()
|
||||
Application.objects.all().delete()
|
||||
|
||||
login(app)
|
||||
|
||||
resp = app.get('/applications/')
|
||||
resp = resp.click('Install')
|
||||
resp.form['bundle'] = Upload('app.tar', app_bundle_parameters, 'application/x-tar')
|
||||
resp = resp.form.submit().follow()
|
||||
assert Variable.objects.get(name='app_foo').value == 'xxx'
|
||||
resp = resp.click('Details')
|
||||
assert resp.pyquery('.app-parameters--section h3')
|
||||
assert not resp.pyquery('.app-parameters--section h3 a')
|
||||
|
||||
resp = resp.click(href=resp.pyquery('.app-parameters--values a').attr.href)
|
||||
assert resp.form['value'].value == 'xxx'
|
||||
resp.form['value'] = 'changed'
|
||||
resp = resp.form.submit().follow()
|
||||
assert Variable.objects.get(name='app_foo').value == 'changed'
|
||||
|
||||
# check parameter cannot be edited or deleted
|
||||
parameter = Parameter.objects.all().first()
|
||||
resp = app.get(f'/applications/manifest/test/edit-parameter/{parameter.id}/', status=404)
|
||||
resp = app.get(f'/applications/manifest/test/delete-parameter/{parameter.id}/', status=404)
|
||||
|
|
Loading…
Reference in New Issue
has_parameters ?
Oui, modifié. (j'ai mis toutes les modifications dans un commit séparé, pour mieux les voir).