Refactor upgrade websocket progress, so "anyone" can join in to see
now while an upgrade is executing, anyone with permission can "view" the upgrade and see the same progress the executor is seeing
This commit is contained in:
parent
18cec49a86
commit
e93063a344
|
@ -40,6 +40,7 @@
|
|||
|
||||
<%def name="extra_styles()">
|
||||
${parent.extra_styles()}
|
||||
% if master.has_perm('execute'):
|
||||
<style type="text/css">
|
||||
.progress-with-textout {
|
||||
border: 1px solid Black;
|
||||
|
@ -48,65 +49,13 @@
|
|||
padding: 1rem;
|
||||
}
|
||||
</style>
|
||||
% 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()">
|
||||
<div class="form">
|
||||
<${form.component}
|
||||
% if master.has_perm('execute'):
|
||||
@declare-failure="declareFailure"
|
||||
% endif
|
||||
>
|
||||
</${form.component}>
|
||||
</div>
|
||||
</%def>
|
||||
|
||||
<%def name="render_form_buttons()">
|
||||
% if not instance.executed and instance.status_code == enum.UPGRADE_STATUS_PENDING and master.has_perm('execute'):
|
||||
<div class="buttons">
|
||||
% if instance.enabled and not instance.executing:
|
||||
% if use_buefy and expose_websockets:
|
||||
<b-button type="is-primary"
|
||||
icon-pack="fas"
|
||||
icon-left="arrow-circle-right"
|
||||
:disabled="upgradeExecuting"
|
||||
@click="executeUpgrade()">
|
||||
{{ upgradeExecuting ? "Working, please wait..." : "Execute this upgrade" }}
|
||||
</b-button>
|
||||
% elif use_buefy:
|
||||
${h.form(url('{}.execute'.format(route_prefix), uuid=instance.uuid), **{'@submit': 'submitForm'})}
|
||||
${h.csrf_token(request)}
|
||||
<b-button type="is-primary"
|
||||
native-type="submit"
|
||||
icon-pack="fas"
|
||||
icon-left="arrow-circle-right"
|
||||
:disabled="formSubmitting">
|
||||
{{ formSubmitting ? "Working, please wait..." : "Execute this upgrade" }}
|
||||
</b-button>
|
||||
${h.end_form()}
|
||||
% else:
|
||||
${h.form(url('{}.execute'.format(route_prefix), uuid=instance.uuid), class_='autodisable')}
|
||||
${h.csrf_token(request)}
|
||||
${h.submit('execute', "Execute this upgrade", class_='button is-primary')}
|
||||
${h.end_form()}
|
||||
% endif
|
||||
% elif instance.enabled:
|
||||
<button type="button" class="button is-primary" disabled="disabled" title="This upgrade is currently executing">Execute this upgrade</button>
|
||||
% else:
|
||||
<button type="button" class="button is-primary" disabled="disabled" title="This upgrade is not enabled">Execute this upgrade</button>
|
||||
% endif
|
||||
</div>
|
||||
|
||||
% if expose_websockets and master.has_perm('execute'):
|
||||
<b-modal :active.sync="upgradeExecuting"
|
||||
full-screen
|
||||
:can-cancel="false">
|
||||
|
@ -116,12 +65,15 @@
|
|||
<div class="level">
|
||||
<div class="level-item has-text-centered"
|
||||
style="display: flex; flex-direction: column;">
|
||||
<p class="block">Upgrading (please wait) ...</p>
|
||||
<p class="block">
|
||||
Upgrading (please wait) ...
|
||||
{{ executeUpgradeComplete ? "DONE!" : "" }}
|
||||
</p>
|
||||
<b-progress size="is-large"
|
||||
style="width: 400px;"
|
||||
## :value="80"
|
||||
## show-value
|
||||
## format="percent"
|
||||
## :value="80"
|
||||
## show-value
|
||||
## format="percent"
|
||||
>
|
||||
</b-progress>
|
||||
</div>
|
||||
|
@ -151,7 +103,64 @@
|
|||
</div>
|
||||
</div>
|
||||
</b-modal>
|
||||
% endif
|
||||
|
||||
% 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()">
|
||||
<div class="form">
|
||||
<${form.component}
|
||||
% if expose_websockets and master.has_perm('execute'):
|
||||
@execute-upgrade-click="executeUpgrade"
|
||||
:upgrade-executing="upgradeExecuting"
|
||||
@declare-failure-click="declareFailureClick"
|
||||
:declare-failure-submitting="declareFailureSubmitting"
|
||||
% endif
|
||||
>
|
||||
</${form.component}>
|
||||
</div>
|
||||
</%def>
|
||||
|
||||
<%def name="render_form_buttons()">
|
||||
% if instance_executable and master.has_perm('execute'):
|
||||
<div class="buttons">
|
||||
% if instance.enabled and not instance.executing:
|
||||
% if use_buefy and expose_websockets:
|
||||
<b-button type="is-primary"
|
||||
icon-pack="fas"
|
||||
icon-left="arrow-circle-right"
|
||||
:disabled="upgradeExecuting"
|
||||
@click="$emit('execute-upgrade-click')">
|
||||
{{ upgradeExecuting ? "Working, please wait..." : "Execute this upgrade" }}
|
||||
</b-button>
|
||||
% elif use_buefy:
|
||||
${h.form(url('{}.execute'.format(route_prefix), uuid=instance.uuid), **{'@submit': 'submitForm'})}
|
||||
${h.csrf_token(request)}
|
||||
<b-button type="is-primary"
|
||||
native-type="submit"
|
||||
icon-pack="fas"
|
||||
icon-left="arrow-circle-right"
|
||||
:disabled="formSubmitting">
|
||||
{{ formSubmitting ? "Working, please wait..." : "Execute this upgrade" }}
|
||||
</b-button>
|
||||
${h.end_form()}
|
||||
% else:
|
||||
${h.form(url('{}.execute'.format(route_prefix), uuid=instance.uuid), class_='autodisable')}
|
||||
${h.csrf_token(request)}
|
||||
${h.submit('execute', "Execute this upgrade", class_='button is-primary')}
|
||||
${h.end_form()}
|
||||
% endif
|
||||
% elif instance.enabled:
|
||||
<button type="button" class="button is-primary" disabled="disabled" title="This upgrade is currently executing">Execute this upgrade</button>
|
||||
% else:
|
||||
<button type="button" class="button is-primary" disabled="disabled" title="This upgrade is not enabled">Execute this upgrade</button>
|
||||
% endif
|
||||
</div>
|
||||
% endif
|
||||
</%def>
|
||||
|
||||
|
@ -165,29 +174,44 @@
|
|||
|
||||
% if expose_websockets:
|
||||
|
||||
TailboneFormData.upgradeExecuting = ${json.dumps(instance.executing)|n}
|
||||
TailboneFormData.progressOutput = []
|
||||
TailboneFormData.progressOutputCounter = 0
|
||||
ThisPageData.ws = null
|
||||
|
||||
TailboneForm.methods.executeUpgrade = function() {
|
||||
this.upgradeExecuting = true
|
||||
//////////////////////////////
|
||||
// execute upgrade
|
||||
//////////////////////////////
|
||||
|
||||
TailboneForm.props.upgradeExecuting = {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
}
|
||||
|
||||
ThisPageData.upgradeExecuting = false
|
||||
ThisPageData.progressOutput = []
|
||||
ThisPageData.progressOutputCounter = 0
|
||||
ThisPageData.executeUpgradeComplete = false
|
||||
|
||||
ThisPage.methods.adjustTextoutHeight = function() {
|
||||
|
||||
// grow the textout area to fill most of screen
|
||||
this.$nextTick(() => {
|
||||
let textout = this.$refs.textout
|
||||
let height = window.innerHeight - textout.offsetTop - 50
|
||||
textout.style.height = height + 'px'
|
||||
})
|
||||
}
|
||||
|
||||
let url = '${master.get_action_url('execute', instance)}'
|
||||
this.submitForm(url, {ws: true}, response => {
|
||||
ThisPage.methods.showExecuteDialog = function() {
|
||||
this.upgradeExecuting = true
|
||||
this.$nextTick(() => {
|
||||
this.adjustTextoutHeight()
|
||||
})
|
||||
}
|
||||
|
||||
ThisPage.methods.establishWebsocket = function() {
|
||||
|
||||
## TODO: should be a cleaner way to get this url?
|
||||
url = '${request.route_url('ws.upgrades.execution_progress', _query={'uuid': instance.uuid})}'
|
||||
url = url.replace(/^https?:/, 'wss:')
|
||||
|
||||
this.ws = new WebSocket(url)
|
||||
let that = this
|
||||
|
||||
## TODO: add support for this here?
|
||||
// this.ws.onclose = (event) => {
|
||||
|
@ -207,13 +231,16 @@
|
|||
if (data.complete) {
|
||||
|
||||
// upgrade has completed; reload page to view result
|
||||
this.executeUpgradeComplete = true
|
||||
this.$nextTick(() => {
|
||||
location.reload()
|
||||
})
|
||||
|
||||
} else if (data.stdout) {
|
||||
|
||||
// add lines to textout area
|
||||
that.progressOutput.push({
|
||||
key: ++that.progressOutputCounter,
|
||||
this.progressOutput.push({
|
||||
key: ++this.progressOutputCounter,
|
||||
text: data.stdout})
|
||||
|
||||
// scroll down to end of textout area
|
||||
|
@ -222,12 +249,36 @@
|
|||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
% if instance.executing:
|
||||
ThisPage.mounted = function() {
|
||||
this.showExecuteDialog()
|
||||
this.establishWebsocket()
|
||||
}
|
||||
% endif
|
||||
|
||||
% if instance_executable:
|
||||
|
||||
ThisPage.methods.executeUpgrade = function() {
|
||||
this.showExecuteDialog()
|
||||
|
||||
let url = '${master.get_action_url('execute', instance)}'
|
||||
this.submitForm(url, {ws: true}, response => {
|
||||
|
||||
this.establishWebsocket()
|
||||
})
|
||||
}
|
||||
|
||||
% endif
|
||||
|
||||
% else:
|
||||
## no websockets
|
||||
|
||||
//////////////////////////////
|
||||
// execute upgrade
|
||||
//////////////////////////////
|
||||
|
||||
TailboneFormData.formSubmitting = false
|
||||
|
||||
TailboneForm.methods.submitForm = function() {
|
||||
|
@ -236,18 +287,27 @@
|
|||
|
||||
% endif
|
||||
|
||||
TailboneFormData.declareFailureSubmitting = false
|
||||
//////////////////////////////
|
||||
// declare failure
|
||||
//////////////////////////////
|
||||
|
||||
TailboneForm.props.declareFailureSubmitting = {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
}
|
||||
|
||||
TailboneForm.methods.declareFailureClick = function() {
|
||||
if (confirm("Really declare this upgrade a failure?")) {
|
||||
this.declareFailureSubmitting = true
|
||||
this.$emit('declare-failure')
|
||||
}
|
||||
this.$emit('declare-failure-click')
|
||||
}
|
||||
|
||||
ThisPage.methods.declareFailure = function() {
|
||||
ThisPageData.declareFailureSubmitting = false
|
||||
|
||||
ThisPage.methods.declareFailureClick = function() {
|
||||
if (confirm("Really declare this upgrade a failure?")) {
|
||||
this.declareFailureSubmitting = true
|
||||
this.$refs.declareFailureForm.submit()
|
||||
}
|
||||
}
|
||||
|
||||
% endif
|
||||
|
||||
|
|
|
@ -1063,6 +1063,8 @@ class MasterView(View):
|
|||
'instance_deletable': self.deletable_instance(instance),
|
||||
'form': form,
|
||||
}
|
||||
if self.executable:
|
||||
context['instance_executable'] = self.executable_instance(instance)
|
||||
if hasattr(form, 'make_deform_form'):
|
||||
context['dform'] = form.make_deform_form()
|
||||
|
||||
|
@ -1784,6 +1786,14 @@ class MasterView(View):
|
|||
elif importer.allow_create:
|
||||
return importer.create_object(key, host_data)
|
||||
|
||||
def executable_instance(self, instance):
|
||||
"""
|
||||
Returns boolean indicating whether or not the given instance
|
||||
can be considered "executable". Returns ``True`` by default;
|
||||
override as necessary.
|
||||
"""
|
||||
return True
|
||||
|
||||
def execute(self):
|
||||
"""
|
||||
Execute an object.
|
||||
|
|
|
@ -475,6 +475,13 @@ class UpgradeView(MasterView):
|
|||
# key = '{}.execute'.format(self.get_grid_key())
|
||||
# return SessionProgress(self.request, key, session_type='file')
|
||||
|
||||
def executable_instance(self, upgrade):
|
||||
if upgrade.executed:
|
||||
return False
|
||||
if upgrade.status_code != self.enum.UPGRADE_STATUS_PENDING:
|
||||
return False
|
||||
return True
|
||||
|
||||
def execute_instance(self, upgrade, user, progress=None, **kwargs):
|
||||
app = self.get_rattail_app()
|
||||
session = app.get_session(upgrade)
|
||||
|
|
Loading…
Reference in a new issue