instance-theia.cfg.jinja.in 25.1 KB
Newer Older
1 2 3
{%- set parameter_dict = dict(default_parameter_dict, **parameter_dict) %}
{%- set additional_frontend = parameter_dict['additional-frontend-guid'] %}
{%- set embedded_instance_config = parameter_dict['initial-embedded-instance'] %}
4

5 6
[buildout]
extends =
7
  ${monitor-template:output}
8 9 10 11 12 13 14 15

theia-environment-parts =
  tasks.json
  slapos-repository
  runner-link
  settings.json

theia-parts =
16 17 18
  frontend-instance
  frontend-instance-rsyslogd
  python-server
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
  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


[publish-connection-parameter]
<= monitor-publish
recipe = slapos.cookbook:publish
35 36 37 38
url = $${remote-frontend:connection-secure_access}
{% if additional_frontend %}
additional-url = $${remote-additional-frontend:connection-secure_access}
{% endif %}
39 40 41
username = $${frontend-instance-password:username}
password = $${frontend-instance-password:passwd}
backend-url = $${frontend-instance:url}
42
ipv6 = {{ ipv6_random }}
43 44 45

[directory]
recipe = slapos.cookbook:mkdirectory
46 47 48 49 50 51 52
home = $${buildout:directory}
etc = $${:home}/etc
var = $${:home}/var
srv = $${:home}/srv
bin = $${:home}/bin
tmp = $${:home}/tmp
dot-theia = $${:home}/.theia/
53 54 55 56
pidfiles = $${:var}/run

services = $${:etc}/service
runner = $${:srv}/runner
57
backup = $${:srv}/backup/theia
58
project = $${:srv}/project
59

60 61 62 63
frontend-static = $${:srv}/frontend-static
frontend-static-public = $${:frontend-static}/public
frontend-static-css = $${:frontend-static}/css

64 65
bash-completions = $${:home}/.local/share/bash-completion/completions/
fish-completions = $${:home}/.config/fish/completions/
66 67


68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
# Monitor
# -------

[monitor-instance-parameter]
monitor-httpd-port = {{ parameter_dict['monitor-httpd-port'] }}
{%- for k in ('monitor-cors-domains', 'monitor-username', 'monitor-password') %}
{%-   set v = parameter_dict.get(k) %}
{%-   if v %}
{{ k[8:] }} = {{ v }}
{%-   endif %}
{%- endfor %}
{%- for k in ('monitor-url-list', ) %}
{%-   set v = parameter_dict.get(k) %}
{%-   if v %}
{{ k }} = {{ v }}
{%-   endif %}
{%- endfor %}


87 88 89 90 91 92 93 94
# Promises
# --------

[promises]
recipe =
instance-promises =
  $${theia-listen-promise:name}
  $${frontend-listen-promise:name}
95
  $${python-server-listen-promise:name}
96
  $${frontend-authentication-promise:name}
97 98 99 100
  $${remote-frontend-url-available-promise:name}
  {% if additional_frontend %}
  $${remote-additional-frontend-url-available-promise:name}
  {% endif %}
101
  $${frontend-instance-rsyslogd-promise:name}
102
  $${slapos-standalone-listen-promise:name}
103
  $${slapos-standalone-ready-promise:name}
104
  $${slapos-autorun-promise:name}
105 106 107
  {% if embedded_instance_config %}
  $${embedded-instance-requested-promise:name}
  {% endif %}
108 109 110

[theia-listen-promise]
<= monitor-promise-base
111
promise = check_socket_listening
112
name = $${:_buildout_section_name_}.py
113
config-host = $${theia-instance:ip}
114 115 116 117
config-port = $${theia-instance:port}

[frontend-listen-promise]
<= monitor-promise-base
118
promise = check_socket_listening
119
name = $${:_buildout_section_name_}.py
120
config-host = $${frontend-instance:ip}
121 122
config-port = $${frontend-instance:port}

123 124 125 126 127 128 129
[python-server-listen-promise]
<= monitor-promise-base
promise = check_socket_listening
name = $${:_buildout_section_name_}.py
config-host = $${python-server-port:ip}
config-port = $${python-server-port:port}

