diff --git a/tailbone/templates/upgrades/view.mako b/tailbone/templates/upgrades/view.mako
index 03fd9b6b..6a027921 100644
--- a/tailbone/templates/upgrades/view.mako
+++ b/tailbone/templates/upgrades/view.mako
@@ -38,6 +38,27 @@
% endif
%def>
+<%def name="render_this_page()">
+ ${parent.render_this_page()}
+
+ % if master.has_perm('execute'):
+ ${h.form(master.get_action_url('declare_failure', instance), ref='declareFailureForm')}
+ ${h.csrf_token(request)}
+ ${h.end_form()}
+ % endif
+%def>
+
+<%def name="render_buefy_form()">
+
+ <${form.component}
+ % if master.has_perm('execute'):
+ @declare-failure="declareFailure"
+ % endif
+ >
+ ${form.component}>
+
+%def>
+
<%def name="render_form_buttons()">
% if not instance.executed and instance.status_code == enum.UPGRADE_STATUS_PENDING and request.has_perm('{}.execute'.format(permission_prefix)):
@@ -81,6 +102,23 @@
this.formButtonText = "Working, please wait..."
}
+ % if master.has_perm('execute'):
+
+ TailboneFormData.declareFailureSubmitting = false
+
+ TailboneForm.methods.declareFailureClick = function() {
+ if (confirm("Really declare this upgrade a failure?")) {
+ this.declareFailureSubmitting = true
+ this.$emit('declare-failure')
+ }
+ }
+
+ ThisPage.methods.declareFailure = function() {
+ this.$refs.declareFailureForm.submit()
+ }
+
+ % endif
+
%def>
diff --git a/tailbone/views/upgrades.py b/tailbone/views/upgrades.py
index ff4de768..2e7c2fc4 100644
--- a/tailbone/views/upgrades.py
+++ b/tailbone/views/upgrades.py
@@ -162,7 +162,7 @@ class UpgradeView(MasterView):
f.remove_field('status_code')
else:
f.set_enum('status_code', self.enum.UPGRADE_STATUS)
- # f.set_readonly('status_code')
+ f.set_renderer('status_code', self.render_status_code)
# executing
if not self.editing:
@@ -205,6 +205,33 @@ class UpgradeView(MasterView):
f.remove_field('package_diff')
f.remove_field('exit_code')
+ def render_status_code(self, upgrade, field):
+ code = getattr(upgrade, field)
+ text = self.enum.UPGRADE_STATUS[code]
+
+ if self.get_use_buefy():
+ if code == self.enum.UPGRADE_STATUS_EXECUTING:
+
+ text = HTML.tag('span', c=[text])
+
+ button = HTML.tag('b-button',
+ type='is-warning',
+ icon_pack='fas',
+ icon_left='sad-tear',
+ c=['{{ declareFailureSubmitting ? "Working, please wait..." : "Declare Failure" }}'],
+ **{':disabled': 'declareFailureSubmitting',
+ '@click': 'declareFailureClick'})
+
+ return HTML.tag('div', class_='level', c=[
+ HTML.tag('div', class_='level-left', c=[
+ HTML.tag('div', class_='level-item', c=[text]),
+ HTML.tag('div', class_='level-item', c=[button]),
+ ]),
+ ])
+
+ # just show status per normal
+ return text
+
def configure_clone_form(self, f):
f.fields = ['description', 'notes', 'enabled']
@@ -446,23 +473,49 @@ class UpgradeView(MasterView):
return data
+ def declare_failure(self):
+ upgrade = self.get_instance()
+ if upgrade.executing and upgrade.status_code == self.enum.UPGRADE_STATUS_EXECUTING:
+ upgrade.executing = False
+ upgrade.status_code = self.enum.UPGRADE_STATUS_FAILED
+ self.request.session.flash("Upgrade was declared a failure.", 'warning')
+ else:
+ self.request.session.flash("Upgrade was not currently executing! "
+ "So it was not declared a failure.",
+ 'error')
+ return self.redirect(self.get_action_url('view', upgrade))
+
def delete_instance(self, upgrade):
self.handler.delete_files(upgrade)
super(UpgradeView, self).delete_instance(upgrade)
@classmethod
def defaults(cls, config):
+ cls._defaults(config)
+ cls._upgrade_defaults(config)
+
+ @classmethod
+ def _upgrade_defaults(cls, config):
route_prefix = cls.get_route_prefix()
- url_prefix = cls.get_url_prefix()
permission_prefix = cls.get_permission_prefix()
+ instance_url_prefix = cls.get_instance_url_prefix()
model_key = cls.get_model_key()
# execution progress
- config.add_route('{}.execute_progress'.format(route_prefix), '{}/{{{}}}/execute/progress'.format(url_prefix, model_key))
- config.add_view(cls, attr='execute_progress', route_name='{}.execute_progress'.format(route_prefix),
- permission='{}.execute'.format(permission_prefix), renderer='json')
+ config.add_route('{}.execute_progress'.format(route_prefix),
+ '{}/execute/progress'.format(instance_url_prefix))
+ config.add_view(cls, attr='execute_progress',
+ route_name='{}.execute_progress'.format(route_prefix),
+ permission='{}.execute'.format(permission_prefix),
+ renderer='json')
- cls._defaults(config)
+ # declare failure
+ config.add_route('{}.declare_failure'.format(route_prefix),
+ '{}/declare-failure'.format(instance_url_prefix),
+ request_method='POST')
+ config.add_view(cls, attr='declare_failure',
+ route_name='{}.declare_failure'.format(route_prefix),
+ permission='{}.execute'.format(permission_prefix))
def defaults(config, **kwargs):