Skip to content

Commit

Permalink
Show logs while deploying
Browse files Browse the repository at this point in the history
  • Loading branch information
Jonathan Curran committed Jan 7, 2019
1 parent 77d772e commit 667247a
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 32 deletions.
30 changes: 27 additions & 3 deletions rsconnect_jupyter/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from notebook.utils import url_path_join
from tornado import web

from .api import app_get, app_search, deploy, verify_server, RSConnectException
from .api import app_config, app_get, app_search, deploy, task_get, verify_server, RSConnectException
from .bundle import make_html_bundle, make_source_bundle

__version__ = '1.0.0'
Expand Down Expand Up @@ -122,11 +122,11 @@ def post(self, action):
raise web.HTTPError(400, 'Invalid app_mode: %s, must be "static" or "jupyter-static"' % app_mode)

try:
published_app = deploy(uri, api_key, app_id, nb_name, nb_title, bundle)
retval = deploy(uri, api_key, app_id, nb_name, nb_title, bundle)
except RSConnectException as exc:
raise web.HTTPError(400, exc.message)

self.finish(published_app)
self.finish(retval)
return

if action == 'app_get':
Expand Down Expand Up @@ -159,6 +159,30 @@ def post(self, action):
self.set_secure_cookie('key_' + address_hash, api_key, expires_days=3650)
return

if action == 'get_log':
uri = urlparse(data['server_address'])
api_key = data['api_key']
task_id = data['task_id']
last_status = data['last_status']
try:
retval = task_get(uri, api_key, task_id, last_status)
except RSConnectException as exc:
raise web.HTTPError(400, exc.message)
self.finish(json.dumps(retval))
return

if action == 'app_config':
uri = urlparse(data['server_address'])
api_key = data['api_key']
app_id = data['app_id']
try:
retval = app_config(uri, api_key, app_id)
except RSConnectException as exc:
raise web.HTTPError(400, exc.message)
self.finish(json.dumps(retval))
return



def load_jupyter_server_extension(nb_app):
nb_app.log.info("rsconnect_jupyter enabled!")
Expand Down
50 changes: 33 additions & 17 deletions rsconnect_jupyter/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,27 +244,43 @@ def deploy(uri, api_key, app_id, app_name, app_title, tarball):

app_bundle = api.app_upload(app['id'], tarball)
task_id = api.app_deploy(app['id'], app_bundle['id'])['id']
return {
'task_id': task_id,
'app_id': app['id'],
}

# 10 minute timeout
timeout = 600
task = wait_for_task(api, task_id, timeout)
# # 10 minute timeout
# timeout = 600
# task = wait_for_task(api, task_id, timeout)

if task is None:
raise RSConnectException('Deployment timed out')
# if task is None:
# raise RSConnectException('Deployment timed out')

if task['code'] != 0:
# app failed to deploy
err_msg = 'Failed to deploy successfully'
if 'error' in task:
err_msg += ': ' + task['error']
raise RSConnectException(err_msg)
# if task['code'] != 0:
# # app failed to deploy
# err_msg = 'Failed to deploy successfully'
# if 'error' in task:
# err_msg += ': ' + task['error']
# raise RSConnectException(err_msg)

# app deployed successfully
config = api.app_config(app['id'])
return {
'app_id': app['id'],
'config': config,
}
# # app deployed successfully
# config = api.app_config(app['id'])
# return {
# 'app_id': app['id'],
# 'config': config,
# }


def task_get(uri, api_key, task_id, last_status):
with RSConnect(uri, api_key) as api:
status = api.task_get(task_id, first_status=last_status)
logger.info('Deployment status for %s: %s' % (task_id, status))
return status


def app_config(uri, api_key, app_id):
with RSConnect(uri, api_key) as api:
return api.app_config(app_id)


APP_MODE_STATIC = 4
Expand Down
95 changes: 83 additions & 12 deletions rsconnect_jupyter/static/connect.js
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,14 @@ define([
var path = Jupyter.notebook.notebook_name;

try {
var cmd = ["!", Jupyter.notebook.kernel_selector.kernelspecs[Jupyter.notebook.kernel.name].spec.argv[0], " -m rsconnect_jupyter.environment ${PWD}/", path].join("");
var cmd = [
"!",
Jupyter.notebook.kernel_selector.kernelspecs[
Jupyter.notebook.kernel.name
].spec.argv[0],
" -m rsconnect_jupyter.environment ${PWD}/",
path
].join("");
console.log("executing: " + cmd);
} catch (e) {
return $.Deferred().reject(e);
Expand Down Expand Up @@ -296,6 +303,67 @@ define([

var entry = this.servers[serverId];

var $log = $("#rsc-log").attr("hidden", null);
$log.text("Deploying...\n");

function getLogs(deployResult) {
function inner(lastStatus) {
lastStatus = lastStatus || null;
return Utils.ajax({
url: Jupyter.notebook.base_url + "rsconnect_jupyter/get_log",
method: "POST",
headers: { "Content-Type": "application/json" },
data: JSON.stringify({
server_address: entry.server,
api_key: apiKey,
task_id: deployResult["task_id"],
last_status: lastStatus
})
}).then(function(result) {
if (result["last_status"] != lastStatus) {
lastStatus = result["lastStatus"];
var output = result["status"].join("\n");
$log.text(output);
// scroll to bottom
$log.scrollTop($log.get(0).scrollHeight);
}
if (result["finished"]) {
if (result["code"] != 0) {
return $.Deferred().reject(
"Failed to deploy successfully: " + result["error"]
);
}
debug.info("logs:", result["status"].join("\n"));
return $.Deferred().resolve(deployResult["app_id"]);
}
var next = $.Deferred();
setTimeout(function() {
return inner(lastStatus).then(next.resolve);
}, 1000);
return next;
});
}
return inner();
}

function appConfig(receivedAppId) {
return Utils.ajax({
url: Jupyter.notebook.base_url + "rsconnect_jupyter/app_config",
method: "POST",
headers: { "Content-Type": "application/json" },
data: JSON.stringify({
server_address: entry.server,
api_key: apiKey,
app_id: receivedAppId
})
}).then(function(config) {
return {
appId: receivedAppId,
config: config
};
});
}

function deploy(environment) {
var data = {
notebook_path: notebookPath,
Expand All @@ -313,18 +381,20 @@ define([
method: "POST",
headers: { "Content-Type": "application/json" },
data: JSON.stringify(data)
});
})
.then(getLogs)
.then(appConfig);

// update server with title and appId and set recently selected
// server
xhr.then(function(result) {
xhr.then(function(configResult) {
self.previousServerId = serverId;
return self.updateServer(
serverId,
result.app_id,
configResult.appId,
notebookTitle,
appMode,
result.config.config_url
configResult.config.config_url
);
});

Expand Down Expand Up @@ -763,18 +833,23 @@ define([
" <label>Publish Source Code</label>",
' <div class="list-group">',
' <a href="#" id="rsc-publish-with-source" class="list-group-item rsc-appmode" data-appmode="jupyter-static">',
' <img src="' + Jupyter.notebook.base_url + 'nbextensions/rsconnect_jupyter/images/publishDocWithSource.png" class="rsc-image">',
' <img src="' +
Jupyter.notebook.base_url +
'nbextensions/rsconnect_jupyter/images/publishDocWithSource.png" class="rsc-image">',
' <span class="rsc-label">Publish document with source code</span><br/>',
' <span class="rsc-text-light">Choose this option if you want to create a scheduled report or rebuild your document on the server</span>',
" </a>",
' <a href="#" id="rsc-publish-without-source" class="list-group-item rsc-appmode" data-appmode="static">',
' <img src="' + Jupyter.notebook.base_url + 'nbextensions/rsconnect_jupyter/images/publishDocWithoutSource.png" class="rsc-image">',
' <img src="' +
Jupyter.notebook.base_url +
'nbextensions/rsconnect_jupyter/images/publishDocWithoutSource.png" class="rsc-image">',
' <span class="rsc-label">Publish finished document only</span><br/>',
' <span class="rsc-text-light">Choose this option to publish a snapshot of the notebook as it appears in Jupyter</span>',
" </a>",
' <span class="help-block"></span>',
" </div>",
" </div>",
' <pre id="rsc-log" hidden></pre>',
' <div class="text-center" data-id="configUrl"></div>',
' <input type="submit" hidden>',
"</form>"
Expand Down Expand Up @@ -910,11 +985,7 @@ define([
}

function handleFailure(xhr) {
addValidationMarkup(
false,
txtTitle,
xhr.responseJSON.message
);
addValidationMarkup(false, txtTitle, xhr.responseJSON.message);
togglePublishButton(true);
}

Expand Down
7 changes: 7 additions & 0 deletions rsconnect_jupyter/static/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,10 @@
color: black;
padding-left: 10px;
}

#rsc-log {
height: 10rem;
margin-top: 1rem;
overflow-y: scroll;
overflow: break-word;
}

0 comments on commit 667247a

Please sign in to comment.