130
[frontend-authentication-promise]
131
<= monitor-promise-base
132
promise = check_url_available
133 134 135
name = $${:_buildout_section_name_}.py
ip = $${frontend-instance:ip}
port = $${frontend-instance:port}
136 137 138
config-url = https://[$${:ip}]:$${:port}
config-username = $${frontend-instance-password:username}
config-password = $${frontend-instance-password:passwd}
139

140
[remote-frontend-url-available-promise]
141
<= monitor-promise-base
142
promise = check_url_available
143
name = $${:_buildout_section_name_}.py
144
config-url = $${remote-frontend:connection-secure_access}
145
config-http-code = 401
146

147 148 149
{% if additional_frontend %}
[remote-additional-frontend-url-available-promise]
<= monitor-promise-base
150
promise = check_url_available
151 152
name = $${:_buildout_section_name_}.py
config-url = $${remote-additional-frontend:connection-secure_access}
153
config-http-code = 401
154 155
{% endif %}

156 157 158 159 160 161
[frontend-instance-rsyslogd-promise]
<= monitor-promise-base
promise = check_command_execute
name = rsyslogd_listen_promise.py
config-command = test -S $${frontend-instance-rsyslogd-config:log-socket}

162 163
[slapos-standalone-listen-promise]
<= monitor-promise-base
164
promise = check_socket_listening
165 166
# XXX promise plugins can not contain "slapos" in their names
name = standalone-listen-promise.py
167
config-host = $${slapos-standalone-instance:hostname}
168 169
config-port = $${slapos-standalone-instance:port}

170 171
[slapos-standalone-ready-promise]
<= monitor-promise-base
172
promise = check_socket_listening
173
name = standalone-ready-promise.py
174
config-abstract = $${slapos-standalone-config:abstract-socket-path}
175

176 177
[slapos-autorun-promise]
<= monitor-promise-base
178
promise = check_service_state
179 180 181
name = autorun-state-promise.py
config-service = $${slapos-autorun:service-name}
config-expect = $${slapos-autorun:autorun}
182
config-run-directory = $${directory:runner}/var/run
183

184 185 186 187 188 189 190 191
{% if embedded_instance_config %}
[embedded-instance-requested-promise]
<= monitor-promise-base
promise = check_command_execute
name = embedded-instance-requested-promise.py
config-command = $${embedded-instance-requested-promise-script:output}
{% endif %}

192

193 194
# Remote Caddy Frontend
# ---------------------
195

196
[remote-frontend-base]
197 198
<= slap-connection
recipe = slapos.cookbook:requestoptional
199
shared = true
200 201 202
config-url = $${frontend-instance:url}
config-https-only = true
config-type = websocket
203
config-websocket-path-list = /services /socket.io
204 205
return = domain secure_access

206 207
[remote-frontend]
<= remote-frontend-base
208 209 210
name = {{ parameter_dict['frontend-name'] }}
software-url = {{ parameter_dict['frontend-sr'] }}
software-type = {{ parameter_dict['frontend-sr-type'] }}
211
{%- if parameter_dict.get('frontend-guid') %}
212
sla-instance_guid = {{ parameter_dict['frontend-guid'] }}
213
{%- endif %}
214 215 216 217

{% if additional_frontend %}
[remote-additional-frontend]
<= remote-frontend-base
218 219 220
name = {{ parameter_dict['additional-frontend-name'] }}
software-url = {{ parameter_dict['additional-frontend-sr'] }}
software-type = {{ parameter_dict['additional-frontend-sr-type'] }}
221
{%- if parameter_dict.get('additional-frontend-guid') %}
222
sla-instance_guid = {{ parameter_dict['additional-frontend-guid'] }}
223
{%- endif %}
224 225
{% endif %}

226

227
# Local Haproxy Frontend
228 229 230 231 232
# --------------------

[frontend-instance-password]
recipe = slapos.cookbook:generate.password
username = admin
233
storage-path = $${buildout:parts-directory}/.$${:_buildout_section_name_}
234

235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
[frontend-instance-rsyslogd-config]
recipe = slapos.recipe.template
output = $${directory:etc}/$${:_buildout_section_name_}
log-file = $${directory:log}/frontend-instance.log
log-socket = $${directory:run}/rsyslog.sock
pidfile = $${directory:pidfiles}/rsyslogd.pid
inline =
  module(
    load="imuxsock"
    SysSock.Name="$${:log-socket}")

  # Just simply output the raw line without any additional information, as
  # haproxy emits enough information by itself
  # Also cut out first empty space in msg, which is related to rsyslogd
  # internal and end up cutting on 8k, as it's default of $MaxMessageSize
  template(name="rawoutput" type="string" string="%msg:2:8192%\n")
  $ActionFileDefaultTemplate rawoutput

  $FileCreateMode 0600
  $DirCreateMode 0700
  $Umask 0022

  $WorkDirectory $${directory:run}

  *.* $${:log-file};rawoutput


[frontend-instance-rsyslogd]
recipe = slapos.cookbook:wrapper
command-line = ${rsyslogd:location}/sbin/rsyslogd -i $${frontend-instance-rsyslogd-config:pidfile} -n -f $${frontend-instance-rsyslogd-config:output}
wrapper-path = $${directory:services}/$${:_buildout_section_name_}
hash-files = $${frontend-instance-rsyslogd-config:output}

268 269 270 271
[frontend-instance-port]
recipe = slapos.cookbook:free_port
minimum = 3000
maximum = 3100
272
ip = {{ ipv6_random }}
273 274 275 276

[frontend-instance-certificate]
recipe = plone.recipe.command
command =
277
  if [ ! -e $${:cert-file} ]
278 279 280
  then
    ${openssl-output:openssl} req -x509 -nodes -days 3650 \
      -subj "/C=AA/ST=X/L=X/O=Dis/CN=$${:common-name}" \
281
      -newkey rsa:1024 -keyout $${:cert-file} \
282 283 284
      -out $${:cert-file}
  fi
update-command = $${:command}
285
cert-file = $${directory:etc}/$${:_buildout_section_name_}.pem
286 287 288 289 290
common-name = $${frontend-instance-config:ip}
location =
  $${:cert-file}

[frontend-instance-config]
291 292
recipe = slapos.recipe.template
output = $${directory:etc}/$${:_buildout_section_name_}
293
blankline =
294
inline =
295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326
  global
    maxconn 4096
    master-worker
    pidfile $${frontend-instance:pidfile}
    log $${frontend-instance-rsyslogd-config:log-socket} local0  info

  defaults
    log global
    option httplog
    mode http
    retries 1
    option redispatch
    maxconn 2000
    balance roundrobin
    timeout connect 10s
    timeout queue 60s
    timeout server 305s
    timeout client 305s

    # compress some content types
    compression algo gzip
    compression type application/font-woff application/font-woff2 application/hal+json application/javascript application/json application/rss+xml application/wasm application/x-font-opentype application/x-font-ttf application/x-javascript application/xml image/svg+xml text/cache-manifest text/css text/html text/javascript text/plain text/xml


  userlist basic-auth-list
    user $${frontend-instance-password:username} insecure-password $${frontend-instance-password:passwd}

  frontend app
    log global
    bind $${:ip}:$${:port} ssl crt $${frontend-instance-certificate:cert-file} alpn h2,http/1.1
    # writing twice the same ACL is doing OR
    acl is_public path_beg /public/
327 328 329
    acl is_public path /$${frontend-instance-favicon.ico:filename}
    acl is_public path /$${frontend-instance-theia.webmanifest:filename}
    acl is_public path /$${frontend-instance-theia-serviceworker.js:filename}
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
    acl auth_ok http_auth(basic-auth-list)
    # No authentication for public folder
    http-request auth unless auth_ok || is_public
    use_backend static if { path_beg /$${frontend-instance-fonts:folder-name} } || { path_beg /$${frontend-instance-slapos.css:folder-name} } || { path /$${frontend-instance-logo:filename} } || is_public
    default_backend nodejs

  backend nodejs
    log global
    server nodejs_backend $${theia-instance:ip}:$${theia-instance:port}

  backend static
    log global
    server static_backend $${python-server-port:ip}:$${python-server-port:port}
  $${:blankline}

345 346 347
ip = $${frontend-instance-port:ip}
hostname = [$${:ip}]
port = $${frontend-instance-port:port}
348
pidfile = $${directory:pidfiles}/haproxy.pid
349 350 351 352 353

[frontend-instance]
recipe = slapos.cookbook:wrapper
wrapper-path = $${directory:services}/$${:_buildout_section_name_}
command-line =
354 355
  ${haproxy:location}/sbin/haproxy -f $${frontend-instance-config:output}
hash-files = $${frontend-instance-config:output}
356 357 358 359 360 361 362 363

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]
364
; XXX python server only serves one folder
365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384
; 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
385 386
url = ${slapos.css.in:output}
output = $${directory:frontend-static}/$${:folder-name}/slapos.css
387 388 389 390
folder-name = css
context =
  key logo_image frontend-instance-logo:filename

391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426
[frontend-instance-theia.webmanifest]
recipe = slapos.recipe.build
short-name = {{ root_title }}
name = Theia SlapOS $${:short-name}
background-color = #3c3c3c
install =
  import json
  with open(options['location'], 'w') as f:
    json.dump({
      "name": options["name"],
      "short_name": options["short-name"],
      "icons": [
        {
          "src": "/" + self.buildout["frontend-instance-favicon.ico"]["filename"],
          "sizes": "256x256",
          "type": "image/png"
        },
      ],
      "start_url": "/",
      "display": "fullscreen",
      "background_color": options["background-color"]
    }, f)

location = $${directory:frontend-static}/$${:filename}
filename = theia.webmanifest

[frontend-instance-theia-serviceworker.js]
recipe = slapos.recipe.template
inline =
  /* minimal service worker for A2HS */
  self.addEventListener("fetch", function(event) { });

output = $${directory:frontend-static}/$${:filename}
filename = theia-serviceworker.js

[frontend-instance-favicon.ico]
427 428
# generate a pseudo random favicon, different for each instance name.
recipe = slapos.recipe.build
429
seed = {{ root_title }}
430 431 432 433 434 435
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(
436
      options['seed'].encode()
437
    ).hexdigest() + "?s=256&d=retro"
438
    shutil.copy(self.download(gravatar_url), location)
439 440 441 442
  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")
443
    open(location, 'w').close()
444 445 446 447
  finally:
    self.buildout['buildout']['offline'] = buildout_offline

location = $${directory:frontend-static}/$${:filename}
448
filename = favicon.ico
449

450 451 452 453 454 455 456 457 458 459 460 461 462 463
# Local Python Server
# -------------------

[python-server-port]
recipe = slapos.cookbook:free_port
minimum = 3000
maximum = 3100
ip = {{ ipv4_random }}

[python-server]
recipe = slapos.cookbook:wrapper
wrapper-path = $${directory:services}/$${:_buildout_section_name_}
command-line = $${buildout:executable} -m http.server $${python-server-port:port} --bind $${python-server-port:ip} --directory $${directory:frontend-static}

464 465 466 467 468

# Common Environment
# ------------------

[common-environment]
469 470 471
recipe = slapos.recipe.template
output = $${directory:bin}/$${:_buildout_section_name_}
inline =
472
  #!/bin/sh
473
  export HOME=$${directory:home}
474
  export PATH=${cli-utilities:PATH}:$HOME/.cargo/bin:$PATH
475
  export IPV6_SLAPRUNNER={{ ipv6_random }}
476 477 478 479 480 481 482 483

# Theia Backend
# -------------

[theia-service-port]
recipe = slapos.cookbook:free_port
minimum = 3500
maximum = 3600
484
ip = {{ ipv4_random }}
485 486

[theia-service]
487 488 489 490
recipe = slapos.recipe.template
output = $${directory:bin}/$${:_buildout_section_name_}
inline =
  #!/bin/sh
491
  {% raw -%}
492
  export THEIA_WEBVIEW_EXTERNAL_ENDPOINT='{{hostname}}'
493
  export THEIA_MINI_BROWSER_HOST_PATTERN='{{hostname}}'
494
  {% endraw -%}
495 496
  export THEIA_OPEN_EDITOR_TOKEN=$(${openssl:location}/bin/openssl rand -hex 32)
  export THEIA_URL=$${:base-url}
497
  export THEIA_SHELL=$${theia-shell:output}
