Skip to content
Snippets Groups Projects
Commit cc56423e authored by Mohamed, Fawzi Roberto (fawzi)'s avatar Mohamed, Fawzi Roberto (fawzi)
Browse files

WIP html templates

parent 62a80cee
Branches htmlTemplates
Tags
No related merge requests found
......@@ -36,7 +36,7 @@ function main() {
const stringify = require('json-stringify-safe');
logger.info(`Started with arguments ${stringify(args)}`)
logger.info(`Using configuration ${config.util.getEnv('NODE_ENV')} for instance ${process.env["NODE_APP_INSTANCE"]} ${stringify(config, null, 2)}`);
if (config.app.catchErrors) {
if (config.app.catchErrors || config.app.debug) {
process.on('uncaughtException', (err) => {
logger.error(`UncaughtException: ${stringify(err)}`)
})
......
......@@ -38,9 +38,11 @@ function guaranteeUserDir(userID, next) {
/// functions that either gives the running pod or starts it
function getOrCreatePod(podName, repl, shouldCreate, next) {
logger.debug(`enter getOrCreatePod ${podName}`)
k8.ns(config.k8component.namespace).pod.get(podName, function(err, result) {
if(err) {
if (shouldCreate) {
logger.debug(`creating ${podName}`)
components.templateForImage(repl, function(err, template, repl) {
if(err) {
logger.error(`Cannot start pod ${podName}, error in template generation: ${stringify(err)}`);
......@@ -49,8 +51,9 @@ function getOrCreatePod(podName, repl, shouldCreate, next) {
guaranteeUserDir(repl.user, function (){
const templateValue = yaml.safeLoad(template, 'utf8')
k8.ns(config.k8component.namespace).pod.post({ body: templateValue}, function(err, res2){
logger.debug(`created ${podName}`)
if(err) {
logger.error(`Cannot start pod ${podName}, error: ${stringify(err)}, \n====\ntemplate was ${template}\n====\nexpanded to\n${templateValue}\n====`);
logger.error(`Cannot start pod ${podName}, error: ${stringify(err)}, \n====\ntemplate was ${template}\n====\nconverted to\n${templateValue}\n====`);
next(err, null)
} else {
logger.info(`Created pod ${podName}: ${stringify(res2)}`)
......@@ -73,8 +76,8 @@ function getOrCreatePod(podName, repl, shouldCreate, next) {
// cache pod name -> host & port
const resolveCache = require('../safe-memory-cache/map.js')({
limit: config.resolveCacheNMax,
maxTTL: config.resolveCacheTtlMaxMs,
limit: config.app.resolveCacheNMax,
maxTTL: config.app.resolveCacheTtlMaxMs,
refreshF: function(key, value, cache) {
}
})
......@@ -108,22 +111,28 @@ function resolvePod(repl, next) {
resolveCache.set(podName, res)
next(null, res)
} else {
let secondsSinceCreation = (Date.parse(pod.metadata.creationTimestamp) - Date.now())/ 1000.0
const err = {
error: "not ready",
msg: "pod not yet ready",
status: pod.status,
host: podIp,
port: portNr
port: portNr,
pod: pod,
secondsSinceCreation: secondsSinceCreation
}
next(err, null)
}
} else {
let secondsSinceCreation = (Date.parse(pod.metadata.creationTimestamp) - Date.now())/ 1000.0
const err = {
error: "no ip",
msg: "ip not yet available",
status: pod.status,
host: podIp,
port: portNr
port: portNr,
pod: pod,
secondsSinceCreation: secondsSinceCreation
}
next(err, null)
}
......@@ -145,24 +154,40 @@ function resolvePod(repl, next) {
ProxyRouter.prototype.lookup = function(req, res, userID, isWebsocket, path, next) {
var start = Date.now()
components.cachedReplacements(req, function(err, repl) {
//logger.debug(`replacements available after ${(Date.now()-start)/1000.0}s`)
logger.debug(`replacements available after ${(Date.now()-start)/1000.0}s`)
if (err) {
logger.error(`No replacements: lookup without visiting the entry point ${config.k8component.entryPoint.path} (${stringify(err)})`)
logger.error(`no replacements for ${userID} in %{path}`)
res.send(500, components.getHtmlErrorTemplate({
error:"No replacements",
msg: `lookup without visiting the entry point ${config.k8component.entryPoint.path} (${stringify(err)})`
}))
} else {
resolvePod(repl, function (err, target) {
//logger.debug(`target available after ${(Date.now()-start)/1000.0}s`)
logger.debug(`target available after ${(Date.now()-start)/1000.0}s, err: ${stringify(err)} target: ${stringify(target)}`)
if (err) {
if (err.error === 'no ip' && err.status && err.status.phase === 'Pending' ||
err.error === 'not ready') {
logger.warn(`pod ${repl.podName} ${err.error} ${stringify(err)}`)
res.send(reloadMsg)
if ((err.error === 'no ip' || err.error === 'not ready') &&
err.status && err.status.phase === 'Pending') {
let error_detail = ''
if (!err.secondsSinceCreation || err.secondsSinceCreation > 10)
error_detail = stringify(err, null, 2)
logger.debug(`eval reload`)
let repl = {
refreshEachS: config.app.pageReloadTime,
error_detail: error_detail
}
logger.debug(`repl done ${stringify(repl)}`)
components.evalHtmlTemplate(
'reloadMsg.html', repl,
function(err, pageHtml) {
res.send(pageHtml)
})
return;
} else {
const errorMsg = `<html><head><title>Error starting Container!</title><meta http-equiv="refresh"<body><h3>Error ${err.error} while trying to start a container for you!</h3><p>${err.msg}</p><pre>${stringify(err, null, 2 )}</pre></body></html>`;
logger.error(`error starting container ${repl.podName}: ${stringify(err)}`)
res.send(500, errorMsg)
res.send(500, components.getHtmlErrorTemplate(err, "Error starting container"))
}
} else {
// logger.debug(`Resolved to ${stringify(target)} after ${(Date.now()-start)/1000.0}s`)
logger.debug(`Resolved to ${stringify(target)} after ${(Date.now()-start)/1000.0}s`)
next(target);
}
})
......
......@@ -10,6 +10,7 @@ const url = require('url');
const compact_sha = require('./compact-sha')
const logger = require('./logger')
const stringify = require('json-stringify-safe')
const yaml = require('js-yaml')
var baseRepl = {
baseDir: baseDir,
......@@ -139,20 +140,37 @@ function getHtmlErrorTemplate(err, context = '') {
// Helper to evaluate a web page template (layout + content)
// will *always* give an html as result (it there was an error it describe the error
function evalHtmlTemplate(htmlPath, repl, next, layout = null, context = '') {
const layout = repl.layout || "defaultTemplate.html"
evalTemplate("html/"+htmlPath, repl, function (err, template){
function evalHtmlTemplate(htmlPath, repl, next, { context = '' } = {} ) {
logger.debug('entered evalHtmlTemplate')
logger.debug(`entering evalHtmlTemplate(${stringify(htmlPath)}, ${stringify(repl)},...)`)
evalTemplate('html/'+htmlPath, repl, function (err, template){
logger.debug(`eval internal template err:${stringify(err)}, body:${stringify(template)}`)
if (err) {
logger.debug(`returning error`)
next(err, getHtmlErrorTemplate(err, context))
} else {
const repl2 = Object.assign({title: htmlPath, head: ''}, repl, { body: template })
evalHtmlTemplate("html/"+layout, repl2, function(err,res){
if (err) {
next(err, getHtmlErrorTemplate(err, context))
} else {
next(nil, res)
}
})
let extraRepl = {}
let templateBody = template
let m = /\B---\B/.exec(template)
if (m) {
templateBody = template.slice(m.index + 3)
extraRepl = yaml.safeLoad(template.slice(0, m.index), 'utf8')
}
logger.debug(`eval layout with extraRepl: ${stringify(extraRepl)} templateBody: ${stringify(templateBody)}`)
const repl2 = Object.assign({title: htmlPath, head: '', layout: "defaultLayout.html"}, extraRepl, repl, { body: templateBody })
const layout = repl2.layout
if (layout) {
evalTemplate("htmlLayout/"+layout, repl2, function(err,res){
logger.debug(`evaluated template, err: ${stringify(err)}`)
if (err) {
next(err, getHtmlErrorTemplate(err, context))
} else {
next(nil, res)
}
})
} else {
next(nil, templateBody)
}
}
})
}
......@@ -276,5 +294,7 @@ module.exports = {
cachedReplacements: cachedReplacements,
podNameForRepl: podNameForRepl,
infoForPodName: infoForPodName,
templateForImage: templateForImage
templateForImage: templateForImage,
getHtmlErrorTemplate: getHtmlErrorTemplate,
evalHtmlTemplate: evalHtmlTemplate
}
title: "Starting up!"
head: "<meta http-equiv=\"refresh\" content=\"{{refreshEachS}}\" >"
---
<h3>Please wait while we start a container for you!</h3>
<p>You might need to refresh manually (F5)...</p>p>
<pre>
{{error_detail}}
</pre>
......@@ -11,6 +11,7 @@ metadata:
spec:
imagePullSecrets:
- name: garching-kube
restartPolicy: Never
containers:
- image: "{{image}}"
name: "{{imageType}}"
......
......@@ -4,6 +4,7 @@ metadata:
name: {{podName}}
spec:
terminationGracePeriodSeconds: 5
restartPolicy: Never
containers:
- image: labdev-nomad.esc.rzg.mpg.de:5000/nomadlab/nomadvis:v1.0.7
name: nomadvis
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment