Commit 5571bb14 authored by Tristan Cavelier's avatar Tristan Cavelier

monitor: add default interface for promises

parent 425318c2
......@@ -56,7 +56,12 @@ md5sum = 2db5c08c7e8658981b4b1e3f27fd5967
[monitor-bin]
<= monitor-download-base
filename = monitor.py.in
md5sum = cc2f9c6b138ce11af9999ed58cd46799
md5sum = a3c673bbd37a98f160f8a10a8fb1b13a
[monitor-web-default-promise-interface]
<= monitor-download-base
filename = default-promise-interface.html
md5sum = 1d71746d4afcdc43d663ae8181190254
[monitor-web-index-html]
<= monitor-download-base
......@@ -89,12 +94,13 @@ recipe = slapos.recipe.template:jinja2
filename = template-monitor.cfg
template = ${:_profile_base_location_}/instance-monitor.cfg.jinja2.in
rendered = ${buildout:directory}/template-monitor.cfg
md5sum = 269962c742248a61a1ce3debdeb077aa
md5sum = 66d13e6e93369a38ff86b8e65abe1cee
context =
key apache_location apache:location
key gzip_location gzip:location
raw monitor_bin ${monitor-bin:location}/${monitor-bin:filename}
raw monitor_conf_template ${monitor-conf:location}/${monitor-conf:filename}
raw monitor_web_default_promise_interface ${monitor-web-default-promise-interface:location}/${monitor-web-default-promise-interface:filename}
raw monitor_web_index_html ${monitor-web-index-html:location}/${monitor-web-index-html:filename}
raw monitor_web_monitor_css ${monitor-web-monitor-css:location}/${monitor-web-monitor-css:filename}
raw monitor_web_monitor_logout_cgi ${monitor-web-monitor-logout-cgi:location}/${monitor-web-monitor-logout-cgi:filename}
......
<!DOCTYPE html>
<html>
<head>
<title>Promise status</title>
<script>
function getServiceName() {
var match = /(?:&|\?)service_name=([^&]*)/.exec(location.search);
if (match) {
return match[1];
}
throw new Error("no service name found");
}
var service_name = getServiceName(),
monitor_json_url = "/monitor.haljson",
status_json_url = "/public/" + service_name + "/status.json"; // XXX hardcoded
function newDeferred() {
var d = {
"promise": undefined,
"resolve": undefined,
"reject": undefined
};
d.promise = new Promise(function (resolve, reject) {
d.resolve = resolve;
d.reject = reject;
});
return d;
}
function xhr(param) {
/*global XMLHttpRequest */
var d = newDeferred(), xhr = new XMLHttpRequest(), k, i, l, a;
d.promise.cancel = function () { xhr.abort(); };
xhr.open((param.method || "GET").toUpperCase(), param.url, true);
xhr.responseType = param.responseType || "";
if (param.withCredentials !== undefined) {
xhr.withCredentials = param.withCredentials;
}
if (param.headers) {
a = Object.keys(param.headers);
l = a.length;
for (i = 0; i < l; i += 1) {
k = a[i];
xhr.setRequestHeader(k, param.headers[k]);
}
}
xhr.addEventListener("load", function (e) {
var r, t = e.target, callback;
if (param.noStatusCheck) {
d.resolve(t);
} else if (t.status < 400) {
d.resolve(t);
} else {
d.reject(new Error("HTTP: " + (t.status ? t.status + " " : "") + (t.statusText || "Unknown")));
}
}, false);
xhr.addEventListener("error", function (e) {
return d.reject(new Error("HTTP: Error"));
}, false);
xhr.addEventListener("abort", function (e) {
return d.reject(new Error("HTTP: Aborted"));
}, false);
xhr.send(param.data);
return d.promise;
}
function unexpectedError(reason) {
console.error(reason);
alert(reason);
}
function PromiseStatusInterface(config) {
var it = this,
statusP = document.createElement("p"),
descriptionH2 = document.createElement("h2"),
descriptionP = document.createElement("p"),
errorH2 = document.createElement("h2"),
errorPre = document.createElement("pre"),
header = document.createElement("header"),
h1 = document.createElement("h1"),
h2 = document.createElement("h2"),
a = document.createElement("a"),
button = document.createElement("button");
this.element = config.rootElement || document.createElement("div");
this.statusP = statusP;
this.descriptionP = descriptionP;
this.errorH2 = errorH2;
this.errorPre = errorPre;
this.element.appendChild(header);
header.appendChild(a);
a.setAttribute("tabindex", "-1");
a.setAttribute("href", "/");
a.appendChild(button);
button.textContent = "Home";
a = document.createElement("a");
button = document.createElement("button");
header.appendChild(a);
a.setAttribute("tabindex", "-1");
a.setAttribute("href", "");
a.appendChild(button);
button.textContent = "Refresh";
this.element.appendChild(h1);
h1.textContent = "Promise status";
this.element.appendChild(statusP);
this.element.appendChild(descriptionH2);
descriptionH2.textContent = "Description";
this.element.appendChild(descriptionP);
this.element.appendChild(errorH2);
errorH2.textContent = "Error output";
errorH2.style.display = "none";
this.element.appendChild(errorPre);
errorPre.style.display = "none";
this.loadStatusUi();
this.loadDescriptionUi();
this.loadErrorUi();
}
PromiseStatusInterface.prototype.loadStatusJson = function () {
if (this.status_json_promise) { return; }
this.status_json_promise = Promise.resolve().then(function () {
return xhr({url: status_json_url, withCredentials: true, responseType: "json"});
}).then(function (xhr) {
return xhr.response;
});
this.status_json_promise.catch(function () { return; }).then(function () {
setTimeout(function () {
delete this.status_json_promise;
}.bind(this), 1000);
}.bind(this));
return this.status_json_promise;
};
PromiseStatusInterface.prototype.loadStatusUi = function () {
this.loadStatusJson();
this.statusP.textContent = "Loading status...";
return this.status_json_promise.then(function (status_json) {
if (status_json.status === "OK") {
this.statusP.textContent = "Status: OK.";
} else {
this.statusP.textContent = "Status: BAD (" + status_json.status + ").";
}
if (status_json.message) {
this.statusP.appendChild(document.createTextNode(" " + status_json.message));
}
}.bind(this), function (reason) {
var message = reason && (reason.target && (reason.target.statusText || "Unknown") || reason.message);
this.statusP.textContent = "Status Json Error: " + (message || "Unknown error");
}.bind(this)).catch(unexpectedError);
};
PromiseStatusInterface.prototype.loadDescriptionUi = function () {
this.loadStatusJson();
this.descriptionP.textContent = "Loading description...";
return this.status_json_promise.then(function (status_json) {
if (status_json.description) {
this.descriptionP.textContent = status_json.description;
} else {
this.descriptionP.textContent = "No description";
}
}.bind(this), function (reason) {
var message = reason && (reason.target && (reason.target.statusText || "Unknown") || reason.message);
this.descriptionP.textContent = "Status Json Error: " + (message || "Unknown error");
}.bind(this)).catch(unexpectedError);
};
PromiseStatusInterface.prototype.loadErrorUi = function () {
this.loadStatusJson();
this.errorPre.textContent = "Loading error output...";
return this.status_json_promise.then(function (status_json) {
if (status_json.error) {
this.errorH2.style.display = "";
this.errorPre.style.display = "";
this.errorPre.textContent = status_json.error;
} else {
this.errorH2.style.display = "none";
this.errorPre.style.display = "none";
this.errorPre.textContent = "";
}
}.bind(this), function (reason) {
var message = reason && (reason.target && (reason.target.statusText || "Unknown") || reason.message);
this.errorPre.textContent = "Status Json Error: " + (message || "Unknown error");
}.bind(this)).catch(unexpectedError);
};
/*global setTimeout */
setTimeout(function () {
/*global document */
document.body.innerHTML = "";
return new PromiseStatusInterface({rootElement: document.body});
});
</script>
</head>
<body>
<h1>Promise status</h1>
<noscript>Javascript should be enabled</noscript>
</body>
</html>
......@@ -178,6 +178,12 @@ context =
key content :command
command = kill -USR1 $(cat ${monitor-httpd-conf-parameter:pid-file})
[monitor-web-default-promise-interface]
recipe = slapos.recipe.template:jinja2
template = {{ monitor_web_default_promise_interface }}
rendered = ${monitor-directory:web-dir}/default-promise-interface.html
context =
[monitor-web-index-html]
recipe = slapos.recipe.template:jinja2
template = {{ monitor_web_index_html }}
......@@ -263,6 +269,7 @@ monitor-title = Monitoring interface
[buildout]
parts =
monitor-web-default-promise-interface
monitor-web-index-html
monitor-web-monitor-css
monitor-web-monitor-js
......
......@@ -70,6 +70,8 @@ def main():
tmp = softConfigGet(service_config, "service", "interface-path")
if tmp:
service_dict["_links"]["interface"] = {"href": "/%s.html" % service_name} # XXX hardcoded
else:
service_dict["_links"]["interface"] = {"href": "/default-promise-interface.html?service_name=%s" % service_name} # XXX hardcoded
with open(config.get("monitor", "monitor-hal-json"), "w") as fp:
json.dump(monitor_dict, fp)
# create symlinks from service configurations
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment