Config-based KasmVNC
This commit is contained in:
committed by
Anthony Merrill
parent
d9cf46f83e
commit
36a1ffc5e4
84
spec/fixtures/defaults_config.yaml
vendored
Normal file
84
spec/fixtures/defaults_config.yaml
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
desktop:
|
||||
resolution:
|
||||
width: 1024
|
||||
height: 768
|
||||
allow_resize: true
|
||||
pixel_depth: 24
|
||||
|
||||
network:
|
||||
protocol: http
|
||||
interface: 0.0.0.0
|
||||
websocket_port: auto
|
||||
use_ipv4: true
|
||||
use_ipv6: true
|
||||
ssl:
|
||||
pem_certificate: /etc/ssl/certs/ssl-cert-snakeoil.pem
|
||||
pem_key: /etc/ssl/private/ssl-cert-snakeoil.key
|
||||
require_ssl: true
|
||||
|
||||
security:
|
||||
brute_force_protection:
|
||||
blacklist_threshold: 5
|
||||
blacklist_timeout: 10
|
||||
|
||||
data_loss_prevention:
|
||||
visible_region:
|
||||
# top: 10
|
||||
# left: 10
|
||||
# right: 40
|
||||
# bottom: 40
|
||||
concealed_region:
|
||||
allow_click_down: false
|
||||
allow_click_release: false
|
||||
clipboard:
|
||||
delay_between_operations: none
|
||||
server_to_client:
|
||||
enabled: true
|
||||
size: 10000
|
||||
primary_clipboard_enabled: false
|
||||
client_to_server:
|
||||
enabled: true
|
||||
size: 10000
|
||||
keyboard:
|
||||
enabled: true
|
||||
rate_limit: unlimited
|
||||
logging:
|
||||
level: off
|
||||
|
||||
encoding:
|
||||
max_frame_rate: 60
|
||||
rect_encoding_mode:
|
||||
min_quality: 7
|
||||
max_quality: 8
|
||||
consider_lossless_quality: 10
|
||||
rectangle_compress_threads: auto
|
||||
|
||||
video_encoding_mode:
|
||||
jpeg_quality: -1
|
||||
webp_quality: -1
|
||||
max_resolution:
|
||||
width: 1920
|
||||
height: 1080
|
||||
enter_video_encoding_mode:
|
||||
time_threshold: 5
|
||||
area_threshold: 45%
|
||||
exit_video_encoding_mode:
|
||||
time_threshold: 3
|
||||
logging:
|
||||
level: off
|
||||
scaling_algorithm: progressive_bilinear
|
||||
|
||||
compare_framebuffer: auto
|
||||
zrle_zlib_level: auto
|
||||
hextile_improved_compression: true
|
||||
|
||||
server:
|
||||
advanced:
|
||||
x_font_path: auto
|
||||
httpd_directory: /usr/share/kasmvnc/www
|
||||
kasm_password_file: ~/.kasmpasswd
|
||||
x_authority_file: auto
|
||||
auto_shutdown:
|
||||
no_user_session_timeout: never
|
||||
active_user_session_timeout: never
|
||||
inactive_user_session_timeout: never
|
||||
3
spec/fixtures/global_config.yaml
vendored
Normal file
3
spec/fixtures/global_config.yaml
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
security:
|
||||
brute_force_protection:
|
||||
blacklist_threshold: 6
|
||||
4
spec/fixtures/user_config.yaml
vendored
Normal file
4
spec/fixtures/user_config.yaml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
security:
|
||||
brute_force_protection:
|
||||
blacklist_threshold: 7
|
||||
blacklist_timeout: 12
|
||||
0
spec/helper/__init__.py
Normal file
0
spec/helper/__init__.py
Normal file
93
spec/helper/spec_helper.py
Normal file
93
spec/helper/spec_helper.py
Normal file
@@ -0,0 +1,93 @@
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
import subprocess
|
||||
import pexpect
|
||||
from path import Path
|
||||
from expects import expect, equal
|
||||
|
||||
vncserver_cmd = 'vncserver :1'
|
||||
running_xvnc = False
|
||||
debug_output = False
|
||||
config_dir = "spec/tmp"
|
||||
config_filename = os.path.join(config_dir, "config.yaml")
|
||||
|
||||
if os.getenv('KASMVNC_SPEC_DEBUG_OUTPUT'):
|
||||
debug_output = True
|
||||
|
||||
|
||||
def write_config(config_text):
|
||||
os.makedirs(config_dir, exist_ok=True)
|
||||
|
||||
with open(config_filename, "w") as f:
|
||||
f.write(config_text)
|
||||
|
||||
|
||||
def clean_env():
|
||||
clean_kasm_users()
|
||||
|
||||
home_dir = os.environ['HOME']
|
||||
vnc_dir = os.path.join(home_dir, ".vnc")
|
||||
Path(vnc_dir).rmtree(ignore_errors=True)
|
||||
|
||||
|
||||
def clean_kasm_users():
|
||||
home_dir = os.environ['HOME']
|
||||
password_file = os.path.join(home_dir, ".kasmpasswd")
|
||||
Path(password_file).remove_p()
|
||||
|
||||
|
||||
def start_xvnc_pexpect(extra_args="", **kwargs):
|
||||
global running_xvnc
|
||||
|
||||
# ":;" is a hack. Without it, Xvnc doesn't run. No idea what happens, but
|
||||
# when I run top, Xvnc just isn't there. I suspect a race.
|
||||
child = pexpect.spawn('/bin/bash',
|
||||
['-ic', f':;{vncserver_cmd} {extra_args}'],
|
||||
timeout=5, encoding='utf-8', **kwargs)
|
||||
if debug_output:
|
||||
child.logfile_read = sys.stderr
|
||||
|
||||
running_xvnc = True
|
||||
|
||||
return child
|
||||
|
||||
|
||||
def start_xvnc(extra_args="", **kwargs):
|
||||
global running_xvnc
|
||||
completed_process = run_cmd(f'{vncserver_cmd} {extra_args}',
|
||||
print_stderr=False, **kwargs)
|
||||
if completed_process.returncode == 0:
|
||||
running_xvnc = True
|
||||
|
||||
return completed_process
|
||||
|
||||
|
||||
def run_cmd(cmd, print_stderr=True, **kwargs):
|
||||
completed_process = subprocess.run(cmd, shell=True, text=True,
|
||||
capture_output=True,
|
||||
executable='/bin/bash', **kwargs)
|
||||
if debug_output:
|
||||
if len(completed_process.stderr) > 0:
|
||||
print(completed_process.stderr)
|
||||
if len(completed_process.stdout) > 0:
|
||||
print(completed_process.stdout)
|
||||
elif print_stderr:
|
||||
if len(completed_process.stderr) > 0:
|
||||
print(completed_process.stderr)
|
||||
|
||||
return completed_process
|
||||
|
||||
|
||||
def add_kasmvnc_user_docker():
|
||||
completed_process = run_cmd('echo -e "password\\npassword\\n" | vncpasswd -u docker -w')
|
||||
expect(completed_process.returncode).to(equal(0))
|
||||
|
||||
|
||||
def kill_xvnc():
|
||||
global running_xvnc
|
||||
if not running_xvnc:
|
||||
return
|
||||
|
||||
run_cmd('vncserver -kill :1', print_stderr=False)
|
||||
running_xvnc = False
|
||||
42
spec/kasmvnc.yaml
Normal file
42
spec/kasmvnc.yaml
Normal file
@@ -0,0 +1,42 @@
|
||||
desktop:
|
||||
resolution:
|
||||
width: 1024
|
||||
height: 768
|
||||
allow_resize: true
|
||||
pixel_depth: 24
|
||||
|
||||
security:
|
||||
brute_force_protection:
|
||||
blacklist_threshold: 1
|
||||
blacklist_timeout: 10
|
||||
|
||||
logging:
|
||||
log_writer_name: all
|
||||
log_dest: logfile
|
||||
# 0 - silent(?), 100 - most verbose
|
||||
level: 100
|
||||
|
||||
data_loss_prevention:
|
||||
visible_region:
|
||||
# top: 10
|
||||
# left: 10
|
||||
# right: 40
|
||||
# bottom: 40
|
||||
concealed_region:
|
||||
allow_click_down: false
|
||||
allow_click_release: false
|
||||
clipboard:
|
||||
delay_between_operations: none
|
||||
# Cut buffers and CLIPBOARD selection.
|
||||
server_to_client:
|
||||
enabled: true
|
||||
size: unlimited
|
||||
primary_clipboard_enabled: false
|
||||
|
||||
keyboard:
|
||||
remap_keys:
|
||||
- 0x22->0x40
|
||||
- 0x24->0x40
|
||||
|
||||
command_line:
|
||||
prompt: true
|
||||
10
spec/vncserver_perl_warnings_spec.py
Normal file
10
spec/vncserver_perl_warnings_spec.py
Normal file
@@ -0,0 +1,10 @@
|
||||
from mamba import description, context, it, fit, before, after
|
||||
from expects import expect, equal, contain, match
|
||||
from helper.spec_helper import start_xvnc, kill_xvnc, run_cmd, clean_env, \
|
||||
add_kasmvnc_user_docker, clean_kasm_users, start_xvnc_pexpect, \
|
||||
write_config, config_filename
|
||||
|
||||
with description("Perl warnings"):
|
||||
with it("treats Perl warning as error"):
|
||||
completed_process = run_cmd("vncserver -dry-run")
|
||||
expect(completed_process.stderr).not_to(match(r'line \d+\.$'))
|
||||
155
spec/vncserver_select_de_spec.py
Normal file
155
spec/vncserver_select_de_spec.py
Normal file
@@ -0,0 +1,155 @@
|
||||
import os
|
||||
import sys
|
||||
import pexpect
|
||||
from mamba import description, context, it, fit, before, after
|
||||
from expects import expect, equal
|
||||
|
||||
from helper.spec_helper import start_xvnc, kill_xvnc, run_cmd, clean_env, \
|
||||
add_kasmvnc_user_docker, clean_kasm_users, start_xvnc_pexpect
|
||||
|
||||
# WIP. Plan to move to start_xvnc_pexpect(), because pexpect provides a way to
|
||||
# wait for vncserver output. start_xvnc() just blindly prints input to vncserver
|
||||
# without knowing what it prints back.
|
||||
|
||||
|
||||
def select_de(de_name):
|
||||
try:
|
||||
extra_args = f'-select-de {de_name}'
|
||||
completed_process = start_xvnc(extra_args)
|
||||
expect(completed_process.returncode).to(equal(0))
|
||||
finally:
|
||||
kill_xvnc()
|
||||
|
||||
|
||||
def check_de_was_setup_to_run(de_name):
|
||||
completed_process = run_cmd(f'grep -q {de_name} ~/.vnc/xstartup')
|
||||
expect(completed_process.returncode).to(equal(0))
|
||||
|
||||
|
||||
with description('vncserver') as self:
|
||||
with before.each:
|
||||
clean_env()
|
||||
with after.each:
|
||||
kill_xvnc()
|
||||
|
||||
with context('on the first run'):
|
||||
with before.each:
|
||||
add_kasmvnc_user_docker()
|
||||
|
||||
with it('asks user to select a DE'):
|
||||
child = start_xvnc_pexpect()
|
||||
child.expect(r'\[1\] Cinnamon.+Manually edit')
|
||||
child.sendline("1\n")
|
||||
child.wait()
|
||||
|
||||
expect(child.exitstatus).to(equal(0))
|
||||
check_de_was_setup_to_run('cinnamon')
|
||||
|
||||
with it("doesn't prompt user to select a DE if prompting is disabled"):
|
||||
child = start_xvnc_pexpect("-prompt 0")
|
||||
child.expect(r'Warning: the Desktop Environment.+wasn\'t selected')
|
||||
child.wait()
|
||||
|
||||
expect(child.exitstatus).to(equal(0))
|
||||
|
||||
with it('asks to select a DE, when ran with -select-de'):
|
||||
child = start_xvnc_pexpect('-select-de')
|
||||
child.expect(r'\[1\] Cinnamon.+Manually edit')
|
||||
child.sendline("1\n")
|
||||
child.wait()
|
||||
|
||||
expect(child.exitstatus).to(equal(0))
|
||||
check_de_was_setup_to_run('cinnamon')
|
||||
|
||||
with it("doesn't prompt user to select a DE if prompting is disabled"):
|
||||
child = start_xvnc_pexpect("-select-de -prompt 0")
|
||||
child.expect(r'Warning: the Desktop Environment.+wasn\'t selected')
|
||||
child.wait()
|
||||
|
||||
expect(child.exitstatus).to(equal(0))
|
||||
|
||||
with it('selects passed DE with -s'):
|
||||
select_de('mate')
|
||||
check_de_was_setup_to_run('mate')
|
||||
|
||||
with it('selects manual xstartup editing, not a DE'):
|
||||
select_de('manual')
|
||||
check_de_was_setup_to_run('twm')
|
||||
|
||||
with context('after DE was selected'):
|
||||
with before.each:
|
||||
add_kasmvnc_user_docker()
|
||||
|
||||
with it("don't ask to choose DE by default"):
|
||||
select_de('mate')
|
||||
|
||||
completed_process = start_xvnc()
|
||||
expect(completed_process.returncode).to(equal(0))
|
||||
|
||||
check_de_was_setup_to_run('mate')
|
||||
|
||||
with it('asks to select a DE, when ran with -select-de'):
|
||||
select_de('mate')
|
||||
|
||||
choose_cinnamon_and_answer_yes = "1\ny\n"
|
||||
completed_process = start_xvnc('-select-de',
|
||||
input=choose_cinnamon_and_answer_yes)
|
||||
expect(completed_process.returncode).to(equal(0))
|
||||
|
||||
check_de_was_setup_to_run('cinnamon')
|
||||
|
||||
with it("doesn't ask user to select a DE if prompting is disabled"):
|
||||
child = start_xvnc_pexpect("-select-de -prompt 0")
|
||||
child.expect(r'Warning: the Desktop Environment.+wasn\'t selected')
|
||||
child.wait()
|
||||
|
||||
expect(child.exitstatus).to(equal(0))
|
||||
|
||||
with it('selects passed DE with -s'):
|
||||
select_de('mate')
|
||||
|
||||
completed_process = start_xvnc('-select-de cinnamon')
|
||||
expect(completed_process.returncode).to(equal(0))
|
||||
|
||||
check_de_was_setup_to_run('cinnamon')
|
||||
|
||||
with context('guided user creation'):
|
||||
with it('asks to create a user if none exist'):
|
||||
clean_kasm_users()
|
||||
|
||||
child = start_xvnc_pexpect('-select-de cinnamon')
|
||||
child.expect('Provide selection number:')
|
||||
child.sendline('1')
|
||||
child.expect('Enter username')
|
||||
child.sendline()
|
||||
child.expect('Password:')
|
||||
child.sendline('password')
|
||||
child.expect('Verify:')
|
||||
child.sendline('password')
|
||||
child.expect(pexpect.EOF)
|
||||
child.close()
|
||||
expect(child.exitstatus).to(equal(0))
|
||||
|
||||
home_dir = os.environ['HOME']
|
||||
user = os.environ['USER']
|
||||
completed_process = run_cmd(f'grep -qw {user} {home_dir}/.kasmpasswd')
|
||||
expect(completed_process.returncode).to(equal(0))
|
||||
|
||||
with it('specify custom username'):
|
||||
custom_username = 'custom_username'
|
||||
child = start_xvnc_pexpect('-select-de cinnamon')
|
||||
child.expect('Provide selection number:')
|
||||
child.sendline('1')
|
||||
child.expect('Enter username')
|
||||
child.sendline(custom_username)
|
||||
child.expect('Password:')
|
||||
child.sendline('password')
|
||||
child.expect('Verify:')
|
||||
child.sendline('password')
|
||||
child.expect(pexpect.EOF)
|
||||
child.wait()
|
||||
expect(child.exitstatus).to(equal(0))
|
||||
|
||||
home_dir = os.environ['HOME']
|
||||
completed_process = run_cmd(f'grep -qw {custom_username} {home_dir}/.kasmpasswd')
|
||||
expect(completed_process.returncode).to(equal(0))
|
||||
297
spec/vncserver_yaml_to_cli_spec.py
Normal file
297
spec/vncserver_yaml_to_cli_spec.py
Normal file
@@ -0,0 +1,297 @@
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
from os.path import expanduser
|
||||
from mamba import description, context, fcontext, it, fit, before, after
|
||||
from expects import expect, equal, contain, match
|
||||
|
||||
from helper.spec_helper import start_xvnc, kill_xvnc, run_cmd, clean_env, \
|
||||
add_kasmvnc_user_docker, clean_kasm_users, start_xvnc_pexpect, \
|
||||
write_config, config_filename
|
||||
|
||||
home_dir = expanduser("~")
|
||||
vnc_dir = f'{home_dir}/.vnc'
|
||||
user_config = f'{vnc_dir}/kasmvnc.yaml'
|
||||
|
||||
|
||||
def run_vncserver():
|
||||
return run_cmd(f'vncserver -dry-run -config {config_filename}')
|
||||
|
||||
|
||||
def pick_cli_option(cli_option, xvnc_cmd):
|
||||
cli_option_regex = re.compile(f'\'?-{cli_option}\'?(?:\s+[^-][^\s]*|$)')
|
||||
results = cli_option_regex.findall(xvnc_cmd)
|
||||
if len(results) == 0:
|
||||
return None
|
||||
|
||||
return ' '.join(results)
|
||||
|
||||
|
||||
def prepare_env():
|
||||
os.makedirs(vnc_dir, exist_ok=True)
|
||||
shutil.copyfile('spec/kasmvnc.yaml', user_config)
|
||||
|
||||
|
||||
with description('YAML to CLI') as self:
|
||||
with before.all:
|
||||
prepare_env()
|
||||
|
||||
with context("convert a boolean key"):
|
||||
with it("convert true to 1"):
|
||||
write_config('''
|
||||
desktop:
|
||||
allow_resize: true
|
||||
''')
|
||||
completed_process = run_vncserver()
|
||||
cli_option = pick_cli_option('AcceptSetDesktopSize',
|
||||
completed_process.stdout)
|
||||
expect(cli_option).to(equal("-AcceptSetDesktopSize '1'"))
|
||||
|
||||
with it("convert false to 0"):
|
||||
write_config('''
|
||||
desktop:
|
||||
allow_resize: false
|
||||
''')
|
||||
completed_process = run_vncserver()
|
||||
cli_option = pick_cli_option('AcceptSetDesktopSize',
|
||||
completed_process.stdout)
|
||||
expect(cli_option).to(equal("-AcceptSetDesktopSize '0'"))
|
||||
|
||||
with it("converts a numeric key to a CLI arg"):
|
||||
write_config('''
|
||||
security:
|
||||
brute_force_protection:
|
||||
blacklist_threshold: 2
|
||||
''')
|
||||
completed_process = run_vncserver()
|
||||
cli_option = pick_cli_option('BlacklistThreshold',
|
||||
completed_process.stdout)
|
||||
expect(cli_option).to(equal("-BlacklistThreshold '2'"))
|
||||
|
||||
with it("converts an ANY key to a CLI arg"):
|
||||
write_config('''
|
||||
network:
|
||||
ssl:
|
||||
pem_certificate: /etc/ssl/certs/ssl-cert-snakeoil.pem
|
||||
''')
|
||||
completed_process = run_vncserver()
|
||||
cli_option = pick_cli_option('cert',
|
||||
completed_process.stdout)
|
||||
expect(cli_option).to(
|
||||
equal("-cert '/etc/ssl/certs/ssl-cert-snakeoil.pem'"))
|
||||
|
||||
with it("converts an array key to a CLI arg"):
|
||||
write_config('''
|
||||
keyboard:
|
||||
remap_keys:
|
||||
- 0x22->0x40
|
||||
- 0x24->0x40
|
||||
''')
|
||||
completed_process = run_vncserver()
|
||||
cli_option = pick_cli_option('RemapKeys',
|
||||
completed_process.stdout)
|
||||
expect(cli_option).to(
|
||||
equal("-RemapKeys '0x22->0x40,0x24->0x40'"))
|
||||
|
||||
with it("converts a constant value to the corresponding numeric value"):
|
||||
write_config('''
|
||||
data_loss_prevention:
|
||||
clipboard:
|
||||
server_to_client:
|
||||
size: 20
|
||||
''')
|
||||
completed_process = run_vncserver()
|
||||
cli_option = pick_cli_option('DLP_ClipSendMax',
|
||||
completed_process.stdout)
|
||||
expect(cli_option).to(equal("-DLP_ClipSendMax '20'"))
|
||||
|
||||
with context("websocketPort"):
|
||||
with it("converts 'auto' value to calculated value"):
|
||||
write_config('''
|
||||
network:
|
||||
websocket_port: auto
|
||||
''')
|
||||
completed_process = run_vncserver()
|
||||
cli_option = pick_cli_option('websocketPort',
|
||||
completed_process.stdout)
|
||||
expect(["-websocketPort '8444'", "-websocketPort '8445'"]). \
|
||||
to(contain(cli_option))
|
||||
|
||||
with it("passes numeric value to CLI option"):
|
||||
write_config('''
|
||||
network:
|
||||
websocket_port: 8555
|
||||
''')
|
||||
completed_process = run_vncserver()
|
||||
cli_option = pick_cli_option('websocketPort',
|
||||
completed_process.stdout)
|
||||
expect(cli_option).to(equal("-websocketPort '8555'"))
|
||||
|
||||
with it("no key - no CLI option"):
|
||||
write_config('''
|
||||
''')
|
||||
completed_process = run_vncserver()
|
||||
cli_option = pick_cli_option('websocketPort',
|
||||
completed_process.stdout)
|
||||
expect(cli_option).to(equal(None))
|
||||
|
||||
with context("option that can yield nothing"):
|
||||
with it("converts a config value that yields nothing"):
|
||||
write_config('''
|
||||
network:
|
||||
protocol: http
|
||||
''')
|
||||
completed_process = run_vncserver()
|
||||
cli_option = pick_cli_option('noWebsocket',
|
||||
completed_process.stdout)
|
||||
expect(cli_option).to(equal(None))
|
||||
|
||||
with it("converts a config value that yields CLI option"):
|
||||
write_config('''
|
||||
network:
|
||||
protocol: vnc
|
||||
''')
|
||||
completed_process = run_vncserver()
|
||||
cli_option = pick_cli_option('noWebsocket',
|
||||
completed_process.stdout)
|
||||
expect(cli_option).to(equal("-noWebsocket '1'"))
|
||||
|
||||
with it("interpolates env variable"):
|
||||
write_config('''
|
||||
server:
|
||||
advanced:
|
||||
kasm_password_file: ${HOME}/.kasmpasswd
|
||||
''')
|
||||
completed_process = run_vncserver()
|
||||
cli_option = pick_cli_option('KasmPasswordFile',
|
||||
completed_process.stdout)
|
||||
expect(cli_option).to(equal("-KasmPasswordFile '/home/docker/.kasmpasswd'"))
|
||||
|
||||
with it("converts logging options into one -Log"):
|
||||
write_config('''
|
||||
logging:
|
||||
log_writer_name: all
|
||||
log_dest: logfile
|
||||
level: 40
|
||||
''')
|
||||
completed_process = run_vncserver()
|
||||
cli_option = pick_cli_option('Log',
|
||||
completed_process.stdout)
|
||||
expect(cli_option).to(equal("-Log '*:stdout:40'"))
|
||||
|
||||
with it("converts DLP region options into one -DLP_Region"):
|
||||
write_config('''
|
||||
data_loss_prevention:
|
||||
visible_region:
|
||||
top: -10
|
||||
left: 10
|
||||
right: 40%
|
||||
bottom: 40
|
||||
''')
|
||||
completed_process = run_vncserver()
|
||||
cli_option = pick_cli_option('DLP_Region',
|
||||
completed_process.stdout)
|
||||
expect(cli_option).to(equal("-DLP_Region '10,-10,40%,40'"))
|
||||
|
||||
with context("converts x_font_path"):
|
||||
with it("auto"):
|
||||
write_config('''
|
||||
server:
|
||||
advanced:
|
||||
x_font_path: auto
|
||||
''')
|
||||
completed_process = run_vncserver()
|
||||
cli_option = pick_cli_option('fp',
|
||||
completed_process.stdout)
|
||||
expect(cli_option).to(match(r'/usr/share/fonts'))
|
||||
|
||||
with it("none specified"):
|
||||
write_config('''
|
||||
''')
|
||||
completed_process = run_vncserver()
|
||||
cli_option = pick_cli_option('fp',
|
||||
completed_process.stdout)
|
||||
expect(cli_option).to(match(r'/usr/share/fonts'))
|
||||
|
||||
with it("path specified"):
|
||||
write_config('''
|
||||
server:
|
||||
advanced:
|
||||
x_font_path: /src
|
||||
''')
|
||||
completed_process = run_vncserver()
|
||||
cli_option = pick_cli_option('fp', completed_process.stdout)
|
||||
expect(cli_option).to(equal("-fp '/src'"))
|
||||
|
||||
with it("CLI override"):
|
||||
write_config('''
|
||||
server:
|
||||
advanced:
|
||||
x_font_path: /src
|
||||
''')
|
||||
completed_process = \
|
||||
run_cmd(f'vncserver -dry-run -fp /override -config {config_filename}')
|
||||
cli_option = pick_cli_option('fp', completed_process.stdout)
|
||||
expect(cli_option).to(equal("-fp '/override'"))
|
||||
|
||||
with it("converts network.interface to -interface"):
|
||||
write_config('''
|
||||
network:
|
||||
interface: 0.0.0.0
|
||||
''')
|
||||
completed_process = run_vncserver()
|
||||
cli_option = pick_cli_option('interface',
|
||||
completed_process.stdout)
|
||||
expect(cli_option).to(equal("-interface '0.0.0.0'"))
|
||||
|
||||
with it("CLI option directly passed, overrides config"):
|
||||
write_config('''
|
||||
encoding:
|
||||
video_encoding_mode:
|
||||
jpeg_quality: -1
|
||||
''')
|
||||
completed_process = \
|
||||
run_cmd(f'vncserver -dry-run -JpegVideoQuality 8 -config {config_filename}')
|
||||
cli_option = pick_cli_option("JpegVideoQuality",
|
||||
completed_process.stdout)
|
||||
expect(cli_option).to(equal("'-JpegVideoQuality' '8'"))
|
||||
|
||||
with it("converts 2 keys into a single CLI option"):
|
||||
write_config('''
|
||||
desktop:
|
||||
resolution:
|
||||
width: 1024
|
||||
height: 768
|
||||
''')
|
||||
completed_process = run_vncserver()
|
||||
cli_option = pick_cli_option('geometry',
|
||||
completed_process.stdout)
|
||||
expect(cli_option).to(equal("-geometry '1024x768'"))
|
||||
|
||||
with it("ignores empty section override"):
|
||||
write_config('''
|
||||
security:
|
||||
''')
|
||||
completed_process = \
|
||||
run_cmd(f'vncserver -dry-run -config spec/fixtures/global_config.yaml,{config_filename}')
|
||||
cli_option = pick_cli_option('BlacklistThreshold',
|
||||
completed_process.stdout)
|
||||
expect(cli_option).to(equal("-BlacklistThreshold '6'"))
|
||||
|
||||
with it("overrides default config value with global config value"):
|
||||
completed_process = run_cmd("vncserver -dry-run -config spec/fixtures/defaults_config.yaml,spec/fixtures/global_config.yaml")
|
||||
cli_option = pick_cli_option('BlacklistThreshold',
|
||||
completed_process.stdout)
|
||||
expect(cli_option).to(equal("-BlacklistThreshold '6'"))
|
||||
|
||||
with it("uses default config value even if section was overriden"):
|
||||
completed_process = run_cmd("vncserver -dry-run -config spec/fixtures/defaults_config.yaml,spec/fixtures/global_config.yaml")
|
||||
cli_option = pick_cli_option('BlacklistTimeout',
|
||||
completed_process.stdout)
|
||||
expect(cli_option).to(equal("-BlacklistTimeout '10'"))
|
||||
|
||||
with it("overrides global config with user config value"):
|
||||
completed_process = run_cmd("vncserver -dry-run -config spec/fixtures/defaults_config.yaml,spec/fixtures/global_config.yaml,spec/fixtures/user_config.yaml")
|
||||
cli_option = pick_cli_option('BlacklistThreshold',
|
||||
completed_process.stdout)
|
||||
expect(cli_option).to(equal("-BlacklistThreshold '7'"))
|
||||
111
spec/vncserver_yaml_validation_spec.py
Normal file
111
spec/vncserver_yaml_validation_spec.py
Normal file
@@ -0,0 +1,111 @@
|
||||
from mamba import description, context, fit, it, before, after
|
||||
from expects import expect, equal, contain
|
||||
|
||||
from helper.spec_helper import start_xvnc, kill_xvnc, run_cmd, clean_env, \
|
||||
add_kasmvnc_user_docker, clean_kasm_users, start_xvnc_pexpect, \
|
||||
config_filename, write_config
|
||||
|
||||
with description('YAML validation') as self:
|
||||
with it("produces error message for an incomplete data clump"):
|
||||
write_config('''
|
||||
desktop:
|
||||
resolution:
|
||||
width: 1024
|
||||
''')
|
||||
completed_process = run_cmd(f'vncserver -dry-run -test-output-topic validation -config {config_filename}', print_stderr=False)
|
||||
expect(completed_process.stderr).to(contain('desktop.resolution.width, desktop.resolution.height: either all keys or none must be present'))
|
||||
|
||||
with it("produces error message if int key was set to a string"):
|
||||
write_config('''
|
||||
desktop:
|
||||
resolution:
|
||||
width: 1024
|
||||
height: none
|
||||
''')
|
||||
completed_process = run_cmd(f'vncserver -dry-run -test-output-topic validation -config {config_filename}', print_stderr=False)
|
||||
expect(completed_process.stderr).to(contain("desktop.resolution.height 'none': must be an integer"))
|
||||
|
||||
with it("produces no error for valid boolean values"):
|
||||
write_config('''
|
||||
network:
|
||||
use_ipv4: true
|
||||
use_ipv6: false
|
||||
''')
|
||||
completed_process = run_cmd(f'vncserver -dry-run -test-output-topic validation -config {config_filename}')
|
||||
expect(completed_process.stderr).to(equal(''))
|
||||
|
||||
with it("produces an error for invalid boolean values"):
|
||||
write_config('''
|
||||
desktop:
|
||||
allow_resize: 10
|
||||
''')
|
||||
|
||||
completed_process = run_cmd(f'vncserver -dry-run -test-output-topic validation -config {config_filename}', print_stderr=False)
|
||||
expect(completed_process.stderr).to(contain("desktop.allow_resize '10': must be true or false"))
|
||||
|
||||
with it("produces an error for invalid enum value"):
|
||||
write_config('''
|
||||
desktop:
|
||||
pixel_depth: none
|
||||
''')
|
||||
|
||||
completed_process = run_cmd(f'vncserver -dry-run -test-output-topic validation -config {config_filename}', print_stderr=False)
|
||||
expect(completed_process.stderr).to(contain("desktop.pixel_depth 'none': must be one of [16, 24, 32]"))
|
||||
|
||||
with it("produces an error for invalid pattern enum value"):
|
||||
write_config('''
|
||||
desktop:
|
||||
pixel_depth: 16|24|32
|
||||
''')
|
||||
|
||||
completed_process = run_cmd(f'vncserver -dry-run -test-output-topic validation -config {config_filename}', print_stderr=False)
|
||||
expect(completed_process.stderr).to(contain("desktop.pixel_depth '16|24|32': must be one of [16, 24, 32]"))
|
||||
|
||||
with it("produces an error fo partially present enum value"):
|
||||
write_config('''
|
||||
network:
|
||||
protocol: vnc2
|
||||
''')
|
||||
|
||||
completed_process = run_cmd(f'vncserver -dry-run -test-output-topic validation -config {config_filename}', print_stderr=False)
|
||||
expect(completed_process.stderr).to(contain("network.protocol 'vnc2': must be one of [http, vnc]"))
|
||||
|
||||
with it("is silent for a valid enum value"):
|
||||
write_config('''
|
||||
desktop:
|
||||
pixel_depth: 16
|
||||
''')
|
||||
|
||||
completed_process = run_cmd(f'vncserver -dry-run -test-output-topic validation -config {config_filename}')
|
||||
expect(completed_process.stderr).to(equal(""))
|
||||
|
||||
with it("produces an error for an array value"):
|
||||
write_config('''
|
||||
keyboard:
|
||||
remap_keys:
|
||||
- 0xzz->0x40
|
||||
- 0x24->0x40
|
||||
''')
|
||||
|
||||
completed_process = run_cmd(f'vncserver -dry-run -test-output-topic validation -config {config_filename}', print_stderr=False)
|
||||
expect(completed_process.stderr).to(contain("keyboard.remap_keys '0xzz->0x40, 0x24->0x40': must be in the format 0x<hex_number>->0x<hex_number>"))
|
||||
|
||||
with context("unsupported keys"):
|
||||
with it("produces an error for an unsupported top-level key"):
|
||||
write_config('''
|
||||
foo: 1
|
||||
''')
|
||||
|
||||
completed_process = run_cmd(f'vncserver -dry-run -test-output-topic validation -config {config_filename}', print_stderr=False)
|
||||
expect(completed_process.stderr).to(
|
||||
contain("Unsupported config keys found:\nfoo"))
|
||||
|
||||
with it("produces an error for an unsupported 2nd-level key"):
|
||||
write_config('''
|
||||
bar:
|
||||
baz: 1
|
||||
''')
|
||||
|
||||
completed_process = run_cmd(f'vncserver -dry-run -test-output-topic validation -config {config_filename}', print_stderr=False)
|
||||
expect(completed_process.stderr).to(
|
||||
contain("Unsupported config keys found:\nbar.baz"))
|
||||
Reference in New Issue
Block a user