mirror of
https://github.com/MAGICGrants/truenas-apps.git
synced 2026-01-09 20:47:58 -05:00
Publish new changes in catalog [skip ci]
This commit is contained in:
@@ -13,8 +13,8 @@ icon: https://media.sys.truenas.net/apps/rust-desk/icons/icon.png
|
||||
keywords:
|
||||
- remote
|
||||
- desktop
|
||||
lib_version: 2.1.57
|
||||
lib_version_hash: 6659ad369fff2f1df318cb6353bb32bffe7047dc21df4823750d39be7284e605
|
||||
lib_version: 2.1.63
|
||||
lib_version_hash: ae27738f46453ea3e6b964592b2e8e1fea7adb0faf5808ffc5eea4690e6368e7
|
||||
maintainers:
|
||||
- email: dev@truenas.com
|
||||
name: truenas
|
||||
@@ -32,4 +32,4 @@ sources:
|
||||
- https://github.com/rustdesk/rustdesk-server
|
||||
title: Rust Desk
|
||||
train: community
|
||||
version: 1.2.11
|
||||
version: 1.3.0
|
||||
@@ -2,6 +2,9 @@ images:
|
||||
image:
|
||||
repository: rustdesk/rustdesk-server
|
||||
tag: 1.1.14
|
||||
pro_image:
|
||||
repository: rustdesk/rustdesk-server-pro
|
||||
tag: 1.7.1
|
||||
|
||||
consts:
|
||||
rust_desk_container_name: rust-desk
|
||||
@@ -19,6 +19,29 @@ questions:
|
||||
schema:
|
||||
type: dict
|
||||
attrs:
|
||||
- variable: image_selector
|
||||
label: Image Selector
|
||||
description: The image selector to use for Scrypted.
|
||||
schema:
|
||||
type: string
|
||||
default: image
|
||||
enum:
|
||||
- value: image
|
||||
description: OSS Image
|
||||
- value: pro_image
|
||||
description: Pro Image - Requires a paid license
|
||||
- variable: mac_address
|
||||
label: MAC Address
|
||||
description: |
|
||||
For licensing purposes, Rust Desk needs the MAC Address to tie the license to your server.</br>
|
||||
Format: XX:XX:XX:XX:XX:XX
|
||||
schema:
|
||||
type: string
|
||||
default: ""
|
||||
min_length: 17
|
||||
max_length: 17
|
||||
show_if: [["image_selector", "=", "pro_image"]]
|
||||
required: true
|
||||
- variable: allow_only_encrypted_connections
|
||||
label: Allow Only Encrypted Connections
|
||||
description: |
|
||||
@@ -100,6 +123,59 @@ questions:
|
||||
schema:
|
||||
type: boolean
|
||||
default: false
|
||||
- variable: webui_port
|
||||
label: Port for the webui
|
||||
description: |
|
||||
This port will be used to connect to the webui.</br>
|
||||
The internal port will always be 21114.</br>
|
||||
This is only available in the PRO version.
|
||||
schema:
|
||||
type: dict
|
||||
show_if: [["host_network", "=", false]]
|
||||
attrs:
|
||||
- variable: bind_mode
|
||||
label: Port Bind Mode
|
||||
description: |
|
||||
The port bind mode.</br>
|
||||
- Publish: The port will be published on the host for external access.</br>
|
||||
- Expose: The port will be exposed for inter-container communication.</br>
|
||||
- None: The port will not be exposed or published.</br>
|
||||
Note: If the Dockerfile defines an EXPOSE directive,
|
||||
the port will still be exposed for inter-container communication regardless of this setting.
|
||||
schema:
|
||||
type: string
|
||||
default: ""
|
||||
enum:
|
||||
- value: "published"
|
||||
description: Publish port on the host for external access
|
||||
- value: "exposed"
|
||||
description: Expose port for inter-container communication
|
||||
- value: ""
|
||||
description: None
|
||||
- variable: port_number
|
||||
label: Port Number
|
||||
schema:
|
||||
type: int
|
||||
show_if: [["bind_mode", "=", "published"]]
|
||||
default: 21114
|
||||
min: 1
|
||||
max: 65535
|
||||
required: true
|
||||
- variable: host_ips
|
||||
label: Host IPs
|
||||
description: IPs on the host to bind this port
|
||||
schema:
|
||||
type: list
|
||||
show_if: [["bind_mode", "=", "published"]]
|
||||
default: []
|
||||
items:
|
||||
- variable: host_ip
|
||||
label: Host IP
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
$ref:
|
||||
- definitions/node_bind_ip
|
||||
- variable: nat_type_test_port
|
||||
label: NAT Type Test Port
|
||||
description: |
|
||||
@@ -1,11 +1,18 @@
|
||||
{% set tpl = ix_lib.base.render.Render(values) %}
|
||||
|
||||
{% set server = tpl.add_container(values.consts.rust_desk_container_name, "image") %}
|
||||
{% set relay = tpl.add_container(values.consts.rust_desk_relay_container_name, "image") %}
|
||||
{% set server = tpl.add_container(values.consts.rust_desk_container_name, values.rust_desk.image_selector) %}
|
||||
{% set relay = tpl.add_container(values.consts.rust_desk_relay_container_name, values.rust_desk.image_selector) %}
|
||||
|
||||
{% set is_pro = values.rust_desk.image_selector == "pro_image" %}
|
||||
|
||||
{% set perm_container = tpl.deps.perms(values.consts.perms_container_name) %}
|
||||
{% set perms_config = {"uid": values.run_as.user, "gid": values.run_as.group, "mode": "check"} %}
|
||||
|
||||
{% if is_pro %}
|
||||
{% do server.set_mac(values.rust_desk.mac_address) %}
|
||||
{% do relay.set_mac(values.rust_desk.mac_address) %}
|
||||
{% endif %}
|
||||
|
||||
{% do server.set_user(values.run_as.user, values.run_as.group) %}
|
||||
{% do relay.set_user(values.run_as.user, values.run_as.group) %}
|
||||
|
||||
@@ -29,6 +36,7 @@
|
||||
{% do relay.environment.add_user_envs(values.rust_desk.additional_envs) %}
|
||||
|
||||
{% if not values.network.host_network %}
|
||||
{% if is_pro %}{% do server.add_port(values.network.webui_port, {"container_port": 21114}) %}{% endif %}
|
||||
{% do server.add_port(values.network.nat_type_test_port, {"container_port": 21115}) %}
|
||||
{% do server.add_port(values.network.id_reg_hole_punch_port, {"container_port": 21116}) %}
|
||||
{% do server.add_port(values.network.id_reg_hole_punch_port, {"container_port": 21116, "protocol": "udp"}) %}
|
||||
@@ -59,4 +67,6 @@
|
||||
{% do relay.depends.add_dependency(values.consts.perms_container_name, "service_completed_successfully") %}
|
||||
{% endif %}
|
||||
|
||||
{% if is_pro %}{% do tpl.portals.add(values.network.web_port) %}{% endif %}
|
||||
|
||||
{{ tpl.render() | tojson }}
|
||||
@@ -25,6 +25,7 @@ try:
|
||||
valid_cap_or_raise,
|
||||
valid_cgroup_or_raise,
|
||||
valid_ipc_mode_or_raise,
|
||||
valid_mac_or_raise,
|
||||
valid_network_mode_or_raise,
|
||||
valid_pid_mode_or_raise,
|
||||
valid_port_bind_mode_or_raise,
|
||||
@@ -55,6 +56,7 @@ except ImportError:
|
||||
valid_cap_or_raise,
|
||||
valid_cgroup_or_raise,
|
||||
valid_ipc_mode_or_raise,
|
||||
valid_mac_or_raise,
|
||||
valid_network_mode_or_raise,
|
||||
valid_pid_mode_or_raise,
|
||||
valid_port_bind_mode_or_raise,
|
||||
@@ -95,6 +97,7 @@ class Container:
|
||||
self._tmpfs: Tmpfs = Tmpfs(self._render_instance, self)
|
||||
self._ipc_mode: str | None = None
|
||||
self._pid_mode: str | None = None
|
||||
self.mac_address: str | None = None
|
||||
self._cgroup: str | None = None
|
||||
self._device_cgroup_rules: DeviceCGroupRules = DeviceCGroupRules(self._render_instance)
|
||||
self.sysctls: Sysctls = Sysctls(self._render_instance, self)
|
||||
@@ -223,6 +226,10 @@ class Container:
|
||||
def set_cgroup(self, cgroup: str):
|
||||
self._cgroup = valid_cgroup_or_raise(cgroup)
|
||||
|
||||
def set_mac(self, mac_address: str):
|
||||
valid_mac_or_raise(mac_address)
|
||||
self.mac_address = mac_address
|
||||
|
||||
def set_init(self, enabled: bool = False):
|
||||
self._init = enabled
|
||||
|
||||
@@ -377,6 +384,9 @@ class Container:
|
||||
if self._cgroup is not None:
|
||||
result["cgroup"] = self._cgroup
|
||||
|
||||
if self.mac_address is not None:
|
||||
result["mac_address"] = self.mac_address
|
||||
|
||||
if self._extra_hosts.has_hosts():
|
||||
result["extra_hosts"] = self._extra_hosts.render()
|
||||
|
||||
@@ -12,6 +12,7 @@ try:
|
||||
from .deps_postgres import PostgresContainer, PostgresConfig
|
||||
from .deps_redis import RedisContainer, RedisConfig
|
||||
from .deps_solr import SolrContainer, SolrConfig
|
||||
from .deps_tika import TikaContainer, TikaConfig
|
||||
except ImportError:
|
||||
from deps_elastic import ElasticSearchContainer, ElasticConfig
|
||||
from deps_mariadb import MariadbContainer, MariadbConfig
|
||||
@@ -21,6 +22,7 @@ except ImportError:
|
||||
from deps_postgres import PostgresContainer, PostgresConfig
|
||||
from deps_redis import RedisContainer, RedisConfig
|
||||
from deps_solr import SolrContainer, SolrConfig
|
||||
from deps_tika import TikaContainer, TikaConfig
|
||||
|
||||
|
||||
class Deps:
|
||||
@@ -50,3 +52,6 @@ class Deps:
|
||||
|
||||
def solr(self, name: str, image: str, config: SolrConfig, perms_instance: PermsContainer):
|
||||
return SolrContainer(self._render_instance, name, image, config, perms_instance)
|
||||
|
||||
def tika(self, name: str, image: str, config: TikaConfig):
|
||||
return TikaContainer(self._render_instance, name, image, config)
|
||||
@@ -37,7 +37,13 @@ class MongoDBContainer:
|
||||
|
||||
c = self._render_instance.add_container(name, image)
|
||||
|
||||
c.set_user(999, 999)
|
||||
user, group = 568, 568
|
||||
run_as = self._render_instance.values.get("run_as")
|
||||
if run_as:
|
||||
user = run_as["user"] or user # Avoids running as root
|
||||
group = run_as["group"] or group # Avoids running as root
|
||||
|
||||
c.set_user(user, group)
|
||||
c.healthcheck.set_test("mongodb", {"db": config["database"]})
|
||||
c.remove_devices()
|
||||
c.add_storage(self._data_dir, config["volume"])
|
||||
@@ -47,7 +53,7 @@ class MongoDBContainer:
|
||||
c.environment.add_env("MONGO_INITDB_DATABASE", config["database"])
|
||||
|
||||
perms_instance.add_or_skip_action(
|
||||
f"{self._name}_mongodb_data", config["volume"], {"uid": 999, "gid": 999, "mode": "check"}
|
||||
f"{self._name}_mongodb_data", config["volume"], {"uid": user, "gid": group, "mode": "check"}
|
||||
)
|
||||
|
||||
self._get_repo(image, ("mongodb"))
|
||||
@@ -0,0 +1,63 @@
|
||||
from typing import TYPE_CHECKING, TypedDict, NotRequired
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from render import Render
|
||||
|
||||
|
||||
try:
|
||||
from .error import RenderError
|
||||
except ImportError:
|
||||
from error import RenderError
|
||||
|
||||
|
||||
class TikaConfig(TypedDict):
|
||||
port: NotRequired[int]
|
||||
|
||||
|
||||
class TikaContainer:
|
||||
def __init__(self, render_instance: "Render", name: str, image: str, config: TikaConfig):
|
||||
self._render_instance = render_instance
|
||||
self._name = name
|
||||
self._config = config
|
||||
|
||||
c = self._render_instance.add_container(name, image)
|
||||
|
||||
user, group = 568, 568
|
||||
run_as = self._render_instance.values.get("run_as")
|
||||
if run_as:
|
||||
user = run_as["user"] or user # Avoids running as root
|
||||
group = run_as["group"] or group # Avoids running as root
|
||||
|
||||
c.set_user(user, group)
|
||||
c.healthcheck.set_test("wget", {"port": self.get_port(), "path": "/tika", "spider": False})
|
||||
c.remove_devices()
|
||||
|
||||
c.set_command(["--port", str(self.get_port())])
|
||||
|
||||
self._get_repo(image, ("apache/tika"))
|
||||
|
||||
# Store container for further configuration
|
||||
# For example: c.depends.add_dependency("other_container", "service_started")
|
||||
self._container = c
|
||||
|
||||
@property
|
||||
def container(self):
|
||||
return self._container
|
||||
|
||||
def _get_repo(self, image, supported_repos):
|
||||
images = self._render_instance.values["images"]
|
||||
if image not in images:
|
||||
raise RenderError(f"Image [{image}] not found in values. Available images: [{', '.join(images.keys())}]")
|
||||
repo = images[image].get("repository")
|
||||
if not repo:
|
||||
raise RenderError("Could not determine repo")
|
||||
if repo not in supported_repos:
|
||||
raise RenderError(f"Unsupported repo [{repo}] for tika. Supported repos: {', '.join(supported_repos)}")
|
||||
return repo
|
||||
|
||||
def get_port(self):
|
||||
return self._config.get("port") or 9998
|
||||
|
||||
def get_url(self):
|
||||
return f"http://{self._name}:{self.get_port()}"
|
||||
@@ -24,6 +24,7 @@ class Environment:
|
||||
self._app_dev_variables: dict[str, Any] = {}
|
||||
|
||||
self._skip_generic_variables: bool = render_instance.values.get("skip_generic_variables", False)
|
||||
self._skip_id_variables: bool = render_instance.values.get("skip_id_variables", False)
|
||||
|
||||
self._auto_add_variables_from_values()
|
||||
|
||||
@@ -65,6 +66,12 @@ class Environment:
|
||||
value = value.lower()
|
||||
return value
|
||||
|
||||
def remove_auto_env(self, name: str):
|
||||
if name in self._auto_variables.keys():
|
||||
del self._auto_variables[name]
|
||||
return
|
||||
raise RenderError(f"Environment variable [{name}] is not defined.")
|
||||
|
||||
def add_env(self, name: str, value: Any):
|
||||
if not name:
|
||||
raise RenderError(f"Environment variable name cannot be empty. [{name}]")
|
||||
@@ -1,5 +1,6 @@
|
||||
import re
|
||||
import copy
|
||||
import yaml
|
||||
import bcrypt
|
||||
import secrets
|
||||
import urllib.parse
|
||||
@@ -21,6 +22,9 @@ class Functions:
|
||||
def __init__(self, render_instance: "Render"):
|
||||
self._render_instance = render_instance
|
||||
|
||||
def _to_yaml(self, data):
|
||||
return yaml.dump(data)
|
||||
|
||||
def _bcrypt_hash(self, password):
|
||||
hashed = bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt()).decode("utf-8")
|
||||
return hashed
|
||||
@@ -120,6 +124,7 @@ class Functions:
|
||||
"scheme": parsed.scheme,
|
||||
"host": parsed.hostname,
|
||||
"port": parsed.port,
|
||||
"path": parsed.path,
|
||||
}
|
||||
if v6_brackets and parsed.hostname and ":" in parsed.hostname:
|
||||
result["host"] = f"[{parsed.hostname}]"
|
||||
@@ -209,4 +214,5 @@ class Functions:
|
||||
"require_no_reserved": self._require_no_reserved,
|
||||
"url_encode": self._url_encode,
|
||||
"url_to_dict": self._url_to_dict,
|
||||
"to_yaml": self._to_yaml,
|
||||
}
|
||||
@@ -458,6 +458,23 @@ def test_set_cgroup_invalid(mock_values):
|
||||
c1.set_cgroup("invalid")
|
||||
|
||||
|
||||
def test_set_mac_invalid(mock_values):
|
||||
render = Render(mock_values)
|
||||
c1 = render.add_container("test_container", "test_image")
|
||||
c1.healthcheck.disable()
|
||||
with pytest.raises(Exception):
|
||||
c1.set_mac("invalid_mac")
|
||||
|
||||
|
||||
def test_set_mac_valid(mock_values):
|
||||
render = Render(mock_values)
|
||||
c1 = render.add_container("test_container", "test_image")
|
||||
c1.healthcheck.disable()
|
||||
c1.set_mac("00:00:00:00:00:00")
|
||||
output = render.render()
|
||||
assert output["services"]["test_container"]["mac_address"] == "00:00:00:00:00:00"
|
||||
|
||||
|
||||
def test_setup_as_helper(mock_values):
|
||||
mock_values["resources"] = {"gpus": {"use_all_gpus": True}}
|
||||
render = Render(mock_values)
|
||||
@@ -620,7 +620,7 @@ def test_add_mongodb(mock_values):
|
||||
assert "devices" not in output["services"]["mongodb_container"]
|
||||
assert "reservations" not in output["services"]["mongodb_container"]["deploy"]["resources"]
|
||||
assert output["services"]["mongodb_container"]["image"] == "mongodb:latest"
|
||||
assert output["services"]["mongodb_container"]["user"] == "999:999"
|
||||
assert output["services"]["mongodb_container"]["user"] == "568:568"
|
||||
assert output["services"]["mongodb_container"]["deploy"]["resources"]["limits"]["cpus"] == "2.0"
|
||||
assert output["services"]["mongodb_container"]["deploy"]["resources"]["limits"]["memory"] == "4096M"
|
||||
assert output["services"]["mongodb_container"]["healthcheck"] == {
|
||||
@@ -952,3 +952,59 @@ def test_add_solr_unsupported_repo(mock_values):
|
||||
},
|
||||
perms_container,
|
||||
)
|
||||
|
||||
|
||||
def test_add_tika(mock_values):
|
||||
mock_values["images"]["tika_image"] = {"repository": "apache/tika", "tag": "3.2.3.0-full"}
|
||||
render = Render(mock_values)
|
||||
c1 = render.add_container("test_container", "test_image")
|
||||
c1.healthcheck.disable()
|
||||
render.deps.tika(
|
||||
"tika_container",
|
||||
"tika_image",
|
||||
{
|
||||
"port": 10999,
|
||||
},
|
||||
)
|
||||
output = render.render()
|
||||
assert "devices" not in output["services"]["tika_container"]
|
||||
assert "reservations" not in output["services"]["tika_container"]["deploy"]["resources"]
|
||||
assert output["services"]["tika_container"]["image"] == "apache/tika:3.2.3.0-full"
|
||||
assert output["services"]["tika_container"]["user"] == "568:568"
|
||||
assert output["services"]["tika_container"]["deploy"]["resources"]["limits"]["cpus"] == "2.0"
|
||||
assert output["services"]["tika_container"]["deploy"]["resources"]["limits"]["memory"] == "4096M"
|
||||
assert output["services"]["tika_container"]["healthcheck"] == {
|
||||
"test": [
|
||||
"CMD",
|
||||
"wget",
|
||||
"--quiet",
|
||||
"-O",
|
||||
"/dev/null",
|
||||
"http://127.0.0.1:10999/tika",
|
||||
],
|
||||
"interval": "30s",
|
||||
"timeout": "5s",
|
||||
"retries": 5,
|
||||
"start_period": "15s",
|
||||
"start_interval": "2s",
|
||||
}
|
||||
assert output["services"]["tika_container"]["environment"] == {
|
||||
"TZ": "Etc/UTC",
|
||||
"UMASK": "002",
|
||||
"UMASK_SET": "002",
|
||||
"NVIDIA_VISIBLE_DEVICES": "void",
|
||||
}
|
||||
assert output["services"]["tika_container"]["command"] == ["--port", "10999"]
|
||||
|
||||
|
||||
def test_add_tika_unsupported_repo(mock_values):
|
||||
mock_values["images"]["tika_image"] = {"repository": "unsupported_repo", "tag": "7"}
|
||||
render = Render(mock_values)
|
||||
c1 = render.add_container("test_container", "test_image")
|
||||
c1.healthcheck.disable()
|
||||
with pytest.raises(Exception):
|
||||
render.deps.tika(
|
||||
"tika_container",
|
||||
"tika_image",
|
||||
{},
|
||||
)
|
||||
@@ -49,6 +49,7 @@ def test_auto_add_vars(mock_values):
|
||||
|
||||
def test_skip_generic_variables(mock_values):
|
||||
mock_values["skip_generic_variables"] = True
|
||||
mock_values["run_as"] = {"user": "1000", "group": "1000"}
|
||||
render = Render(mock_values)
|
||||
c1 = render.add_container("test_container", "test_image")
|
||||
c1.healthcheck.disable()
|
||||
@@ -56,7 +57,29 @@ def test_skip_generic_variables(mock_values):
|
||||
envs = output["services"]["test_container"]["environment"]
|
||||
|
||||
assert len(envs) == 1
|
||||
assert envs["NVIDIA_VISIBLE_DEVICES"] == "void"
|
||||
assert envs == {
|
||||
"NVIDIA_VISIBLE_DEVICES": "void",
|
||||
}
|
||||
|
||||
|
||||
def test_remove_auto_env(mock_values):
|
||||
mock_values["run_as"] = {"user": "1000", "group": "1000"}
|
||||
render = Render(mock_values)
|
||||
c1 = render.add_container("test_container", "test_image")
|
||||
c1.healthcheck.disable()
|
||||
c1.environment.remove_auto_env("UID")
|
||||
|
||||
output = render.render()
|
||||
envs = output["services"]["test_container"]["environment"]
|
||||
assert "UID" not in envs
|
||||
|
||||
|
||||
def test_remove_env_not_defined(mock_values):
|
||||
render = Render(mock_values)
|
||||
c1 = render.add_container("test_container", "test_image")
|
||||
c1.healthcheck.disable()
|
||||
with pytest.raises(Exception):
|
||||
c1.environment.remove_auto_env("NOT_DEFINED")
|
||||
|
||||
|
||||
def test_add_from_all_sources(mock_values):
|
||||
@@ -105,24 +105,36 @@ def test_funcs(mock_values):
|
||||
{
|
||||
"func": "url_to_dict",
|
||||
"values": ["192.168.1.1:8080"],
|
||||
"expected": {"host": "192.168.1.1", "port": 8080, "scheme": "http", "netloc": "192.168.1.1:8080"},
|
||||
"expected": {
|
||||
"host": "192.168.1.1",
|
||||
"port": 8080,
|
||||
"scheme": "http",
|
||||
"netloc": "192.168.1.1:8080",
|
||||
"path": "",
|
||||
},
|
||||
},
|
||||
{
|
||||
"func": "url_to_dict",
|
||||
"values": ["[::]:8080"],
|
||||
"expected": {"host": "::", "port": 8080, "scheme": "http", "netloc": "[::]:8080"},
|
||||
"expected": {"host": "::", "port": 8080, "scheme": "http", "netloc": "[::]:8080", "path": ""},
|
||||
},
|
||||
{
|
||||
"func": "url_to_dict",
|
||||
"values": ["[::]:8080", True],
|
||||
"values": ["[::]:8080/abc/", True],
|
||||
"expected": {
|
||||
"host": "[::]",
|
||||
"port": 8080,
|
||||
"host_no_brackets": "::",
|
||||
"scheme": "http",
|
||||
"netloc": "[::]:8080",
|
||||
"path": "/abc/",
|
||||
},
|
||||
},
|
||||
{
|
||||
"func": "to_yaml",
|
||||
"values": [{"a": 1, "b": 2}],
|
||||
"expected": "a: 1\nb: 2\n",
|
||||
},
|
||||
]
|
||||
|
||||
for test in tests:
|
||||
@@ -8,6 +8,8 @@ try:
|
||||
except ImportError:
|
||||
from error import RenderError
|
||||
|
||||
MAC_ADDR_REGEX = re.compile(r"^([0-9A-Fa-f]{2}:){5}([0-9A-Fa-f]{2})$")
|
||||
|
||||
OCTAL_MODE_REGEX = re.compile(r"^0[0-7]{3}$")
|
||||
RESTRICTED_IN: tuple[Path, ...] = (Path("/mnt"), Path("/"))
|
||||
RESTRICTED: tuple[Path, ...] = (
|
||||
@@ -24,6 +26,12 @@ RESTRICTED: tuple[Path, ...] = (
|
||||
)
|
||||
|
||||
|
||||
def valid_mac_or_raise(mac: str):
|
||||
if MAC_ADDR_REGEX.match(mac):
|
||||
return mac
|
||||
raise RenderError(f"Invalid MAC Address [{mac}], valid format is either XX:XX:XX:XX:XX:XX")
|
||||
|
||||
|
||||
def valid_security_opt_or_raise(opt: str):
|
||||
if ":" in opt or "=" in opt:
|
||||
raise RenderError(f"Security Option [{opt}] cannot contain [:] or [=]. Pass value as an argument")
|
||||
@@ -101,9 +101,6 @@ class CifsVolume:
|
||||
raise RenderError(f"Option [{key}] already added for [cifs] type.")
|
||||
if key in disallowed_opts:
|
||||
raise RenderError(f"Option [{key}] is not allowed for [cifs] type.")
|
||||
for disallowed in disallowed_opts:
|
||||
if key == disallowed:
|
||||
raise RenderError(f"Option [{key}] is not allowed for [cifs] type.")
|
||||
opts.append(opt)
|
||||
tracked_keys.add(key)
|
||||
opts.sort()
|
||||
@@ -4,6 +4,8 @@ resources:
|
||||
memory: 4096
|
||||
|
||||
rust_desk:
|
||||
image_selector: "image"
|
||||
# mac_address: "02:42:ac:11:00:02" # Optional MAC address for PRO edition
|
||||
allow_only_encrypted_connections: false
|
||||
additional_relay_servers: []
|
||||
additional_envs: []
|
||||
Reference in New Issue
Block a user