498 499 500 501
  export TMP=$${directory:tmp}
  export TEMP=$TMP
  export LC_ALL=C.UTF-8
  export TERMINFO=${ncurses:location}/lib/terminfo/
502
  export EDITOR="${theia-open:output} --wait"
503
  export THEIA_DEFAULT_PLUGINS="local-dir:${theia-plugins:location}"
504 505
  . $${common-environment:output}
  exec ${theia-wrapper:output} "$@"
506 507 508 509 510 511 512
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_}
513
command-line = $${theia-service:output}  --hostname=$${:hostname} --port=$${:port} $${directory:project}
514
hash-existing-files =
515
  ${yarn.lock:target}
516
  ${theia-wrapper:output}
517
ip =  {{ ipv4_random }}
518 519 520 521 522
hostname = $${:ip}
port = $${theia-service:port}

[theia-shell]
recipe = slapos.recipe.template:jinja2
523
output = $${directory:bin}/$${:_buildout_section_name_}
Xavier Thompson's avatar
Xavier Thompson committed
524
inline =
525 526
  {% raw -%}
  #!{{ bash }}
527 528 529 530 531 532 533 534 535 536 537
  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 }}
  fi
  exec "$SHELL" "$@"
  {% endraw %}
context =
  raw bash ${bash:location}/bin/bash
538 539
  key activate slapos-standalone-activate:output
  key bashrc theia-bashrc:output
540 541

[theia-bashrc]
542 543 544
recipe = slapos.recipe.template
output = $${directory:etc}/$${:_buildout_section_name_}
inline =
545 546 547 548 549 550 551 552 553 554 555 556 557 558 559
  # 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


560 561 562
# Embedded Instance
# -----------------

563 564 565 566 567 568 569
[embedded-instance-config]
recipe = slapos.recipe.template:jinja2
output = $${directory:etc}/$${:_buildout_section_name_}.json
once = $${:output}
config = {{ dumps(embedded_instance_config) }}
context =
  key config :config
570
inline =
571 572 573
{%-     raw %}
  {{ config or "{}"}}
{%-     endraw %}
574

575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596
[embedded-instance-requested-promise-script]
recipe = slapos.recipe.template:jinja2
output = $${directory:bin}/$${:_buildout_section_name_}
exitcode-file = $${slapos-standalone-script:embedded-request-exitcode-file}
context =
  key exitcodefile :exitcode-file
{%- raw %}
inline =
  #!/bin/sh
  if ! [ -f {{ repr(exitcodefile) }} ]
  then
    echo "ERROR embedded_instance has not been requested"
    exit 1
  elif [ "$(cat {{ repr(exitcodefile) }})" = 0 ]
  then
    echo "OK embedded_instance has been sucessfully requested"
    exit 0
  else
    echo "ERROR request of embedded_instance failed"
    exit 1
  fi
{%- endraw %}
597

598

599 600 601 602 603 604 605
# SlapOS Standalone
# -----------------

[slapos-standalone-port]
recipe = slapos.cookbook:free_port
minimum = 4000
maximum = 4100
606
ip = {{ ipv4_random }}
607 608

[slapos-standalone-config]
609 610
ipv4 = {{ ipv4_random }}
ipv6 = {{ ipv6_random }}
611
port = $${slapos-standalone-port:port}
612 613 614
base-directory = $${directory:runner}
software-root = $${directory:runner}/software
instance-root = $${directory:runner}/instance
615
local-software-release-root = $${directory:home}
616
slapos-bin = ${buildout:bin-directory}/slapos
617 618
slapos-configuration = $${directory:runner}/etc/slapos.cfg
computer-id = slaprunner
619
abstract-socket-path = $${directory:home}/standalone-ready
620 621

[slapos-standalone-activate]
622 623 624
recipe = slapos.recipe.template
output = $${directory:bin}/$${:_buildout_section_name_}
inline =
625 626 627 628 629
  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'

630
[slapos-standalone-script]
631
recipe = slapos.recipe.template:jinja2
632
output = $${directory:bin}/$${:_buildout_section_name_}
633 634 635 636 637 638 639 640 641 642 643 644
embedded-request-exitcode-file = $${directory:etc}/embedded-request-exitcode
shared-part-list =
  {{ """${buildout:shared-part-list}""" | indent(2) }}
