software/theia: Add switch-softwaretype
This defers the rendering of `instance-theia.cfg.in` to the instance creation time instead of the software installation time, which will allow buildout sections to be added based on the instance parameters. See merge request !981
Showing
[buildout] | |||
extends = | |||
${monitor-template:rendered} | |||
theia-environment-parts = | |||
tasks.json | |||
slapos-repository | |||
runner-link | |||
settings.json | |||
request-script-template | |||
theia-parts = | |||
frontend-reload | |||
promises | |||
parts = | |||
monitor-base | |||
$${:theia-parts} | |||
$${:theia-environment-parts} | |||
publish-connection-parameter | |||
eggs-directory = ${buildout:eggs-directory} | |||
develop-eggs-directory = ${buildout:develop-eggs-directory} | |||
offline = true | |||
[instance-parameter] | |||
{% for k, v in slapconfiguration_section.items() -%} | |||
{{ k }} = {{ v }} | |||
{% endfor -%} | |||
[publish-connection-parameter] | |||
<= monitor-publish | |||
recipe = slapos.cookbook:publish | |||
url = $${apache-frontend:connection-secure_access} | |||
username = $${frontend-instance-password:username} | |||
password = $${frontend-instance-password:passwd} | |||
backend-url = $${frontend-instance:url} | |||
[directory] | |||
recipe = slapos.cookbook:mkdirectory | |||
etc = $${buildout:directory}/etc | |||
var = $${buildout:directory}/var | |||
srv = $${buildout:directory}/srv | |||
bin = $${buildout:directory}/bin | |||
tmp = $${buildout:directory}/tmp | |||
dot-theia = $${buildout:directory}/.theia/ | |||
pidfiles = $${:var}/run | |||
services = $${:etc}/service | |||
runner = $${:srv}/runner | |||
project = $${:srv}/project | |||
frontend-static = $${:srv}/frontend-static | |||
frontend-static-public = $${:frontend-static}/public | |||
frontend-static-css = $${:frontend-static}/css | |||
bash-completions = $${buildout:directory}/.local/share/bash-completion/completions/ | |||
fish-completions = $${buildout:directory}/.config/fish/completions/ | |||
# Promises | |||
# -------- | |||
[promises] | |||
recipe = | |||
instance-promises = | |||
$${theia-listen-promise:name} | |||
$${frontend-listen-promise:name} | |||
$${apache-frontend-url-available-promise:name} | |||
$${slapos-standalone-listen-promise:name} | |||
$${slapos-autorun-promise:name} | |||
[theia-listen-promise] | |||
<= monitor-promise-base | |||
module = check_port_listening | |||
name = $${:_buildout_section_name_}.py | |||
config-hostname = $${theia-instance:ip} | |||
config-port = $${theia-instance:port} | |||
[frontend-listen-promise] | |||
<= monitor-promise-base | |||
module = check_port_listening | |||
name = $${:_buildout_section_name_}.py | |||
config-hostname = $${frontend-instance:ip} | |||
config-port = $${frontend-instance:port} | |||
[apache-frontend-url-available-promise] | |||
<= monitor-promise-base | |||
module = check_url_available | |||
name = $${:_buildout_section_name_}.py | |||
config-url = $${apache-frontend:connection-secure_access} | |||
config-check-secure = 1 | |||
[slapos-standalone-listen-promise] | |||
<= monitor-promise-base | |||
module = check_port_listening | |||
# XXX promise plugins can not contain "slapos" in their names | |||
name = standalone-listen-promise.py | |||
config-hostname = $${slapos-standalone-instance:hostname} | |||
config-port = $${slapos-standalone-instance:port} | |||
[slapos-autorun-promise] | |||
<= monitor-promise-base | |||
module = check_service_state | |||
# XXX promise plugins can not contain "slapos" in their names | |||
name = autorun-state-promise.py | |||
config-service = $${slapos-autorun:service-name} | |||
config-expect = $${slapos-autorun:autorun} | |||
# Remote Apache Frontend | |||
# ---------------------- | |||
[apache-frontend] | |||
<= slap-connection | |||
recipe = slapos.cookbook:requestoptional | |||
name = Theia Frontend | |||
# XXX We have hardcoded SR URL here. | |||
software-url = http://git.erp5.org/gitweb/slapos.git/blob_plain/HEAD:/software/apache-frontend/software.cfg | |||
slave = true | |||
config-url = $${frontend-instance:url} | |||
config-https-only = true | |||
config-type = websocket | |||
config-websocket-path-list = /services /file-upload | |||
return = domain secure_access | |||
# Local Caddy Frontend | |||
# -------------------- | |||
[frontend-instance-password] | |||
recipe = slapos.cookbook:generate.password | |||
username = admin | |||
bytes = 12 | |||
[frontend-instance-port] | |||
recipe = slapos.cookbook:free_port | |||
minimum = 3000 | |||
maximum = 3100 | |||
ip = $${instance-parameter:ipv6-random} | |||
[frontend-instance-certificate] | |||
recipe = plone.recipe.command | |||
command = | |||
if [ ! -e $${:key-file} ] | |||
then | |||
${openssl-output:openssl} req -x509 -nodes -days 3650 \ | |||
-subj "/C=AA/ST=X/L=X/O=Dis/CN=$${:common-name}" \ | |||
-newkey rsa:1024 -keyout $${:key-file} \ | |||
-out $${:cert-file} | |||
fi | |||
update-command = $${:command} | |||
key-file = $${directory:etc}/$${:_buildout_section_name_}.key | |||
cert-file = $${directory:etc}/$${:_buildout_section_name_}.crt | |||
common-name = $${frontend-instance-config:ip} | |||
location = | |||
$${:key-file} | |||
$${:cert-file} | |||
[frontend-instance-config] | |||
recipe = slapos.recipe.template:jinja2 | |||
rendered = $${directory:etc}/$${:_buildout_section_name_} | |||
template = | |||
inline: | |||
:$${:port} { | |||
bind $${:ip} | |||
tls $${frontend-instance-certificate:cert-file} $${frontend-instance-certificate:key-file} | |||
log stdout | |||
errors stderr | |||
gzip | |||
# because caddy does not support upgrade http2 to websocket | |||
# https://tools.ietf.org/html/rfc8441 | |||
tls { | |||
alpn http/1.1 | |||
} | |||
root $${directory:frontend-static} | |||
browse | |||
proxy / $${theia-instance:base-url} { | |||
except $${frontend-instance-fonts:folder-name} $${frontend-instance-slapos.css:folder-name} public $${favicon.ico:filename} $${frontend-instance-logo:filename} | |||
} | |||
proxy /services $${theia-instance:base-url} { | |||
websocket | |||
} | |||
proxy /file-upload $${theia-instance:base-url} { | |||
websocket | |||
} | |||
basicauth $${frontend-instance-password:username} $${frontend-instance-password:passwd} { | |||
realm "Theia" | |||
/ | |||
} | |||
} | |||
ip = $${frontend-instance-port:ip} | |||
hostname = [$${:ip}] | |||
port = $${frontend-instance-port:port} | |||
[frontend-instance] | |||
recipe = slapos.cookbook:wrapper | |||
wrapper-path = $${directory:services}/$${:_buildout_section_name_} | |||
command-line = | |||
${caddy:output} -conf $${frontend-instance-config:rendered} -pidfile $${:pidfile} | |||
ip = $${frontend-instance-config:ip} | |||
hostname = $${frontend-instance-config:hostname} | |||
port = $${frontend-instance-config:port} | |||
pidfile = $${directory:pidfiles}/$${:_buildout_section_name_}.pid | |||
url = https://$${:hostname}:$${:port}/ | |||
[frontend-instance-fonts] | |||
; XXX caddy 1 does not seem to serve different folders at different locations | |||
; so we link fonts in static folder | |||
recipe = plone.recipe.command | |||
location = $${directory:frontend-static}/$${:folder-name} | |||
folder-name = fonts | |||
command = | |||
mkdir -p $${:location} | |||
ln -sf ${source-code-pro-fonts:location} $${:location}/source-code-pro | |||
ln -sf ${jetbrains-mono-fonts:location} $${:location}/jetbrains-mono | |||
stop-on-error = true | |||
[frontend-instance-logo] | |||
recipe = plone.recipe.command | |||
filename = logo.png | |||
full-path = $${directory:frontend-static}/$${:filename} | |||
command = | |||
cp --remove-destination ${logo.png:output} $${:full-path} | |||
stop-on-error = true | |||
[frontend-instance-slapos.css] | |||
recipe = slapos.recipe.template:jinja2 | |||
template = ${slapos.css.in:output} | |||
rendered = $${directory:frontend-static}/$${:folder-name}/slapos.css | |||
folder-name = css | |||
context = | |||
key logo_image frontend-instance-logo:filename | |||
[frontend-reload] | |||
recipe = slapos.cookbook:wrapper | |||
wrapper-path = $${directory:services}/$${:_buildout_section_name_} | |||
command-line = | |||
${bash:location}/bin/bash -c | |||
"kill -s USR1 $$(${coreutils:location}/bin/cat $${frontend-instance:pidfile}) \ | |||
&& ${coreutils:location}/bin/sleep infinity" | |||
hash-files = | |||
$${frontend-instance-config:rendered} | |||
$${frontend-instance:wrapper-path} | |||
wait-for-files = $${frontend-instance:pidfile} | |||
[favicon.ico] | |||
# generate a pseudo random favicon, different for each instance name. | |||
recipe = slapos.recipe.build | |||
install = | |||
import hashlib, shutil | |||
buildout_offline = self.buildout['buildout']['offline'] | |||
self.buildout['buildout']['offline'] = 'false' | |||
try: | |||
gravatar_url = "https://www.gravatar.com/avatar/" + hashlib.md5( | |||
'''$${slap-configuration:root-instance-title}''' | |||
).hexdigest() + "?s=256&d=retro" | |||
shutil.copy(self.download(gravatar_url), '''$${:location}''') | |||
except Exception: | |||
# Because installation should work offline, if we can't download a favicon, | |||
# just ignore this step. | |||
self.logger.exception("Error while downloading favicon, using empty one") | |||
open('''$${:location}''', 'w').close() | |||
finally: | |||
self.buildout['buildout']['offline'] = buildout_offline | |||
location = $${directory:frontend-static}/$${:filename} | |||
filename = $${:_buildout_section_name_} | |||
# Common Environment | |||
# ------------------ | |||
[common-environment] | |||
recipe = slapos.recipe.template:jinja2 | |||
rendered = $${directory:bin}/$${:_buildout_section_name_} | |||
mode = 0700 | |||
template = | |||
inline: | |||
#!/bin/sh | |||
. ${gowork:env.sh} | |||
# reset PS1 from gowork | |||
export PS1='$ ' | |||
export HOME=$${buildout:directory} | |||
export PATH=${python-language-server:location}/bin:${java-jdk:location}/bin:${cli-utilities:PATH}:$HOME/.cargo/bin:$PATH | |||
# Theia Backend | |||
# ------------- | |||
[theia-service-port] | |||
recipe = slapos.cookbook:free_port | |||
minimum = 3500 | |||
maximum = 3600 | |||
ip = $${instance-parameter:ipv4-random} | |||
[theia-service] | |||
recipe = slapos.recipe.template:jinja2 | |||
rendered = $${directory:bin}/$${:_buildout_section_name_} | |||
mode = 0700 | |||
template = | |||
inline:#!/bin/sh | |||
{{ "{% raw %}" }} | |||
{% raw %} | |||
|
|||
export THEIA_WEBVIEW_EXTERNAL_ENDPOINT='{{hostname}}' | |||
{% endraw %} | |||
{{ "{% endraw %}" }} | |||
export THEIA_OPEN_EDITOR_TOKEN=$(${openssl:location}/bin/openssl rand -hex 32) | |||
export THEIA_URL=$${:base-url} | |||
export THEIA_SHELL=$${theia-shell:rendered} | |||
export TMP=$${directory:tmp} | |||
export TEMP=$TMP | |||
export LC_ALL=C.UTF-8 | |||
export TERMINFO=${ncurses:location}/lib/terminfo/ | |||
export EDITOR="${theia-open:rendered} --wait" | |||
export THEIA_DEFAULT_PLUGINS="local-dir:${theia-plugins:location}" | |||
. $${common-environment:rendered} | |||
exec ${theia-wrapper:rendered} "$@" | |||
ip = $${theia-service-port:ip} | |||
port = $${theia-service-port:port} | |||
base-url = http://$${:ip}:$${:port}/ | |||
[theia-instance] | |||
recipe = slapos.cookbook:wrapper | |||
wrapper-path = $${directory:services}/$${:_buildout_section_name_} | |||
command-line = $${theia-service:rendered} --hostname=$${:hostname} --port=$${:port} $${directory:project} | |||
hash-existing-files = | |||
${yarn.lock:output} | |||
${theia-wrapper:rendered} | |||
ip = $${instance-parameter:ipv4-random} | |||
hostname = $${:ip} | |||
port = $${theia-service:port} | |||
base-url = $${theia-service:base-url} | |||
[theia-shell] | |||
recipe = slapos.recipe.template:jinja2 | |||
rendered = $${directory:bin}/$${:_buildout_section_name_} | |||
mode = 0700 | |||
template = | |||
{% raw %} | |||
inline:#!{{ bash }} | |||
SHELL=$BASH | |||
# when running interactively, activate slapos configuration and reset GIT_EXEC_PATH to workaround https://github.com/eclipse-theia/theia/issues/7555 | |||
if [ $# = 0 ]; then | |||
. {{ activate }} | |||
unset GIT_EXEC_PATH | |||
set -- --rcfile {{ bashrc }} | |||
# otherwise, assume this shell is running task and add an artificial delay to workaround https://github.com/eclipse-theia/theia/issues/2961 | |||
else | |||
sleep 1 | |||
fi | |||
exec "$SHELL" "$@" | |||
{% endraw %} | |||
context = | |||
raw bash ${bash:location}/bin/bash | |||
key activate slapos-standalone-activate:rendered | |||
key bashrc theia-bashrc:rendered | |||
[theia-bashrc] | |||
recipe = slapos.recipe.template:jinja2 | |||
rendered = $${directory:etc}/$${:_buildout_section_name_} | |||
template = | |||
inline: | |||
# enable bash completion | |||
. ${bash-completion:location}/etc/profile.d/bash_completion.sh | |||
# source user's .bashrc | |||
[ -f ~/.bashrc ] && . ~/.bashrc | |||
depends = | |||
$${shell-setup-completion:recipe} | |||
[shell-setup-completion] | |||
recipe = plone.recipe.command | |||
stop-on-error = true | |||
command = | |||
${buildout:bin-directory}/slapos complete > $${directory:bash-completions}/slapos | |||
${buildout:bin-directory}/slapos complete --shell fish > $${directory:fish-completions}/slapos.fish | |||
# SlapOS Standalone | |||
# ----------------- | |||
[slapos-standalone-port] | |||
recipe = slapos.cookbook:free_port | |||
minimum = 4000 | |||
maximum = 4100 | |||
ip = $${instance-parameter:ipv4-random} | |||
[slapos-standalone-config] | |||
ipv4 = $${instance-parameter:ipv4-random} | |||
ipv6 = $${instance-parameter:ipv6-random} | |||
port = $${slapos-standalone-port:port} | |||
slapos-configuration = $${directory:runner}/etc/slapos.cfg | |||
computer-id = slaprunner | |||
[slapos-standalone-activate] | |||
recipe = slapos.recipe.template:jinja2 | |||
rendered = $${directory:bin}/$${:_buildout_section_name_} | |||
template = | |||
inline: | |||
export PATH=${buildout:bin-directory}:$PATH | |||
export SLAPOS_CONFIGURATION=$${slapos-standalone-config:slapos-configuration} | |||
export SLAPOS_CLIENT_CONFIGURATION=$SLAPOS_CONFIGURATION | |||
echo 'Standalone SlapOS for computer `$${slapos-standalone-config:computer-id}` activated' | |||
[slapos-standalone] | |||
recipe = slapos.recipe.template:jinja2 | |||
rendered = $${directory:bin}/$${:_buildout_section_name_} | |||
mode = 0700 | |||
template = | |||
inline:#!/bin/sh | |||
. $${common-environment:rendered} | |||
#XXX find out where the extra nodejs in theia's PATH comes from | |||
export PATH=${nodejs:location}/bin/:$PATH | |||
. $${slapos-standalone-activate:rendered} | |||
exec ${slapos-standalone:script-path} \ | |||
$${directory:runner} \ | |||
$${slapos-standalone-config:ipv4} \ | |||
$${slapos-standalone-config:ipv6} \ | |||
$${slapos-standalone-config:port} \ | |||
$${slapos-standalone-config:computer-id} \ | |||
--sr='$${instance-parameter:configuration.embedded-sr}' \ | |||
--srtype='$${instance-parameter:configuration.embedded-sr-type}' \ | |||
$${slap-connection:server-url} \ | |||
$${slap-connection:computer-id} \ | |||
$${slap-connection:partition-id} \ | |||
--key='$${slap-connection:key-file}' \ | |||
--cert='$${slap-connection:cert-file}' | |||
[slapos-standalone-instance] | |||
recipe = slapos.cookbook:wrapper | |||
wrapper-path = $${directory:services}/$${:_buildout_section_name_} | |||
command-line = $${slapos-standalone:rendered} | |||
hash-files = | |||
$${slapos-standalone:rendered} | |||
hostname = $${slapos-standalone-config:ipv4} | |||
port = $${slapos-standalone-config:port} | |||
# Slapos Standalone Autoprocessing | |||
# -------------------------------- | |||
[slapos-autorun] | |||
recipe = plone.recipe.command | |||
command = | |||
case $${:autorun} in | |||
( running ) ${buildout:bin-directory}/supervisorctl -c $${:supervisor-conf} start $${:service-name};; | |||
( stopped ) ${buildout:bin-directory}/supervisorctl -c $${:supervisor-conf} stop $${:service-name};; | |||
esac | |||
update-command = $${:command} | |||
service-name = slapos-node-auto | |||
supervisor-conf = $${directory:runner}/etc/supervisord.conf | |||
autorun = $${instance-parameter:configuration.autorun} | |||
# Theia Local Environment Setup | |||
# ----------------------------- | |||
[tasks.json] | |||
recipe = slapos.recipe.template:jinja2 | |||
rendered = $${directory:dot-theia}/tasks.json | |||
template = | |||
inline: | |||
{ | |||
// See https://go.microsoft.com/fwlink/?LinkId=733558 | |||
// for the documentation about the tasks.json format | |||
"version": "2.0.0", | |||
"tasks": [ | |||
{ | |||
"label": "slapos node software", | |||
"detail": "Build all software supplied to the node", | |||
"type": "shell", | |||
"command": "${buildout:bin-directory}/slapos", | |||
"args": [ | |||
"node", | |||
"software", | |||
// debug mode can be enabled by commenting out this line: | |||
// "--buildout-debug", | |||
"--all" | |||
], | |||
"options": { | |||
"env": { | |||
"SLAPOS_CONFIGURATION": "$${slapos-standalone-config:slapos-configuration}", | |||
"GIT_EXEC_PATH": "" | |||
} | |||
}, | |||
"group": { | |||
"kind": "build", | |||
"isDefault": true | |||
}, | |||
"problemMatcher": [] | |||
}, | |||
{ | |||
"label": "slapos node instance", | |||
"detail": "Create all instances requested on the node", | |||
"type": "shell", | |||
"command": "${buildout:bin-directory}/slapos", | |||
"args": [ | |||
"node", | |||
"instance", | |||
// debug mode can be enabled by commenting out this line: | |||
// "--buildout-debug", | |||
"--all" | |||
], | |||
"options": { | |||
"env": { | |||
"SLAPOS_CONFIGURATION": "$${slapos-standalone-config:slapos-configuration}", | |||
"GIT_EXEC_PATH": "" | |||
} | |||
}, | |||
"problemMatcher": [], | |||
"group": { | |||
"kind": "build", | |||
"isDefault": true | |||
} | |||
} | |||
] | |||
} | |||
[slapos-repository] | |||
recipe = slapos.recipe.build:gitclone | |||
repository = https://lab.nexedi.com/nexedi/slapos.git | |||
location = $${directory:project}/slapos | |||
branch = 1.0 | |||
develop = true | |||
git-executable = ${git:location}/bin/git | |||
[settings.json] | |||
recipe = slapos.recipe.template:jinja2 | |||
rendered = $${directory:dot-theia}$${:_buildout_section_name_} | |||
once = $${:rendered} | |||
template = | |||
inline: | |||
{ | |||
"files.watcherExclude": { | |||
"**/.eggs/**": true, | |||
"**/.env/**": true, | |||
"**/.git/**": true, | |||
"**/node_modules/**": true, | |||
"$${directory:runner}/**":true, | |||
"$${directory:project}/runner/**":true | |||
} | |||
} | |||
[runner-link] | |||
recipe = slapos.cookbook:symbolic.link | |||
target-directory = $${directory:project} | |||
link-binary = $${directory:runner} | |||
[request-script-template] | |||
recipe = slapos.recipe.template:jinja2 | |||
rendered = $${directory:project}/$${:_buildout_section_name_}.sh | |||
mode = 0700 | |||
template = | |||
inline:#!/bin/sh | |||
# This template is generated automatically, copy it in order to supply and request. | |||
# Any manual change to this file may be lost. | |||
software_name=html5as-base #replace the software name writen in ~/srv/project/slapos/software/ | |||
software_release_uri=~/srv/project/slapos/software/$software_name/software.cfg | |||
# slapos supply is used to add the software to the software list to be supplied to a node. | |||
slapos supply $software_release_uri slaprunner | |||
# slapos request the allocation of an instance to the master. | |||
# slapos request also gets status and parameters of the instance if it has any | |||
# (slapos request is meant to be run multiple time until you get the status). | |||
slapos request $software_name'_1' $software_release_uri |