context =
  raw python_for_standalone ${python-for-standalone:executable}
  raw request_script_path $${directory:project}/request-embedded-instance.sh
  raw parameters_file_path $${directory:project}/embedded-instance-parameters.json
  key request_script_template request-script-example:inline
  key shared_part_list :shared-part-list
  key embedded_request_exitcode_file :embedded-request-exitcode-file
  key embedded_instance_config embedded-instance-config:output
  key home_path directory:home
645
  key forward_frontend_requests :forward-frontend-requests
646 647
  section slap_connection slap-connection
  section slapos_standalone_config slapos-standalone-config
648
forward-frontend-requests = {{ parameter_dict['forward-slapos-frontend-requests'] }}
649
url = ${slapos-standalone-script:output}
650

651
[slapos-standalone]
652 653 654 655 656
recipe = slapos.recipe.template
output = $${directory:bin}/$${:_buildout_section_name_}
inline =
  #!/bin/sh
  . $${common-environment:output}
657 658
  #XXX find out where the extra nodejs in theia's PATH comes from
  export PATH=${nodejs:location}/bin/:$PATH
659 660
  . $${slapos-standalone-activate:output}
  exec $${slapos-standalone-script:output}
661 662 663 664

[slapos-standalone-instance]
recipe = slapos.cookbook:wrapper
wrapper-path = $${directory:services}/$${:_buildout_section_name_}
665
command-line = $${slapos-standalone:output}
666
hash-files =
667 668
  $${slapos-standalone:output}
  $${slapos-standalone-script:output}
669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685
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
686
autorun = {{ parameter_dict['autorun'] }}
687 688 689 690 691 692


# Theia Local Environment Setup
# -----------------------------

[tasks.json]
693 694 695
recipe = slapos.recipe.template
output = $${directory:dot-theia}/tasks.json
inline =
696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761
  {
    // 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
762 763 764
output = $${directory:dot-theia}$${:_buildout_section_name_}
once = $${:output}
inline =
765 766 767 768 769 770 771 772
  {
    "files.watcherExclude": {
      "**/.eggs/**": true,
      "**/.env/**": true,
      "**/.git/**": true,
      "**/node_modules/**": true,
      "$${directory:runner}/**":true,
      "$${directory:project}/runner/**":true
773
    },
774
    "git.terminalAuthentication": false,
775 776
    "security.workspace.trust.startupPrompt": "once",
    "zc-buildout.python.executable": "${python-for-buildout-languageserver:executable}"
777 778 779 780 781 782 783
  }

[runner-link]
recipe = slapos.cookbook:symbolic.link
target-directory = $${directory:project}
link-binary = $${directory:runner}

784 785
[request-script-example]
recipe = slapos.recipe.template:jinja2
786
output = $${directory:project}/$${:_buildout_section_name_}.sh
787 788 789 790 791 792 793 794 795 796 797 798
software_url = ~/srv/project/slapos/software/html5as-base/software.cfg
request_options = html5as-1 $${:software_url}
header_text =
  # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
  # This template is generated automatically by buildout. #
  # Any changes to this file may be overwritten.          #
  # Copy and adapt it to create your own request script.  #
  # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
context =
  key software_url :software_url
  key request_options :request_options
  key header_text :header_text
799
inline =
800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828
{%- raw %}
  #!/bin/sh -e

  {{ header_text }}

  # slapos supply <url> <node> registers a software for installation on a node.
  #
  # A software is uniquely identified by its URL (the URL may be a local path).
  # You may choose from softwares available in ~/srv/project/slapos/software.
  #
  # The one and only SlapOS Node embedded inside Theia is called 'slaprunner'.
  #
  # For more information, run:
  #     slapos help supply
  #
  slapos supply {{ software_url }} slaprunner

  # slapos request <name> <url> registers an instance for allocation on a node.
  #
  # An instance is uniquely identified by its name (and its requester).
  #
  # It will be allocated on a node where the software URL is already supplied.
  # Inside Theia that node can only be 'slaprunner'.
  #
  # For more information, run:
  #     slapos help request
  #
  slapos request {{ request_options }}
{%  endraw %}