diff --git a/ix-dev/community/actual-budget/app.yaml b/ix-dev/community/actual-budget/app.yaml index 99f80ee686..da8b9200ea 100644 --- a/ix-dev/community/actual-budget/app.yaml +++ b/ix-dev/community/actual-budget/app.yaml @@ -10,8 +10,8 @@ icon: https://media.sys.truenas.net/apps/actual-budget/icons/icon.png keywords: - finance - budget -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -33,4 +33,4 @@ sources: - https://hub.docker.com/r/actualbudget/actual-server title: Actual Budget train: community -version: 1.1.12 +version: 1.1.13 diff --git a/ix-dev/community/actual-budget/templates/docker-compose.yaml b/ix-dev/community/actual-budget/templates/docker-compose.yaml index 4c17f83ffc..acaacce96d 100644 --- a/ix-dev/community/actual-budget/templates/docker-compose.yaml +++ b/ix-dev/community/actual-budget/templates/docker-compose.yaml @@ -64,7 +64,7 @@ services: {% if values.network.dns_opts %} dns_opt: {{ ix_lib.base.network.dns_opts(values.network.dns_opts) | tojson }} {% endif %} - {% set test = ix_lib.base.healthchecks.http_test(path="/health", port=values.network.web_port) %} + {% set test = "NODE_TLS_REJECT_UNAUTHORIZED=0 npm run health-check" %} healthcheck: {{ ix_lib.base.healthchecks.check_health(test) | tojson }} {% set app_env = { "ACTUAL_PORT": values.network.web_port, diff --git a/ix-dev/community/actual-budget/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/actual-budget/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/actual-budget/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/actual-budget/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/actual-budget/templates/library/base_v1_1_3/environment.py b/ix-dev/community/actual-budget/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/actual-budget/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/actual-budget/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/actual-budget/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/actual-budget/templates/library/base_v1_1_4/healthchecks.py similarity index 92% rename from ix-dev/community/actual-budget/templates/library/base_v1_1_3/healthchecks.py rename to ix-dev/community/actual-budget/templates/library/base_v1_1_4/healthchecks.py index 09f8ac53fd..cc98270d1d 100644 --- a/ix-dev/community/actual-budget/templates/library/base_v1_1_3/healthchecks.py +++ b/ix-dev/community/actual-budget/templates/library/base_v1_1_4/healthchecks.py @@ -95,10 +95,9 @@ def http_test(port, path, config=None): host = config.get("host", "127.0.0.1") - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa def netcat_test(port, config=None): diff --git a/ix-dev/community/actual-budget/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/actual-budget/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/actual-budget/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/actual-budget/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/actual-budget/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/actual-budget/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/actual-budget/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/actual-budget/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/actual-budget/templates/library/base_v1_1_3/network.py b/ix-dev/community/actual-budget/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/actual-budget/templates/library/base_v1_1_3/network.py rename to ix-dev/community/actual-budget/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/audiobookshelf/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/actual-budget/templates/library/base_v1_1_4/permissions.py similarity index 98% rename from ix-dev/community/audiobookshelf/templates/library/base_v1_1_3/permissions.py rename to ix-dev/community/actual-budget/templates/library/base_v1_1_4/permissions.py index 7d98983af6..1ce6e60ca1 100644 --- a/ix-dev/community/audiobookshelf/templates/library/base_v1_1_3/permissions.py +++ b/ix-dev/community/actual-budget/templates/library/base_v1_1_4/permissions.py @@ -70,12 +70,12 @@ def process_dir_shell_func(): if [ -z "$$dir" ]; then echo "Path is empty, skipping..." - exit 0 + return 0 fi if [ ! -d "$$dir" ]; then echo "Path [$$dir] does is not a directory, skipping..." - exit 0 + return 0 fi if [ "$$is_temporary" = "true" ]; then @@ -86,7 +86,7 @@ def process_dir_shell_func(): if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then echo "Path [$$dir] is not empty, skipping..." - exit 0 + return 0 fi echo "Current Ownership and Permissions on [$$dir]:" diff --git a/ix-dev/community/actual-budget/templates/library/base_v1_1_3/ports.py b/ix-dev/community/actual-budget/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/actual-budget/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/actual-budget/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/actual-budget/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/actual-budget/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/actual-budget/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/actual-budget/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/actual-budget/templates/library/base_v1_1_3/redis.py b/ix-dev/community/actual-budget/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/actual-budget/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/actual-budget/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/actual-budget/templates/library/base_v1_1_3/resources.py b/ix-dev/community/actual-budget/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/actual-budget/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/actual-budget/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/actual-budget/templates/library/base_v1_1_3/security.py b/ix-dev/community/actual-budget/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/actual-budget/templates/library/base_v1_1_3/security.py rename to ix-dev/community/actual-budget/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/actual-budget/templates/library/base_v1_1_3/storage.py b/ix-dev/community/actual-budget/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/actual-budget/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/actual-budget/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/actual-budget/templates/library/base_v1_1_3/utils.py b/ix-dev/community/actual-budget/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/actual-budget/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/actual-budget/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/adguard-home/app.yaml b/ix-dev/community/adguard-home/app.yaml index 70dc200215..d653369b6c 100644 --- a/ix-dev/community/adguard-home/app.yaml +++ b/ix-dev/community/adguard-home/app.yaml @@ -18,8 +18,8 @@ icon: https://media.sys.truenas.net/apps/adguard-home/icons/icon.svg keywords: - dns - adblock -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -40,4 +40,4 @@ sources: - https://hub.docker.com/r/adguard/adguardhome title: AdGuard Home train: community -version: 1.0.21 +version: 1.0.22 diff --git a/ix-dev/community/adguard-home/templates/docker-compose.yaml b/ix-dev/community/adguard-home/templates/docker-compose.yaml index b179fa3472..a05d314666 100644 --- a/ix-dev/community/adguard-home/templates/docker-compose.yaml +++ b/ix-dev/community/adguard-home/templates/docker-compose.yaml @@ -49,7 +49,7 @@ services: {% if values.network.dns_opts %} dns_opt: {{ ix_lib.base.network.dns_opts(values.network.dns_opts) | tojson }} {% endif %} - {% set test = ix_lib.base.healthchecks.wget_test(port=values.network.web_port, path="/health-check", config={"scheme": "https" if values.adguard.use_https_probe else "http"}) %} + {% set test = ix_lib.base.healthchecks.wget_test(port=values.network.web_port, path="/", config={"scheme": "https" if values.adguard.use_https_probe else "http"}) %} healthcheck: {{ ix_lib.base.healthchecks.check_health(test) | tojson }} environment: {{ ix_lib.base.environment.envs(app={}, user=values.adguard.additional_envs,values=values) | tojson }} {% if not values.network.host_network and not values.network.dhcp_enabled %} diff --git a/ix-dev/community/adguard-home/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/adguard-home/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/adguard-home/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/adguard-home/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/adguard-home/templates/library/base_v1_1_3/environment.py b/ix-dev/community/adguard-home/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/adguard-home/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/adguard-home/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/audiobookshelf/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/adguard-home/templates/library/base_v1_1_4/healthchecks.py similarity index 92% rename from ix-dev/community/audiobookshelf/templates/library/base_v1_1_3/healthchecks.py rename to ix-dev/community/adguard-home/templates/library/base_v1_1_4/healthchecks.py index 09f8ac53fd..cc98270d1d 100644 --- a/ix-dev/community/audiobookshelf/templates/library/base_v1_1_3/healthchecks.py +++ b/ix-dev/community/adguard-home/templates/library/base_v1_1_4/healthchecks.py @@ -95,10 +95,9 @@ def http_test(port, path, config=None): host = config.get("host", "127.0.0.1") - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa def netcat_test(port, config=None): diff --git a/ix-dev/community/adguard-home/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/adguard-home/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/adguard-home/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/adguard-home/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/adguard-home/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/adguard-home/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/adguard-home/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/adguard-home/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/adguard-home/templates/library/base_v1_1_3/network.py b/ix-dev/community/adguard-home/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/adguard-home/templates/library/base_v1_1_3/network.py rename to ix-dev/community/adguard-home/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/actual-budget/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/adguard-home/templates/library/base_v1_1_4/permissions.py similarity index 98% rename from ix-dev/community/actual-budget/templates/library/base_v1_1_3/permissions.py rename to ix-dev/community/adguard-home/templates/library/base_v1_1_4/permissions.py index 7d98983af6..1ce6e60ca1 100644 --- a/ix-dev/community/actual-budget/templates/library/base_v1_1_3/permissions.py +++ b/ix-dev/community/adguard-home/templates/library/base_v1_1_4/permissions.py @@ -70,12 +70,12 @@ def process_dir_shell_func(): if [ -z "$$dir" ]; then echo "Path is empty, skipping..." - exit 0 + return 0 fi if [ ! -d "$$dir" ]; then echo "Path [$$dir] does is not a directory, skipping..." - exit 0 + return 0 fi if [ "$$is_temporary" = "true" ]; then @@ -86,7 +86,7 @@ def process_dir_shell_func(): if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then echo "Path [$$dir] is not empty, skipping..." - exit 0 + return 0 fi echo "Current Ownership and Permissions on [$$dir]:" diff --git a/ix-dev/community/adguard-home/templates/library/base_v1_1_3/ports.py b/ix-dev/community/adguard-home/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/adguard-home/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/adguard-home/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/adguard-home/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/adguard-home/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/adguard-home/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/adguard-home/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/adguard-home/templates/library/base_v1_1_3/redis.py b/ix-dev/community/adguard-home/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/adguard-home/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/adguard-home/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/adguard-home/templates/library/base_v1_1_3/resources.py b/ix-dev/community/adguard-home/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/adguard-home/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/adguard-home/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/adguard-home/templates/library/base_v1_1_3/security.py b/ix-dev/community/adguard-home/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/adguard-home/templates/library/base_v1_1_3/security.py rename to ix-dev/community/adguard-home/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/adguard-home/templates/library/base_v1_1_3/storage.py b/ix-dev/community/adguard-home/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/adguard-home/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/adguard-home/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/adguard-home/templates/library/base_v1_1_3/utils.py b/ix-dev/community/adguard-home/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/adguard-home/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/adguard-home/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/audiobookshelf/app.yaml b/ix-dev/community/audiobookshelf/app.yaml index 29a7d316b3..5aab58c295 100644 --- a/ix-dev/community/audiobookshelf/app.yaml +++ b/ix-dev/community/audiobookshelf/app.yaml @@ -9,8 +9,8 @@ icon: https://media.sys.truenas.net/apps/audiobookshelf/icons/icon.svg keywords: - media - audiobook -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -33,4 +33,4 @@ sources: - https://github.com/advplyr/audiobookshelf title: Audiobookshelf train: community -version: 1.2.13 +version: 1.2.14 diff --git a/ix-dev/community/audiobookshelf/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/audiobookshelf/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/audiobookshelf/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/audiobookshelf/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/audiobookshelf/templates/library/base_v1_1_3/environment.py b/ix-dev/community/audiobookshelf/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/audiobookshelf/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/audiobookshelf/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/adguard-home/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/audiobookshelf/templates/library/base_v1_1_4/healthchecks.py similarity index 92% rename from ix-dev/community/adguard-home/templates/library/base_v1_1_3/healthchecks.py rename to ix-dev/community/audiobookshelf/templates/library/base_v1_1_4/healthchecks.py index 09f8ac53fd..cc98270d1d 100644 --- a/ix-dev/community/adguard-home/templates/library/base_v1_1_3/healthchecks.py +++ b/ix-dev/community/audiobookshelf/templates/library/base_v1_1_4/healthchecks.py @@ -95,10 +95,9 @@ def http_test(port, path, config=None): host = config.get("host", "127.0.0.1") - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa def netcat_test(port, config=None): diff --git a/ix-dev/community/audiobookshelf/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/audiobookshelf/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/audiobookshelf/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/audiobookshelf/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/audiobookshelf/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/audiobookshelf/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/audiobookshelf/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/audiobookshelf/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/audiobookshelf/templates/library/base_v1_1_3/network.py b/ix-dev/community/audiobookshelf/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/audiobookshelf/templates/library/base_v1_1_3/network.py rename to ix-dev/community/audiobookshelf/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/autobrr/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/audiobookshelf/templates/library/base_v1_1_4/permissions.py similarity index 98% rename from ix-dev/community/autobrr/templates/library/base_v1_1_3/permissions.py rename to ix-dev/community/audiobookshelf/templates/library/base_v1_1_4/permissions.py index 7d98983af6..1ce6e60ca1 100644 --- a/ix-dev/community/autobrr/templates/library/base_v1_1_3/permissions.py +++ b/ix-dev/community/audiobookshelf/templates/library/base_v1_1_4/permissions.py @@ -70,12 +70,12 @@ def process_dir_shell_func(): if [ -z "$$dir" ]; then echo "Path is empty, skipping..." - exit 0 + return 0 fi if [ ! -d "$$dir" ]; then echo "Path [$$dir] does is not a directory, skipping..." - exit 0 + return 0 fi if [ "$$is_temporary" = "true" ]; then @@ -86,7 +86,7 @@ def process_dir_shell_func(): if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then echo "Path [$$dir] is not empty, skipping..." - exit 0 + return 0 fi echo "Current Ownership and Permissions on [$$dir]:" diff --git a/ix-dev/community/audiobookshelf/templates/library/base_v1_1_3/ports.py b/ix-dev/community/audiobookshelf/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/audiobookshelf/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/audiobookshelf/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/audiobookshelf/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/audiobookshelf/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/audiobookshelf/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/audiobookshelf/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/audiobookshelf/templates/library/base_v1_1_3/redis.py b/ix-dev/community/audiobookshelf/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/audiobookshelf/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/audiobookshelf/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/audiobookshelf/templates/library/base_v1_1_3/resources.py b/ix-dev/community/audiobookshelf/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/audiobookshelf/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/audiobookshelf/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/audiobookshelf/templates/library/base_v1_1_3/security.py b/ix-dev/community/audiobookshelf/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/audiobookshelf/templates/library/base_v1_1_3/security.py rename to ix-dev/community/audiobookshelf/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/audiobookshelf/templates/library/base_v1_1_3/storage.py b/ix-dev/community/audiobookshelf/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/audiobookshelf/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/audiobookshelf/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/audiobookshelf/templates/library/base_v1_1_3/utils.py b/ix-dev/community/audiobookshelf/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/audiobookshelf/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/audiobookshelf/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/autobrr/app.yaml b/ix-dev/community/autobrr/app.yaml index 9991351820..e28be7bae6 100644 --- a/ix-dev/community/autobrr/app.yaml +++ b/ix-dev/community/autobrr/app.yaml @@ -10,8 +10,8 @@ keywords: - media - torrent - usenet -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -31,4 +31,4 @@ sources: - https://github.com/autobrr/autobrr title: Autobrr train: community -version: 1.1.13 +version: 1.1.14 diff --git a/ix-dev/community/autobrr/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/autobrr/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/autobrr/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/autobrr/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/autobrr/templates/library/base_v1_1_3/environment.py b/ix-dev/community/autobrr/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/autobrr/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/autobrr/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/autobrr/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/autobrr/templates/library/base_v1_1_4/healthchecks.py similarity index 92% rename from ix-dev/community/autobrr/templates/library/base_v1_1_3/healthchecks.py rename to ix-dev/community/autobrr/templates/library/base_v1_1_4/healthchecks.py index 09f8ac53fd..cc98270d1d 100644 --- a/ix-dev/community/autobrr/templates/library/base_v1_1_3/healthchecks.py +++ b/ix-dev/community/autobrr/templates/library/base_v1_1_4/healthchecks.py @@ -95,10 +95,9 @@ def http_test(port, path, config=None): host = config.get("host", "127.0.0.1") - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa def netcat_test(port, config=None): diff --git a/ix-dev/community/autobrr/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/autobrr/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/autobrr/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/autobrr/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/autobrr/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/autobrr/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/autobrr/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/autobrr/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/autobrr/templates/library/base_v1_1_3/network.py b/ix-dev/community/autobrr/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/autobrr/templates/library/base_v1_1_3/network.py rename to ix-dev/community/autobrr/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/adguard-home/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/autobrr/templates/library/base_v1_1_4/permissions.py similarity index 98% rename from ix-dev/community/adguard-home/templates/library/base_v1_1_3/permissions.py rename to ix-dev/community/autobrr/templates/library/base_v1_1_4/permissions.py index 7d98983af6..1ce6e60ca1 100644 --- a/ix-dev/community/adguard-home/templates/library/base_v1_1_3/permissions.py +++ b/ix-dev/community/autobrr/templates/library/base_v1_1_4/permissions.py @@ -70,12 +70,12 @@ def process_dir_shell_func(): if [ -z "$$dir" ]; then echo "Path is empty, skipping..." - exit 0 + return 0 fi if [ ! -d "$$dir" ]; then echo "Path [$$dir] does is not a directory, skipping..." - exit 0 + return 0 fi if [ "$$is_temporary" = "true" ]; then @@ -86,7 +86,7 @@ def process_dir_shell_func(): if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then echo "Path [$$dir] is not empty, skipping..." - exit 0 + return 0 fi echo "Current Ownership and Permissions on [$$dir]:" diff --git a/ix-dev/community/autobrr/templates/library/base_v1_1_3/ports.py b/ix-dev/community/autobrr/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/autobrr/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/autobrr/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/autobrr/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/autobrr/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/autobrr/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/autobrr/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/autobrr/templates/library/base_v1_1_3/redis.py b/ix-dev/community/autobrr/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/autobrr/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/autobrr/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/autobrr/templates/library/base_v1_1_3/resources.py b/ix-dev/community/autobrr/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/autobrr/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/autobrr/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/autobrr/templates/library/base_v1_1_3/security.py b/ix-dev/community/autobrr/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/autobrr/templates/library/base_v1_1_3/security.py rename to ix-dev/community/autobrr/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/autobrr/templates/library/base_v1_1_3/storage.py b/ix-dev/community/autobrr/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/autobrr/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/autobrr/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/autobrr/templates/library/base_v1_1_3/utils.py b/ix-dev/community/autobrr/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/autobrr/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/autobrr/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/bazarr/app.yaml b/ix-dev/community/bazarr/app.yaml index f4353208c6..4722d7f18c 100644 --- a/ix-dev/community/bazarr/app.yaml +++ b/ix-dev/community/bazarr/app.yaml @@ -10,8 +10,8 @@ icon: https://media.sys.truenas.net/apps/bazarr/icons/icon.png keywords: - media - subtitles -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -31,4 +31,4 @@ sources: - https://github.com/morpheus65535/bazarr title: Bazarr train: community -version: 1.0.21 +version: 1.0.22 diff --git a/ix-dev/community/bazarr/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/bazarr/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/bazarr/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/bazarr/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/bazarr/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/bazarr/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/bazarr/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/bazarr/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/bazarr/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/bazarr/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/bazarr/templates/library/base_v1_1_3/environment.py b/ix-dev/community/bazarr/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/bazarr/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/bazarr/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/bazarr/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/bazarr/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/bazarr/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/bazarr/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/bazarr/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/bazarr/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/bazarr/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/bazarr/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/bazarr/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/bazarr/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/bazarr/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/bazarr/templates/library/base_v1_1_3/network.py b/ix-dev/community/bazarr/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/bazarr/templates/library/base_v1_1_3/network.py rename to ix-dev/community/bazarr/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/bazarr/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/bazarr/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/bazarr/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/bazarr/templates/library/base_v1_1_3/ports.py b/ix-dev/community/bazarr/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/bazarr/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/bazarr/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/bazarr/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/bazarr/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/bazarr/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/bazarr/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/bazarr/templates/library/base_v1_1_3/redis.py b/ix-dev/community/bazarr/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/bazarr/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/bazarr/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/bazarr/templates/library/base_v1_1_3/resources.py b/ix-dev/community/bazarr/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/bazarr/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/bazarr/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/bazarr/templates/library/base_v1_1_3/security.py b/ix-dev/community/bazarr/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/bazarr/templates/library/base_v1_1_3/security.py rename to ix-dev/community/bazarr/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/bazarr/templates/library/base_v1_1_3/storage.py b/ix-dev/community/bazarr/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/bazarr/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/bazarr/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/bazarr/templates/library/base_v1_1_3/utils.py b/ix-dev/community/bazarr/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/bazarr/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/bazarr/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/briefkasten/app.yaml b/ix-dev/community/briefkasten/app.yaml index 5019fb0ccd..f53301049c 100644 --- a/ix-dev/community/briefkasten/app.yaml +++ b/ix-dev/community/briefkasten/app.yaml @@ -8,8 +8,8 @@ host_mounts: [] icon: https://media.sys.truenas.net/apps/briefkasten/icons/icon.svg keywords: - bookmark -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -35,4 +35,4 @@ sources: - https://docs.briefkastenhq.com/ title: Briefkasten train: community -version: 1.0.18 +version: 1.0.19 diff --git a/ix-dev/community/briefkasten/templates/docker-compose.yaml b/ix-dev/community/briefkasten/templates/docker-compose.yaml index fc8d71145b..8112d6c2dd 100644 --- a/ix-dev/community/briefkasten/templates/docker-compose.yaml +++ b/ix-dev/community/briefkasten/templates/docker-compose.yaml @@ -117,7 +117,7 @@ services: {% if values.network.dns_opts %} dns_opt: {{ ix_lib.base.network.dns_opts(values.network.dns_opts) | tojson }} {% endif %} - {% set test = ix_lib.base.healthchecks.http_test(port=values.network.web_port, path="/") %} + {% set test = ix_lib.base.healthchecks.tcp_test(port=values.network.web_port) %} healthcheck: {{ ix_lib.base.healthchecks.check_health(test) | tojson }} environment: {{ ix_lib.base.environment.envs(app=app_env, user=values.briefkasten.additional_envs, values=values) | tojson }} ports: diff --git a/ix-dev/community/briefkasten/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/briefkasten/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/briefkasten/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/briefkasten/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/briefkasten/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/briefkasten/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/briefkasten/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/briefkasten/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/briefkasten/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/briefkasten/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/briefkasten/templates/library/base_v1_1_3/environment.py b/ix-dev/community/briefkasten/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/briefkasten/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/briefkasten/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/briefkasten/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/briefkasten/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/briefkasten/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/briefkasten/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/briefkasten/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/briefkasten/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/briefkasten/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/briefkasten/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/briefkasten/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/briefkasten/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/briefkasten/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/briefkasten/templates/library/base_v1_1_3/network.py b/ix-dev/community/briefkasten/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/briefkasten/templates/library/base_v1_1_3/network.py rename to ix-dev/community/briefkasten/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/briefkasten/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/briefkasten/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/briefkasten/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/briefkasten/templates/library/base_v1_1_3/ports.py b/ix-dev/community/briefkasten/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/briefkasten/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/briefkasten/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/briefkasten/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/briefkasten/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/briefkasten/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/briefkasten/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/briefkasten/templates/library/base_v1_1_3/redis.py b/ix-dev/community/briefkasten/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/briefkasten/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/briefkasten/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/briefkasten/templates/library/base_v1_1_3/resources.py b/ix-dev/community/briefkasten/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/briefkasten/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/briefkasten/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/briefkasten/templates/library/base_v1_1_3/security.py b/ix-dev/community/briefkasten/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/briefkasten/templates/library/base_v1_1_3/security.py rename to ix-dev/community/briefkasten/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/briefkasten/templates/library/base_v1_1_3/storage.py b/ix-dev/community/briefkasten/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/briefkasten/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/briefkasten/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/briefkasten/templates/library/base_v1_1_3/utils.py b/ix-dev/community/briefkasten/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/briefkasten/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/briefkasten/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/castopod/app.yaml b/ix-dev/community/castopod/app.yaml index 03a7a39ed1..90868bbbcb 100644 --- a/ix-dev/community/castopod/app.yaml +++ b/ix-dev/community/castopod/app.yaml @@ -19,8 +19,8 @@ host_mounts: [] icon: https://media.sys.truenas.net/apps/castopod/icons/icon.svg keywords: - podcast -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -49,4 +49,4 @@ sources: - https://code.castopod.org/adaures/castopod title: Castopod train: community -version: 1.0.8 +version: 1.0.9 diff --git a/ix-dev/community/castopod/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/castopod/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/castopod/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/castopod/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/castopod/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/castopod/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/castopod/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/castopod/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/castopod/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/castopod/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/castopod/templates/library/base_v1_1_3/environment.py b/ix-dev/community/castopod/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/castopod/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/castopod/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/castopod/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/castopod/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/castopod/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/castopod/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/castopod/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/castopod/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/castopod/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/castopod/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/castopod/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/castopod/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/castopod/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/castopod/templates/library/base_v1_1_3/network.py b/ix-dev/community/castopod/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/castopod/templates/library/base_v1_1_3/network.py rename to ix-dev/community/castopod/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/castopod/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/castopod/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/castopod/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/castopod/templates/library/base_v1_1_3/ports.py b/ix-dev/community/castopod/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/castopod/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/castopod/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/castopod/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/castopod/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/castopod/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/castopod/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/castopod/templates/library/base_v1_1_3/redis.py b/ix-dev/community/castopod/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/castopod/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/castopod/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/castopod/templates/library/base_v1_1_3/resources.py b/ix-dev/community/castopod/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/castopod/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/castopod/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/castopod/templates/library/base_v1_1_3/security.py b/ix-dev/community/castopod/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/castopod/templates/library/base_v1_1_3/security.py rename to ix-dev/community/castopod/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/castopod/templates/library/base_v1_1_3/storage.py b/ix-dev/community/castopod/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/castopod/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/castopod/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/castopod/templates/library/base_v1_1_3/utils.py b/ix-dev/community/castopod/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/castopod/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/castopod/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/chia/app.yaml b/ix-dev/community/chia/app.yaml index 5745c4f909..fd80fa31d7 100644 --- a/ix-dev/community/chia/app.yaml +++ b/ix-dev/community/chia/app.yaml @@ -11,8 +11,8 @@ keywords: - blockchain - hard-drive - chia -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -30,4 +30,4 @@ sources: - https://www.chia.net/ title: Chia train: community -version: 1.0.14 +version: 1.0.15 diff --git a/ix-dev/community/chia/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/chia/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/chia/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/chia/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/chia/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/chia/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/chia/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/chia/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/chia/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/chia/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/chia/templates/library/base_v1_1_3/environment.py b/ix-dev/community/chia/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/chia/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/chia/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/chia/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/chia/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/chia/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/chia/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/chia/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/chia/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/chia/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/chia/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/chia/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/chia/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/chia/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/chia/templates/library/base_v1_1_3/network.py b/ix-dev/community/chia/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/chia/templates/library/base_v1_1_3/network.py rename to ix-dev/community/chia/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/chia/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/chia/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/chia/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/chia/templates/library/base_v1_1_3/ports.py b/ix-dev/community/chia/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/chia/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/chia/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/chia/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/chia/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/chia/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/chia/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/chia/templates/library/base_v1_1_3/redis.py b/ix-dev/community/chia/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/chia/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/chia/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/chia/templates/library/base_v1_1_3/resources.py b/ix-dev/community/chia/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/chia/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/chia/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/chia/templates/library/base_v1_1_3/security.py b/ix-dev/community/chia/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/chia/templates/library/base_v1_1_3/security.py rename to ix-dev/community/chia/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/chia/templates/library/base_v1_1_3/storage.py b/ix-dev/community/chia/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/chia/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/chia/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/chia/templates/library/base_v1_1_3/utils.py b/ix-dev/community/chia/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/chia/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/chia/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/clamav/app.yaml b/ix-dev/community/clamav/app.yaml index 711fe456c1..3aa0d9ea1c 100644 --- a/ix-dev/community/clamav/app.yaml +++ b/ix-dev/community/clamav/app.yaml @@ -19,8 +19,8 @@ icon: https://media.sys.truenas.net/apps/clamav/icons/icon.png keywords: - anti-virus - clamav -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -38,4 +38,4 @@ sources: - https://www.clamav.net/ title: ClamAV train: community -version: 1.1.9 +version: 1.1.10 diff --git a/ix-dev/community/clamav/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/clamav/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/clamav/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/clamav/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/clamav/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/clamav/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/clamav/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/clamav/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/clamav/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/clamav/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/clamav/templates/library/base_v1_1_3/environment.py b/ix-dev/community/clamav/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/clamav/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/clamav/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/clamav/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/clamav/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/clamav/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/clamav/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/clamav/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/clamav/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/clamav/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/clamav/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/clamav/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/clamav/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/clamav/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/clamav/templates/library/base_v1_1_3/network.py b/ix-dev/community/clamav/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/clamav/templates/library/base_v1_1_3/network.py rename to ix-dev/community/clamav/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/clamav/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/clamav/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/clamav/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/clamav/templates/library/base_v1_1_3/ports.py b/ix-dev/community/clamav/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/clamav/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/clamav/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/clamav/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/clamav/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/clamav/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/clamav/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/clamav/templates/library/base_v1_1_3/redis.py b/ix-dev/community/clamav/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/clamav/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/clamav/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/clamav/templates/library/base_v1_1_3/resources.py b/ix-dev/community/clamav/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/clamav/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/clamav/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/clamav/templates/library/base_v1_1_3/security.py b/ix-dev/community/clamav/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/clamav/templates/library/base_v1_1_3/security.py rename to ix-dev/community/clamav/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/clamav/templates/library/base_v1_1_3/storage.py b/ix-dev/community/clamav/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/clamav/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/clamav/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/clamav/templates/library/base_v1_1_3/utils.py b/ix-dev/community/clamav/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/clamav/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/clamav/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/cloudflared/app.yaml b/ix-dev/community/cloudflared/app.yaml index b33aa9985f..cd5621b48c 100644 --- a/ix-dev/community/cloudflared/app.yaml +++ b/ix-dev/community/cloudflared/app.yaml @@ -11,8 +11,8 @@ keywords: - network - cloudflare - tunnel -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -30,4 +30,4 @@ sources: - https://hub.docker.com/r/cloudflare/cloudflared title: Cloudflared train: community -version: 1.1.12 +version: 1.1.13 diff --git a/ix-dev/community/cloudflared/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/cloudflared/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/cloudflared/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/cloudflared/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/cloudflared/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/cloudflared/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/cloudflared/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/cloudflared/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/cloudflared/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/cloudflared/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/cloudflared/templates/library/base_v1_1_3/environment.py b/ix-dev/community/cloudflared/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/cloudflared/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/cloudflared/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/cloudflared/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/cloudflared/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/cloudflared/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/cloudflared/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/cloudflared/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/cloudflared/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/cloudflared/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/cloudflared/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/cloudflared/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/cloudflared/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/cloudflared/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/cloudflared/templates/library/base_v1_1_3/network.py b/ix-dev/community/cloudflared/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/cloudflared/templates/library/base_v1_1_3/network.py rename to ix-dev/community/cloudflared/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/cloudflared/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/cloudflared/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/cloudflared/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/cloudflared/templates/library/base_v1_1_3/ports.py b/ix-dev/community/cloudflared/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/cloudflared/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/cloudflared/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/cloudflared/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/cloudflared/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/cloudflared/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/cloudflared/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/cloudflared/templates/library/base_v1_1_3/redis.py b/ix-dev/community/cloudflared/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/cloudflared/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/cloudflared/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/cloudflared/templates/library/base_v1_1_3/resources.py b/ix-dev/community/cloudflared/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/cloudflared/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/cloudflared/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/cloudflared/templates/library/base_v1_1_3/security.py b/ix-dev/community/cloudflared/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/cloudflared/templates/library/base_v1_1_3/security.py rename to ix-dev/community/cloudflared/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/cloudflared/templates/library/base_v1_1_3/storage.py b/ix-dev/community/cloudflared/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/cloudflared/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/cloudflared/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/cloudflared/templates/library/base_v1_1_3/utils.py b/ix-dev/community/cloudflared/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/cloudflared/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/cloudflared/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/dashy/app.yaml b/ix-dev/community/dashy/app.yaml index 415005a47c..80164b5ebc 100644 --- a/ix-dev/community/dashy/app.yaml +++ b/ix-dev/community/dashy/app.yaml @@ -8,8 +8,8 @@ host_mounts: [] icon: https://media.sys.truenas.net/apps/dashy/icons/icon.png keywords: - dashboard -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -29,4 +29,4 @@ sources: - https://github.com/lissy93/dashy title: Dashy train: community -version: 1.0.17 +version: 1.0.18 diff --git a/ix-dev/community/dashy/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/dashy/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/dashy/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/dashy/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/dashy/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/dashy/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/dashy/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/dashy/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/dashy/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/dashy/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/dashy/templates/library/base_v1_1_3/environment.py b/ix-dev/community/dashy/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/dashy/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/dashy/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/dashy/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/dashy/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/dashy/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/dashy/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/dashy/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/dashy/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/dashy/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/dashy/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/dashy/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/dashy/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/dashy/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/dashy/templates/library/base_v1_1_3/network.py b/ix-dev/community/dashy/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/dashy/templates/library/base_v1_1_3/network.py rename to ix-dev/community/dashy/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/dashy/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/dashy/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/dashy/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/dashy/templates/library/base_v1_1_3/ports.py b/ix-dev/community/dashy/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/dashy/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/dashy/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/dashy/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/dashy/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/dashy/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/dashy/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/dashy/templates/library/base_v1_1_3/redis.py b/ix-dev/community/dashy/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/dashy/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/dashy/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/dashy/templates/library/base_v1_1_3/resources.py b/ix-dev/community/dashy/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/dashy/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/dashy/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/dashy/templates/library/base_v1_1_3/security.py b/ix-dev/community/dashy/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/dashy/templates/library/base_v1_1_3/security.py rename to ix-dev/community/dashy/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/dashy/templates/library/base_v1_1_3/storage.py b/ix-dev/community/dashy/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/dashy/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/dashy/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/dashy/templates/library/base_v1_1_3/utils.py b/ix-dev/community/dashy/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/dashy/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/dashy/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/ddns-updater/app.yaml b/ix-dev/community/ddns-updater/app.yaml index 9abf8bca5d..ebac6cf5f5 100644 --- a/ix-dev/community/ddns-updater/app.yaml +++ b/ix-dev/community/ddns-updater/app.yaml @@ -9,8 +9,8 @@ icon: https://media.sys.truenas.net/apps/ddns-updater/icons/icon.svg keywords: - ddns-updater - ddns -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -30,4 +30,4 @@ sources: - https://hub.docker.com/r/qmcgaw/ddns-updater title: DDNS Updater train: community -version: 1.0.23 +version: 1.0.24 diff --git a/ix-dev/community/ddns-updater/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/ddns-updater/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/ddns-updater/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/ddns-updater/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/ddns-updater/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/ddns-updater/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/ddns-updater/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/ddns-updater/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/ddns-updater/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/ddns-updater/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/ddns-updater/templates/library/base_v1_1_3/environment.py b/ix-dev/community/ddns-updater/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/ddns-updater/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/ddns-updater/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/ddns-updater/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/ddns-updater/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/ddns-updater/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/ddns-updater/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/ddns-updater/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/ddns-updater/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/ddns-updater/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/ddns-updater/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/ddns-updater/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/ddns-updater/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/ddns-updater/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/ddns-updater/templates/library/base_v1_1_3/network.py b/ix-dev/community/ddns-updater/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/ddns-updater/templates/library/base_v1_1_3/network.py rename to ix-dev/community/ddns-updater/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/ddns-updater/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/ddns-updater/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/ddns-updater/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/ddns-updater/templates/library/base_v1_1_3/ports.py b/ix-dev/community/ddns-updater/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/ddns-updater/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/ddns-updater/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/ddns-updater/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/ddns-updater/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/ddns-updater/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/ddns-updater/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/ddns-updater/templates/library/base_v1_1_3/redis.py b/ix-dev/community/ddns-updater/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/ddns-updater/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/ddns-updater/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/ddns-updater/templates/library/base_v1_1_3/resources.py b/ix-dev/community/ddns-updater/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/ddns-updater/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/ddns-updater/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/ddns-updater/templates/library/base_v1_1_3/security.py b/ix-dev/community/ddns-updater/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/ddns-updater/templates/library/base_v1_1_3/security.py rename to ix-dev/community/ddns-updater/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/ddns-updater/templates/library/base_v1_1_3/storage.py b/ix-dev/community/ddns-updater/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/ddns-updater/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/ddns-updater/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/ddns-updater/templates/library/base_v1_1_3/utils.py b/ix-dev/community/ddns-updater/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/ddns-updater/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/ddns-updater/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/ddns-updater/templates/library/community/ddns-updater/v1_0_23/__init__.py b/ix-dev/community/ddns-updater/templates/library/community/ddns-updater/v1_0_24/__init__.py similarity index 100% rename from ix-dev/community/ddns-updater/templates/library/community/ddns-updater/v1_0_23/__init__.py rename to ix-dev/community/ddns-updater/templates/library/community/ddns-updater/v1_0_24/__init__.py diff --git a/ix-dev/community/ddns-updater/templates/library/community/ddns-updater/v1_0_23/config.py b/ix-dev/community/ddns-updater/templates/library/community/ddns-updater/v1_0_24/config.py similarity index 99% rename from ix-dev/community/ddns-updater/templates/library/community/ddns-updater/v1_0_23/config.py rename to ix-dev/community/ddns-updater/templates/library/community/ddns-updater/v1_0_24/config.py index b8604baa85..920ddc1042 100644 --- a/ix-dev/community/ddns-updater/templates/library/community/ddns-updater/v1_0_23/config.py +++ b/ix-dev/community/ddns-updater/templates/library/community/ddns-updater/v1_0_24/config.py @@ -1,4 +1,4 @@ -from base_v1_1_3 import utils +from base_v1_1_4 import utils import json valid_ip_dns_providers = [ diff --git a/ix-dev/community/deluge/app.yaml b/ix-dev/community/deluge/app.yaml index 1e01e76ff7..e8d2a2d50a 100644 --- a/ix-dev/community/deluge/app.yaml +++ b/ix-dev/community/deluge/app.yaml @@ -19,8 +19,8 @@ icon: https://media.sys.truenas.net/apps/deluge/icons/icon.png keywords: - torrent - download -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -38,4 +38,4 @@ sources: - https://deluge-torrent.org/ title: Deluge train: community -version: 1.0.17 +version: 1.0.18 diff --git a/ix-dev/community/deluge/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/deluge/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/deluge/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/deluge/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/deluge/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/deluge/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/deluge/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/deluge/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/deluge/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/deluge/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/deluge/templates/library/base_v1_1_3/environment.py b/ix-dev/community/deluge/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/deluge/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/deluge/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/deluge/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/deluge/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/deluge/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/deluge/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/deluge/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/deluge/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/deluge/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/deluge/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/deluge/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/deluge/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/deluge/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/deluge/templates/library/base_v1_1_3/network.py b/ix-dev/community/deluge/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/deluge/templates/library/base_v1_1_3/network.py rename to ix-dev/community/deluge/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/deluge/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/deluge/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/deluge/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/deluge/templates/library/base_v1_1_3/ports.py b/ix-dev/community/deluge/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/deluge/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/deluge/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/deluge/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/deluge/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/deluge/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/deluge/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/deluge/templates/library/base_v1_1_3/redis.py b/ix-dev/community/deluge/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/deluge/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/deluge/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/deluge/templates/library/base_v1_1_3/resources.py b/ix-dev/community/deluge/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/deluge/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/deluge/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/deluge/templates/library/base_v1_1_3/security.py b/ix-dev/community/deluge/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/deluge/templates/library/base_v1_1_3/security.py rename to ix-dev/community/deluge/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/deluge/templates/library/base_v1_1_3/storage.py b/ix-dev/community/deluge/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/deluge/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/deluge/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/deluge/templates/library/base_v1_1_3/utils.py b/ix-dev/community/deluge/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/deluge/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/deluge/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/distribution/app.yaml b/ix-dev/community/distribution/app.yaml index 9fbfbd209a..2fd511a576 100644 --- a/ix-dev/community/distribution/app.yaml +++ b/ix-dev/community/distribution/app.yaml @@ -10,8 +10,8 @@ icon: https://media.sys.truenas.net/apps/distribution/icons/icon.svg keywords: - registry - container -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -30,4 +30,4 @@ sources: - https://github.com/distribution/distribution title: Distribution train: community -version: 1.0.18 +version: 1.0.19 diff --git a/ix-dev/community/distribution/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/distribution/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/distribution/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/distribution/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/distribution/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/distribution/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/distribution/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/distribution/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/distribution/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/distribution/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/distribution/templates/library/base_v1_1_3/environment.py b/ix-dev/community/distribution/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/distribution/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/distribution/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/distribution/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/distribution/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/distribution/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/distribution/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/distribution/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/distribution/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/distribution/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/distribution/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/distribution/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/distribution/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/distribution/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/distribution/templates/library/base_v1_1_3/network.py b/ix-dev/community/distribution/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/distribution/templates/library/base_v1_1_3/network.py rename to ix-dev/community/distribution/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/distribution/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/distribution/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/distribution/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/distribution/templates/library/base_v1_1_3/ports.py b/ix-dev/community/distribution/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/distribution/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/distribution/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/distribution/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/distribution/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/distribution/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/distribution/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/distribution/templates/library/base_v1_1_3/redis.py b/ix-dev/community/distribution/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/distribution/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/distribution/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/distribution/templates/library/base_v1_1_3/resources.py b/ix-dev/community/distribution/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/distribution/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/distribution/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/distribution/templates/library/base_v1_1_3/security.py b/ix-dev/community/distribution/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/distribution/templates/library/base_v1_1_3/security.py rename to ix-dev/community/distribution/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/distribution/templates/library/base_v1_1_3/storage.py b/ix-dev/community/distribution/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/distribution/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/distribution/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/distribution/templates/library/base_v1_1_3/utils.py b/ix-dev/community/distribution/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/distribution/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/distribution/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/dockge/app.yaml b/ix-dev/community/dockge/app.yaml index 4f4d0e80c8..61008a66d0 100644 --- a/ix-dev/community/dockge/app.yaml +++ b/ix-dev/community/dockge/app.yaml @@ -28,8 +28,8 @@ icon: https://media.sys.truenas.net/apps/dockge/icons/icon.svg keywords: - docker - compose -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -48,4 +48,4 @@ sources: - https://github.com/louislam/dockge title: Dockge train: community -version: 1.0.16 +version: 1.0.17 diff --git a/ix-dev/community/dockge/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/dockge/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/dockge/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/dockge/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/dockge/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/dockge/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/dockge/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/dockge/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/dockge/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/dockge/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/dockge/templates/library/base_v1_1_3/environment.py b/ix-dev/community/dockge/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/dockge/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/dockge/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/dockge/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/dockge/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/dockge/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/dockge/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/dockge/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/dockge/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/dockge/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/dockge/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/dockge/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/dockge/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/dockge/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/dockge/templates/library/base_v1_1_3/network.py b/ix-dev/community/dockge/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/dockge/templates/library/base_v1_1_3/network.py rename to ix-dev/community/dockge/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/dockge/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/dockge/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/dockge/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/dockge/templates/library/base_v1_1_3/ports.py b/ix-dev/community/dockge/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/dockge/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/dockge/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/dockge/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/dockge/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/dockge/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/dockge/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/dockge/templates/library/base_v1_1_3/redis.py b/ix-dev/community/dockge/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/dockge/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/dockge/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/dockge/templates/library/base_v1_1_3/resources.py b/ix-dev/community/dockge/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/dockge/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/dockge/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/dockge/templates/library/base_v1_1_3/security.py b/ix-dev/community/dockge/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/dockge/templates/library/base_v1_1_3/security.py rename to ix-dev/community/dockge/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/dockge/templates/library/base_v1_1_3/storage.py b/ix-dev/community/dockge/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/dockge/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/dockge/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/dockge/templates/library/base_v1_1_3/utils.py b/ix-dev/community/dockge/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/dockge/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/dockge/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/drawio/app.yaml b/ix-dev/community/drawio/app.yaml index ec66fe9a80..f5e6766a57 100644 --- a/ix-dev/community/drawio/app.yaml +++ b/ix-dev/community/drawio/app.yaml @@ -9,8 +9,8 @@ icon: https://media.sys.truenas.net/apps/drawio/icons/icon.png keywords: - diagram - whiteboard -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -32,4 +32,4 @@ sources: - https://github.com/jgraph/drawio title: Draw.io train: community -version: 1.1.10 +version: 1.1.11 diff --git a/ix-dev/community/drawio/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/drawio/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/drawio/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/drawio/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/drawio/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/drawio/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/drawio/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/drawio/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/drawio/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/drawio/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/drawio/templates/library/base_v1_1_3/environment.py b/ix-dev/community/drawio/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/drawio/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/drawio/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/drawio/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/drawio/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/drawio/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/drawio/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/drawio/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/drawio/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/drawio/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/drawio/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/drawio/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/drawio/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/drawio/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/drawio/templates/library/base_v1_1_3/network.py b/ix-dev/community/drawio/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/drawio/templates/library/base_v1_1_3/network.py rename to ix-dev/community/drawio/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/drawio/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/drawio/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/drawio/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/drawio/templates/library/base_v1_1_3/ports.py b/ix-dev/community/drawio/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/drawio/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/drawio/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/drawio/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/drawio/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/drawio/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/drawio/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/drawio/templates/library/base_v1_1_3/redis.py b/ix-dev/community/drawio/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/drawio/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/drawio/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/drawio/templates/library/base_v1_1_3/resources.py b/ix-dev/community/drawio/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/drawio/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/drawio/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/drawio/templates/library/base_v1_1_3/security.py b/ix-dev/community/drawio/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/drawio/templates/library/base_v1_1_3/security.py rename to ix-dev/community/drawio/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/drawio/templates/library/base_v1_1_3/storage.py b/ix-dev/community/drawio/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/drawio/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/drawio/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/drawio/templates/library/base_v1_1_3/utils.py b/ix-dev/community/drawio/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/drawio/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/drawio/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/filebrowser/app.yaml b/ix-dev/community/filebrowser/app.yaml index b6cdbb495f..ee97400e1e 100644 --- a/ix-dev/community/filebrowser/app.yaml +++ b/ix-dev/community/filebrowser/app.yaml @@ -10,8 +10,8 @@ icon: https://media.sys.truenas.net/apps/filebrowser/icons/icon.png keywords: - files - browser -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -33,4 +33,4 @@ sources: - https://hub.docker.com/r/filebrowser/filebrowser title: File Browser train: community -version: 1.1.10 +version: 1.1.11 diff --git a/ix-dev/community/filebrowser/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/filebrowser/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/filebrowser/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/filebrowser/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/filebrowser/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/filebrowser/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/filebrowser/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/filebrowser/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/filebrowser/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/filebrowser/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/filebrowser/templates/library/base_v1_1_3/environment.py b/ix-dev/community/filebrowser/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/filebrowser/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/filebrowser/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/filebrowser/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/filebrowser/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/filebrowser/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/filebrowser/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/filebrowser/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/filebrowser/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/filebrowser/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/filebrowser/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/filebrowser/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/filebrowser/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/filebrowser/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/filebrowser/templates/library/base_v1_1_3/network.py b/ix-dev/community/filebrowser/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/filebrowser/templates/library/base_v1_1_3/network.py rename to ix-dev/community/filebrowser/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/filebrowser/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/filebrowser/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/filebrowser/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/filebrowser/templates/library/base_v1_1_3/ports.py b/ix-dev/community/filebrowser/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/filebrowser/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/filebrowser/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/filebrowser/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/filebrowser/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/filebrowser/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/filebrowser/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/filebrowser/templates/library/base_v1_1_3/redis.py b/ix-dev/community/filebrowser/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/filebrowser/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/filebrowser/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/filebrowser/templates/library/base_v1_1_3/resources.py b/ix-dev/community/filebrowser/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/filebrowser/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/filebrowser/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/filebrowser/templates/library/base_v1_1_3/security.py b/ix-dev/community/filebrowser/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/filebrowser/templates/library/base_v1_1_3/security.py rename to ix-dev/community/filebrowser/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/filebrowser/templates/library/base_v1_1_3/storage.py b/ix-dev/community/filebrowser/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/filebrowser/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/filebrowser/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/filebrowser/templates/library/base_v1_1_3/utils.py b/ix-dev/community/filebrowser/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/filebrowser/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/filebrowser/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/firefly-iii/app.yaml b/ix-dev/community/firefly-iii/app.yaml index 00df3bbb93..28c62c1be3 100644 --- a/ix-dev/community/firefly-iii/app.yaml +++ b/ix-dev/community/firefly-iii/app.yaml @@ -19,8 +19,8 @@ host_mounts: [] icon: https://media.sys.truenas.net/apps/firefly-iii/icons/icon.png keywords: - finance -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -57,4 +57,4 @@ sources: - https://github.com/firefly-iii/firefly-iii title: Firefly III train: community -version: 1.2.17 +version: 1.2.18 diff --git a/ix-dev/community/firefly-iii/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/firefly-iii/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/firefly-iii/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/firefly-iii/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/firefly-iii/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/firefly-iii/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/firefly-iii/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/firefly-iii/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/firefly-iii/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/firefly-iii/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/firefly-iii/templates/library/base_v1_1_3/environment.py b/ix-dev/community/firefly-iii/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/firefly-iii/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/firefly-iii/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/firefly-iii/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/firefly-iii/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/firefly-iii/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/firefly-iii/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/firefly-iii/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/firefly-iii/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/firefly-iii/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/firefly-iii/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/firefly-iii/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/firefly-iii/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/firefly-iii/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/firefly-iii/templates/library/base_v1_1_3/network.py b/ix-dev/community/firefly-iii/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/firefly-iii/templates/library/base_v1_1_3/network.py rename to ix-dev/community/firefly-iii/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/firefly-iii/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/firefly-iii/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/firefly-iii/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/firefly-iii/templates/library/base_v1_1_3/ports.py b/ix-dev/community/firefly-iii/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/firefly-iii/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/firefly-iii/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/firefly-iii/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/firefly-iii/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/firefly-iii/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/firefly-iii/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/firefly-iii/templates/library/base_v1_1_3/redis.py b/ix-dev/community/firefly-iii/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/firefly-iii/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/firefly-iii/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/firefly-iii/templates/library/base_v1_1_3/resources.py b/ix-dev/community/firefly-iii/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/firefly-iii/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/firefly-iii/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/firefly-iii/templates/library/base_v1_1_3/security.py b/ix-dev/community/firefly-iii/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/firefly-iii/templates/library/base_v1_1_3/security.py rename to ix-dev/community/firefly-iii/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/firefly-iii/templates/library/base_v1_1_3/storage.py b/ix-dev/community/firefly-iii/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/firefly-iii/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/firefly-iii/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/firefly-iii/templates/library/base_v1_1_3/utils.py b/ix-dev/community/firefly-iii/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/firefly-iii/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/firefly-iii/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/flame/app.yaml b/ix-dev/community/flame/app.yaml index ab38384d71..4230912971 100644 --- a/ix-dev/community/flame/app.yaml +++ b/ix-dev/community/flame/app.yaml @@ -14,8 +14,8 @@ host_mounts: [] icon: https://media.sys.truenas.net/apps/flame/icons/icon.png keywords: - startpage -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -34,4 +34,4 @@ sources: - https://github.com/pawelmalak/flame title: Flame train: community -version: 1.0.18 +version: 1.0.19 diff --git a/ix-dev/community/flame/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/flame/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/flame/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/flame/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/flame/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/flame/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/flame/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/flame/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/flame/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/flame/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/flame/templates/library/base_v1_1_3/environment.py b/ix-dev/community/flame/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/flame/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/flame/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/flame/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/flame/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/flame/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/flame/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/flame/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/flame/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/flame/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/flame/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/flame/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/flame/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/flame/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/flame/templates/library/base_v1_1_3/network.py b/ix-dev/community/flame/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/flame/templates/library/base_v1_1_3/network.py rename to ix-dev/community/flame/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/flame/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/flame/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/flame/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/flame/templates/library/base_v1_1_3/ports.py b/ix-dev/community/flame/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/flame/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/flame/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/flame/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/flame/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/flame/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/flame/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/flame/templates/library/base_v1_1_3/redis.py b/ix-dev/community/flame/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/flame/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/flame/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/flame/templates/library/base_v1_1_3/resources.py b/ix-dev/community/flame/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/flame/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/flame/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/flame/templates/library/base_v1_1_3/security.py b/ix-dev/community/flame/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/flame/templates/library/base_v1_1_3/security.py rename to ix-dev/community/flame/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/flame/templates/library/base_v1_1_3/storage.py b/ix-dev/community/flame/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/flame/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/flame/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/flame/templates/library/base_v1_1_3/utils.py b/ix-dev/community/flame/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/flame/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/flame/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/freshrss/app.yaml b/ix-dev/community/freshrss/app.yaml index 2706dd523a..c353f99fe2 100644 --- a/ix-dev/community/freshrss/app.yaml +++ b/ix-dev/community/freshrss/app.yaml @@ -15,8 +15,8 @@ icon: https://media.sys.truenas.net/apps/freshrss/icons/icon.png keywords: - rss - news -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -41,4 +41,4 @@ sources: - https://hub.docker.com/r/freshrss/freshrss title: FreshRSS train: community -version: 1.1.13 +version: 1.1.14 diff --git a/ix-dev/community/freshrss/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/freshrss/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/freshrss/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/freshrss/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/freshrss/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/freshrss/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/freshrss/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/freshrss/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/freshrss/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/freshrss/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/freshrss/templates/library/base_v1_1_3/environment.py b/ix-dev/community/freshrss/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/freshrss/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/freshrss/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/freshrss/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/freshrss/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/freshrss/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/freshrss/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/freshrss/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/freshrss/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/freshrss/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/freshrss/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/freshrss/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/freshrss/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/freshrss/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/freshrss/templates/library/base_v1_1_3/network.py b/ix-dev/community/freshrss/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/freshrss/templates/library/base_v1_1_3/network.py rename to ix-dev/community/freshrss/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/freshrss/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/freshrss/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/freshrss/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/freshrss/templates/library/base_v1_1_3/ports.py b/ix-dev/community/freshrss/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/freshrss/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/freshrss/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/freshrss/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/freshrss/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/freshrss/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/freshrss/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/freshrss/templates/library/base_v1_1_3/redis.py b/ix-dev/community/freshrss/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/freshrss/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/freshrss/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/freshrss/templates/library/base_v1_1_3/resources.py b/ix-dev/community/freshrss/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/freshrss/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/freshrss/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/freshrss/templates/library/base_v1_1_3/security.py b/ix-dev/community/freshrss/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/freshrss/templates/library/base_v1_1_3/security.py rename to ix-dev/community/freshrss/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/freshrss/templates/library/base_v1_1_3/storage.py b/ix-dev/community/freshrss/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/freshrss/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/freshrss/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/freshrss/templates/library/base_v1_1_3/utils.py b/ix-dev/community/freshrss/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/freshrss/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/freshrss/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/frigate/app.yaml b/ix-dev/community/frigate/app.yaml index adb619c15b..3d35b79283 100644 --- a/ix-dev/community/frigate/app.yaml +++ b/ix-dev/community/frigate/app.yaml @@ -19,8 +19,8 @@ icon: https://media.sys.truenas.net/apps/frigate/icons/icon.svg keywords: - camera - nvr -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -40,4 +40,4 @@ sources: - https://github.com/blakeblackshear/frigate title: Frigate train: community -version: 1.0.8 +version: 1.0.9 diff --git a/ix-dev/community/frigate/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/frigate/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/frigate/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/frigate/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/frigate/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/frigate/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/frigate/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/frigate/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/frigate/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/frigate/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/frigate/templates/library/base_v1_1_3/environment.py b/ix-dev/community/frigate/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/frigate/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/frigate/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/frigate/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/frigate/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/frigate/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/frigate/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/frigate/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/frigate/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/frigate/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/frigate/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/frigate/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/frigate/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/frigate/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/frigate/templates/library/base_v1_1_3/network.py b/ix-dev/community/frigate/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/frigate/templates/library/base_v1_1_3/network.py rename to ix-dev/community/frigate/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/frigate/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/frigate/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/frigate/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/frigate/templates/library/base_v1_1_3/ports.py b/ix-dev/community/frigate/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/frigate/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/frigate/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/frigate/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/frigate/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/frigate/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/frigate/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/frigate/templates/library/base_v1_1_3/redis.py b/ix-dev/community/frigate/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/frigate/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/frigate/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/frigate/templates/library/base_v1_1_3/resources.py b/ix-dev/community/frigate/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/frigate/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/frigate/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/frigate/templates/library/base_v1_1_3/security.py b/ix-dev/community/frigate/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/frigate/templates/library/base_v1_1_3/security.py rename to ix-dev/community/frigate/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/frigate/templates/library/base_v1_1_3/storage.py b/ix-dev/community/frigate/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/frigate/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/frigate/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/frigate/templates/library/base_v1_1_3/utils.py b/ix-dev/community/frigate/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/frigate/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/frigate/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/fscrawler/app.yaml b/ix-dev/community/fscrawler/app.yaml index c2983b6fb4..d8c9ad3d68 100644 --- a/ix-dev/community/fscrawler/app.yaml +++ b/ix-dev/community/fscrawler/app.yaml @@ -10,8 +10,8 @@ icon: https://media.sys.truenas.net/apps/fscrawler/icons/icon.svg keywords: - index - crawler -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -30,4 +30,4 @@ sources: - https://fscrawler.readthedocs.io/ title: FSCrawler train: community -version: 1.0.16 +version: 1.0.17 diff --git a/ix-dev/community/fscrawler/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/fscrawler/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/fscrawler/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/fscrawler/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/fscrawler/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/fscrawler/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/fscrawler/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/fscrawler/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/fscrawler/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/fscrawler/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/fscrawler/templates/library/base_v1_1_3/environment.py b/ix-dev/community/fscrawler/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/fscrawler/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/fscrawler/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/fscrawler/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/fscrawler/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/fscrawler/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/fscrawler/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/fscrawler/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/fscrawler/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/fscrawler/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/fscrawler/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/fscrawler/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/fscrawler/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/fscrawler/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/fscrawler/templates/library/base_v1_1_3/network.py b/ix-dev/community/fscrawler/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/fscrawler/templates/library/base_v1_1_3/network.py rename to ix-dev/community/fscrawler/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/fscrawler/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/fscrawler/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/fscrawler/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/fscrawler/templates/library/base_v1_1_3/ports.py b/ix-dev/community/fscrawler/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/fscrawler/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/fscrawler/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/fscrawler/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/fscrawler/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/fscrawler/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/fscrawler/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/fscrawler/templates/library/base_v1_1_3/redis.py b/ix-dev/community/fscrawler/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/fscrawler/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/fscrawler/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/fscrawler/templates/library/base_v1_1_3/resources.py b/ix-dev/community/fscrawler/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/fscrawler/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/fscrawler/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/fscrawler/templates/library/base_v1_1_3/security.py b/ix-dev/community/fscrawler/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/fscrawler/templates/library/base_v1_1_3/security.py rename to ix-dev/community/fscrawler/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/fscrawler/templates/library/base_v1_1_3/storage.py b/ix-dev/community/fscrawler/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/fscrawler/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/fscrawler/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/fscrawler/templates/library/base_v1_1_3/utils.py b/ix-dev/community/fscrawler/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/fscrawler/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/fscrawler/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/gitea/app.yaml b/ix-dev/community/gitea/app.yaml index 728f82649f..8a4d27438a 100644 --- a/ix-dev/community/gitea/app.yaml +++ b/ix-dev/community/gitea/app.yaml @@ -10,8 +10,8 @@ keywords: - git - gitea - source control -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -33,4 +33,4 @@ sources: - https://docs.gitea.io/en-us/install-with-docker-rootless title: Gitea train: community -version: 1.0.11 +version: 1.0.12 diff --git a/ix-dev/community/gitea/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/gitea/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/gitea/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/gitea/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/gitea/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/gitea/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/gitea/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/gitea/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/gitea/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/gitea/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/gitea/templates/library/base_v1_1_3/environment.py b/ix-dev/community/gitea/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/gitea/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/gitea/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/gitea/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/gitea/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/gitea/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/gitea/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/gitea/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/gitea/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/gitea/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/gitea/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/gitea/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/gitea/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/gitea/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/gitea/templates/library/base_v1_1_3/network.py b/ix-dev/community/gitea/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/gitea/templates/library/base_v1_1_3/network.py rename to ix-dev/community/gitea/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/gitea/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/gitea/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/gitea/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/gitea/templates/library/base_v1_1_3/ports.py b/ix-dev/community/gitea/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/gitea/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/gitea/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/gitea/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/gitea/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/gitea/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/gitea/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/gitea/templates/library/base_v1_1_3/redis.py b/ix-dev/community/gitea/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/gitea/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/gitea/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/gitea/templates/library/base_v1_1_3/resources.py b/ix-dev/community/gitea/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/gitea/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/gitea/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/gitea/templates/library/base_v1_1_3/security.py b/ix-dev/community/gitea/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/gitea/templates/library/base_v1_1_3/security.py rename to ix-dev/community/gitea/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/gitea/templates/library/base_v1_1_3/storage.py b/ix-dev/community/gitea/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/gitea/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/gitea/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/gitea/templates/library/base_v1_1_3/utils.py b/ix-dev/community/gitea/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/gitea/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/gitea/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/grafana/app.yaml b/ix-dev/community/grafana/app.yaml index 6edbc2a7cc..5ab05d1991 100644 --- a/ix-dev/community/grafana/app.yaml +++ b/ix-dev/community/grafana/app.yaml @@ -12,8 +12,8 @@ keywords: - monitoring - metrics - dashboards -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -34,4 +34,4 @@ sources: - https://github.com/grafana title: Grafana train: community -version: 1.1.11 +version: 1.1.12 diff --git a/ix-dev/community/grafana/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/grafana/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/grafana/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/grafana/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/grafana/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/grafana/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/grafana/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/grafana/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/grafana/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/grafana/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/grafana/templates/library/base_v1_1_3/environment.py b/ix-dev/community/grafana/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/grafana/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/grafana/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/grafana/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/grafana/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/grafana/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/grafana/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/grafana/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/grafana/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/grafana/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/grafana/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/grafana/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/grafana/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/grafana/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/grafana/templates/library/base_v1_1_3/network.py b/ix-dev/community/grafana/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/grafana/templates/library/base_v1_1_3/network.py rename to ix-dev/community/grafana/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/grafana/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/grafana/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/grafana/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/grafana/templates/library/base_v1_1_3/ports.py b/ix-dev/community/grafana/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/grafana/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/grafana/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/grafana/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/grafana/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/grafana/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/grafana/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/grafana/templates/library/base_v1_1_3/redis.py b/ix-dev/community/grafana/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/grafana/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/grafana/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/grafana/templates/library/base_v1_1_3/resources.py b/ix-dev/community/grafana/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/grafana/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/grafana/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/grafana/templates/library/base_v1_1_3/security.py b/ix-dev/community/grafana/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/grafana/templates/library/base_v1_1_3/security.py rename to ix-dev/community/grafana/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/grafana/templates/library/base_v1_1_3/storage.py b/ix-dev/community/grafana/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/grafana/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/grafana/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/grafana/templates/library/base_v1_1_3/utils.py b/ix-dev/community/grafana/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/grafana/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/grafana/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/handbrake/app.yaml b/ix-dev/community/handbrake/app.yaml index bb744bb970..cb50af49fe 100644 --- a/ix-dev/community/handbrake/app.yaml +++ b/ix-dev/community/handbrake/app.yaml @@ -28,8 +28,8 @@ keywords: - media - video - transcoder -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -47,4 +47,4 @@ sources: - https://hub.docker.com/r/jlesage/handbrake title: Handbrake train: community -version: 2.0.10 +version: 2.0.11 diff --git a/ix-dev/community/handbrake/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/handbrake/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/handbrake/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/handbrake/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/handbrake/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/handbrake/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/handbrake/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/handbrake/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/handbrake/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/handbrake/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/handbrake/templates/library/base_v1_1_3/environment.py b/ix-dev/community/handbrake/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/handbrake/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/handbrake/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/handbrake/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/handbrake/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/handbrake/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/handbrake/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/handbrake/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/handbrake/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/handbrake/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/handbrake/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/handbrake/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/handbrake/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/handbrake/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/handbrake/templates/library/base_v1_1_3/network.py b/ix-dev/community/handbrake/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/handbrake/templates/library/base_v1_1_3/network.py rename to ix-dev/community/handbrake/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/handbrake/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/handbrake/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/handbrake/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/handbrake/templates/library/base_v1_1_3/ports.py b/ix-dev/community/handbrake/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/handbrake/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/handbrake/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/handbrake/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/handbrake/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/handbrake/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/handbrake/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/handbrake/templates/library/base_v1_1_3/redis.py b/ix-dev/community/handbrake/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/handbrake/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/handbrake/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/handbrake/templates/library/base_v1_1_3/resources.py b/ix-dev/community/handbrake/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/handbrake/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/handbrake/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/handbrake/templates/library/base_v1_1_3/security.py b/ix-dev/community/handbrake/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/handbrake/templates/library/base_v1_1_3/security.py rename to ix-dev/community/handbrake/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/handbrake/templates/library/base_v1_1_3/storage.py b/ix-dev/community/handbrake/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/handbrake/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/handbrake/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/handbrake/templates/library/base_v1_1_3/utils.py b/ix-dev/community/handbrake/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/handbrake/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/handbrake/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/homarr/app.yaml b/ix-dev/community/homarr/app.yaml index d6d852e766..6469358b63 100644 --- a/ix-dev/community/homarr/app.yaml +++ b/ix-dev/community/homarr/app.yaml @@ -9,8 +9,8 @@ host_mounts: [] icon: https://media.sys.truenas.net/apps/homarr/icons/icon.svg keywords: - dashboard -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -31,4 +31,4 @@ sources: - https://github.com/ajnart/homarr title: Homarr train: community -version: 1.0.18 +version: 1.0.19 diff --git a/ix-dev/community/homarr/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/homarr/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/homarr/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/homarr/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/homarr/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/homarr/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/homarr/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/homarr/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/homarr/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/homarr/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/homarr/templates/library/base_v1_1_3/environment.py b/ix-dev/community/homarr/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/homarr/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/homarr/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/homarr/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/homarr/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/homarr/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/homarr/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/homarr/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/homarr/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/homarr/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/homarr/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/homarr/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/homarr/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/homarr/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/homarr/templates/library/base_v1_1_3/network.py b/ix-dev/community/homarr/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/homarr/templates/library/base_v1_1_3/network.py rename to ix-dev/community/homarr/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/homarr/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/homarr/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/homarr/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/homarr/templates/library/base_v1_1_3/ports.py b/ix-dev/community/homarr/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/homarr/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/homarr/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/homarr/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/homarr/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/homarr/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/homarr/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/homarr/templates/library/base_v1_1_3/redis.py b/ix-dev/community/homarr/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/homarr/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/homarr/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/homarr/templates/library/base_v1_1_3/resources.py b/ix-dev/community/homarr/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/homarr/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/homarr/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/homarr/templates/library/base_v1_1_3/security.py b/ix-dev/community/homarr/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/homarr/templates/library/base_v1_1_3/security.py rename to ix-dev/community/homarr/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/homarr/templates/library/base_v1_1_3/storage.py b/ix-dev/community/homarr/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/homarr/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/homarr/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/homarr/templates/library/base_v1_1_3/utils.py b/ix-dev/community/homarr/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/homarr/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/homarr/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/homepage/app.yaml b/ix-dev/community/homepage/app.yaml index 31c7e210f6..adde8e9804 100644 --- a/ix-dev/community/homepage/app.yaml +++ b/ix-dev/community/homepage/app.yaml @@ -8,8 +8,8 @@ host_mounts: [] icon: https://media.sys.truenas.net/apps/homepage/icons/icon.png keywords: - dashboard -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -33,4 +33,4 @@ sources: - https://github.com/benphelps/homepage title: Homepage train: community -version: 1.0.21 +version: 1.0.22 diff --git a/ix-dev/community/homepage/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/homepage/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/homepage/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/homepage/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/homepage/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/homepage/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/homepage/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/homepage/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/homepage/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/homepage/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/homepage/templates/library/base_v1_1_3/environment.py b/ix-dev/community/homepage/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/homepage/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/homepage/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/homepage/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/homepage/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/homepage/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/homepage/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/homepage/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/homepage/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/homepage/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/homepage/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/homepage/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/homepage/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/homepage/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/homepage/templates/library/base_v1_1_3/network.py b/ix-dev/community/homepage/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/homepage/templates/library/base_v1_1_3/network.py rename to ix-dev/community/homepage/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/homepage/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/homepage/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/homepage/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/homepage/templates/library/base_v1_1_3/ports.py b/ix-dev/community/homepage/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/homepage/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/homepage/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/homepage/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/homepage/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/homepage/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/homepage/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/homepage/templates/library/base_v1_1_3/redis.py b/ix-dev/community/homepage/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/homepage/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/homepage/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/homepage/templates/library/base_v1_1_3/resources.py b/ix-dev/community/homepage/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/homepage/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/homepage/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/homepage/templates/library/base_v1_1_3/security.py b/ix-dev/community/homepage/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/homepage/templates/library/base_v1_1_3/security.py rename to ix-dev/community/homepage/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/homepage/templates/library/base_v1_1_3/storage.py b/ix-dev/community/homepage/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/homepage/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/homepage/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/homepage/templates/library/base_v1_1_3/utils.py b/ix-dev/community/homepage/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/homepage/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/homepage/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/homer/app.yaml b/ix-dev/community/homer/app.yaml index dcf36ff607..8f0f7dae82 100644 --- a/ix-dev/community/homer/app.yaml +++ b/ix-dev/community/homer/app.yaml @@ -7,8 +7,8 @@ description: Homer is a dead simple static HOMepage for your servER to keep your home: https://github.com/bastienwirtz/homer host_mounts: [] icon: https://media.sys.truenas.net/apps/homer/icons/icon.png -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -30,4 +30,4 @@ tags: - homepage title: Homer train: community -version: 2.0.9 +version: 2.0.10 diff --git a/ix-dev/community/homer/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/homer/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/homer/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/homer/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/homer/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/homer/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/homer/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/homer/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/homer/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/homer/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/homer/templates/library/base_v1_1_3/environment.py b/ix-dev/community/homer/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/homer/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/homer/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/homer/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/homer/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/homer/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/homer/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/homer/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/homer/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/homer/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/homer/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/homer/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/homer/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/homer/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/homer/templates/library/base_v1_1_3/network.py b/ix-dev/community/homer/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/homer/templates/library/base_v1_1_3/network.py rename to ix-dev/community/homer/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/homer/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/homer/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/homer/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/homer/templates/library/base_v1_1_3/ports.py b/ix-dev/community/homer/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/homer/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/homer/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/homer/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/homer/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/homer/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/homer/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/homer/templates/library/base_v1_1_3/redis.py b/ix-dev/community/homer/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/homer/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/homer/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/homer/templates/library/base_v1_1_3/resources.py b/ix-dev/community/homer/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/homer/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/homer/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/homer/templates/library/base_v1_1_3/security.py b/ix-dev/community/homer/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/homer/templates/library/base_v1_1_3/security.py rename to ix-dev/community/homer/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/homer/templates/library/base_v1_1_3/storage.py b/ix-dev/community/homer/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/homer/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/homer/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/homer/templates/library/base_v1_1_3/utils.py b/ix-dev/community/homer/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/homer/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/homer/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/immich/app.yaml b/ix-dev/community/immich/app.yaml index 14c6ac14ed..24c6bc2296 100644 --- a/ix-dev/community/immich/app.yaml +++ b/ix-dev/community/immich/app.yaml @@ -16,8 +16,8 @@ icon: https://media.sys.truenas.net/apps/immich/icons/icon.svg keywords: - photos - backup -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -45,4 +45,4 @@ sources: - https://github.com/immich-app/immich title: Immich train: community -version: 1.6.18 +version: 1.6.19 diff --git a/ix-dev/community/immich/templates/docker-compose.yaml b/ix-dev/community/immich/templates/docker-compose.yaml index 1fd39ed660..a07a201384 100644 --- a/ix-dev/community/immich/templates/docker-compose.yaml +++ b/ix-dev/community/immich/templates/docker-compose.yaml @@ -95,7 +95,7 @@ services: {% if values.network.dns_opts %} dns_opt: {{ ix_lib.base.network.dns_opts(values.network.dns_opts) | tojson }} {% endif %} - {% set test = ix_lib.base.healthchecks.http_test(port=values.network.web_port, path="/api/server/ping") %} + {% set test = "/usr/src/app/bin/immich-healthcheck" %} healthcheck: {{ ix_lib.base.healthchecks.check_health(test) | tojson }} {% set server_app_env = { "NODE_ENV": "production", @@ -168,7 +168,7 @@ services: {% if values.network.dns_opts %} dns_opt: {{ ix_lib.base.network.dns_opts(values.network.dns_opts) | tojson }} {% endif %} - {% set test = ix_lib.base.healthchecks.http_test(port=values.consts.ml_port, path="/ping") %} + {% set test = "python3 /usr/src/app/healthcheck.py" %} healthcheck: {{ ix_lib.base.healthchecks.check_health(test) | tojson }} {% set ml_app_env = { "NODE_ENV": "production", diff --git a/ix-dev/community/immich/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/immich/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/immich/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/immich/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/immich/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/immich/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/immich/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/immich/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/immich/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/immich/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/immich/templates/library/base_v1_1_3/environment.py b/ix-dev/community/immich/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/immich/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/immich/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/immich/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/immich/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/immich/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/immich/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/immich/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/immich/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/immich/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/immich/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/immich/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/immich/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/immich/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/immich/templates/library/base_v1_1_3/network.py b/ix-dev/community/immich/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/immich/templates/library/base_v1_1_3/network.py rename to ix-dev/community/immich/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/immich/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/immich/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/immich/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/immich/templates/library/base_v1_1_3/ports.py b/ix-dev/community/immich/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/immich/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/immich/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/immich/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/immich/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/immich/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/immich/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/immich/templates/library/base_v1_1_3/redis.py b/ix-dev/community/immich/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/immich/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/immich/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/immich/templates/library/base_v1_1_3/resources.py b/ix-dev/community/immich/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/immich/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/immich/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/immich/templates/library/base_v1_1_3/security.py b/ix-dev/community/immich/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/immich/templates/library/base_v1_1_3/security.py rename to ix-dev/community/immich/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/immich/templates/library/base_v1_1_3/storage.py b/ix-dev/community/immich/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/immich/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/immich/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/immich/templates/library/base_v1_1_3/utils.py b/ix-dev/community/immich/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/immich/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/immich/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/invidious/app.yaml b/ix-dev/community/invidious/app.yaml index b337f0b7b1..0d9f2e3cbc 100644 --- a/ix-dev/community/invidious/app.yaml +++ b/ix-dev/community/invidious/app.yaml @@ -8,8 +8,8 @@ host_mounts: [] icon: https://media.sys.truenas.net/apps/invidious/icons/icon.svg keywords: - youtube -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -38,4 +38,4 @@ sources: - https://quay.io/repository/invidious title: Invidious train: community -version: 1.0.10 +version: 1.0.11 diff --git a/ix-dev/community/invidious/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/invidious/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/invidious/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/invidious/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/invidious/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/invidious/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/invidious/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/invidious/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/invidious/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/invidious/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/invidious/templates/library/base_v1_1_3/environment.py b/ix-dev/community/invidious/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/invidious/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/invidious/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/invidious/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/invidious/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/invidious/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/invidious/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/invidious/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/invidious/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/invidious/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/invidious/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/invidious/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/invidious/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/invidious/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/invidious/templates/library/base_v1_1_3/network.py b/ix-dev/community/invidious/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/invidious/templates/library/base_v1_1_3/network.py rename to ix-dev/community/invidious/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/invidious/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/invidious/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/invidious/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/invidious/templates/library/base_v1_1_3/ports.py b/ix-dev/community/invidious/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/invidious/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/invidious/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/invidious/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/invidious/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/invidious/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/invidious/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/invidious/templates/library/base_v1_1_3/redis.py b/ix-dev/community/invidious/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/invidious/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/invidious/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/invidious/templates/library/base_v1_1_3/resources.py b/ix-dev/community/invidious/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/invidious/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/invidious/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/invidious/templates/library/base_v1_1_3/security.py b/ix-dev/community/invidious/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/invidious/templates/library/base_v1_1_3/security.py rename to ix-dev/community/invidious/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/invidious/templates/library/base_v1_1_3/storage.py b/ix-dev/community/invidious/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/invidious/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/invidious/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/invidious/templates/library/base_v1_1_3/utils.py b/ix-dev/community/invidious/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/invidious/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/invidious/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/ipfs/app.yaml b/ix-dev/community/ipfs/app.yaml index a1ac209cdc..d05581545b 100644 --- a/ix-dev/community/ipfs/app.yaml +++ b/ix-dev/community/ipfs/app.yaml @@ -12,8 +12,8 @@ keywords: - ipfs - file-sharing - kubo -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -33,4 +33,4 @@ sources: - https://ipfs.tech/ title: IPFS train: community -version: 1.0.18 +version: 1.0.19 diff --git a/ix-dev/community/ipfs/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/ipfs/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/ipfs/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/ipfs/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/ipfs/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/ipfs/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/ipfs/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/ipfs/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/ipfs/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/ipfs/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/ipfs/templates/library/base_v1_1_3/environment.py b/ix-dev/community/ipfs/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/ipfs/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/ipfs/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/ipfs/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/ipfs/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/ipfs/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/ipfs/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/ipfs/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/ipfs/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/ipfs/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/ipfs/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/ipfs/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/ipfs/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/ipfs/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/ipfs/templates/library/base_v1_1_3/network.py b/ix-dev/community/ipfs/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/ipfs/templates/library/base_v1_1_3/network.py rename to ix-dev/community/ipfs/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/ipfs/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/ipfs/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/ipfs/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/ipfs/templates/library/base_v1_1_3/ports.py b/ix-dev/community/ipfs/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/ipfs/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/ipfs/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/ipfs/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/ipfs/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/ipfs/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/ipfs/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/ipfs/templates/library/base_v1_1_3/redis.py b/ix-dev/community/ipfs/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/ipfs/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/ipfs/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/ipfs/templates/library/base_v1_1_3/resources.py b/ix-dev/community/ipfs/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/ipfs/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/ipfs/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/ipfs/templates/library/base_v1_1_3/security.py b/ix-dev/community/ipfs/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/ipfs/templates/library/base_v1_1_3/security.py rename to ix-dev/community/ipfs/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/ipfs/templates/library/base_v1_1_3/storage.py b/ix-dev/community/ipfs/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/ipfs/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/ipfs/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/ipfs/templates/library/base_v1_1_3/utils.py b/ix-dev/community/ipfs/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/ipfs/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/ipfs/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/jellyfin/app.yaml b/ix-dev/community/jellyfin/app.yaml index f5df83b789..6a86ef9e03 100644 --- a/ix-dev/community/jellyfin/app.yaml +++ b/ix-dev/community/jellyfin/app.yaml @@ -14,8 +14,8 @@ keywords: - tv - media - streaming -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -35,4 +35,4 @@ sources: - https://jellyfin.org/ title: Jellyfin train: community -version: 1.0.24 +version: 1.0.25 diff --git a/ix-dev/community/jellyfin/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/jellyfin/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/jellyfin/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/jellyfin/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/jellyfin/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/jellyfin/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/jellyfin/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/jellyfin/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/jellyfin/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/jellyfin/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/jellyfin/templates/library/base_v1_1_3/environment.py b/ix-dev/community/jellyfin/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/jellyfin/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/jellyfin/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/jellyfin/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/jellyfin/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/jellyfin/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/jellyfin/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/jellyfin/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/jellyfin/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/jellyfin/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/jellyfin/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/jellyfin/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/jellyfin/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/jellyfin/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/jellyfin/templates/library/base_v1_1_3/network.py b/ix-dev/community/jellyfin/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/jellyfin/templates/library/base_v1_1_3/network.py rename to ix-dev/community/jellyfin/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/jellyfin/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/jellyfin/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/jellyfin/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/jellyfin/templates/library/base_v1_1_3/ports.py b/ix-dev/community/jellyfin/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/jellyfin/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/jellyfin/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/jellyfin/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/jellyfin/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/jellyfin/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/jellyfin/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/jellyfin/templates/library/base_v1_1_3/redis.py b/ix-dev/community/jellyfin/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/jellyfin/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/jellyfin/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/jellyfin/templates/library/base_v1_1_3/resources.py b/ix-dev/community/jellyfin/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/jellyfin/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/jellyfin/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/jellyfin/templates/library/base_v1_1_3/security.py b/ix-dev/community/jellyfin/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/jellyfin/templates/library/base_v1_1_3/security.py rename to ix-dev/community/jellyfin/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/jellyfin/templates/library/base_v1_1_3/storage.py b/ix-dev/community/jellyfin/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/jellyfin/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/jellyfin/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/jellyfin/templates/library/base_v1_1_3/utils.py b/ix-dev/community/jellyfin/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/jellyfin/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/jellyfin/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/jellyseerr/app.yaml b/ix-dev/community/jellyseerr/app.yaml index 0072587ff4..cf47b1f917 100644 --- a/ix-dev/community/jellyseerr/app.yaml +++ b/ix-dev/community/jellyseerr/app.yaml @@ -9,8 +9,8 @@ host_mounts: [] icon: https://media.sys.truenas.net/apps/jellyseerr/icons/icon.svg keywords: - media -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -29,4 +29,4 @@ sources: - https://hub.docker.com/r/fallenbagel/jellyseerr title: Jellyseerr train: community -version: 1.0.18 +version: 1.0.19 diff --git a/ix-dev/community/jellyseerr/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/jellyseerr/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/jellyseerr/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/jellyseerr/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/jellyseerr/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/jellyseerr/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/jellyseerr/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/jellyseerr/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/jellyseerr/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/jellyseerr/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/jellyseerr/templates/library/base_v1_1_3/environment.py b/ix-dev/community/jellyseerr/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/jellyseerr/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/jellyseerr/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/jellyseerr/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/jellyseerr/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/jellyseerr/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/jellyseerr/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/jellyseerr/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/jellyseerr/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/jellyseerr/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/jellyseerr/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/jellyseerr/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/jellyseerr/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/jellyseerr/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/jellyseerr/templates/library/base_v1_1_3/network.py b/ix-dev/community/jellyseerr/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/jellyseerr/templates/library/base_v1_1_3/network.py rename to ix-dev/community/jellyseerr/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/jellyseerr/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/jellyseerr/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/jellyseerr/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/jellyseerr/templates/library/base_v1_1_3/ports.py b/ix-dev/community/jellyseerr/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/jellyseerr/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/jellyseerr/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/jellyseerr/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/jellyseerr/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/jellyseerr/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/jellyseerr/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/jellyseerr/templates/library/base_v1_1_3/redis.py b/ix-dev/community/jellyseerr/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/jellyseerr/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/jellyseerr/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/jellyseerr/templates/library/base_v1_1_3/resources.py b/ix-dev/community/jellyseerr/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/jellyseerr/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/jellyseerr/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/jellyseerr/templates/library/base_v1_1_3/security.py b/ix-dev/community/jellyseerr/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/jellyseerr/templates/library/base_v1_1_3/security.py rename to ix-dev/community/jellyseerr/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/jellyseerr/templates/library/base_v1_1_3/storage.py b/ix-dev/community/jellyseerr/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/jellyseerr/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/jellyseerr/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/jellyseerr/templates/library/base_v1_1_3/utils.py b/ix-dev/community/jellyseerr/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/jellyseerr/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/jellyseerr/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/jenkins/app.yaml b/ix-dev/community/jenkins/app.yaml index b6160ec74d..8646058047 100644 --- a/ix-dev/community/jenkins/app.yaml +++ b/ix-dev/community/jenkins/app.yaml @@ -9,8 +9,8 @@ icon: https://media.sys.truenas.net/apps/jenkins/icons/icon.svg keywords: - automation - ci/cd -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -31,4 +31,4 @@ sources: - https://www.jenkins.io/ title: Jenkins train: community -version: 1.0.12 +version: 1.0.13 diff --git a/ix-dev/community/jenkins/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/jenkins/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/jenkins/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/jenkins/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/jenkins/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/jenkins/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/jenkins/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/jenkins/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/jenkins/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/jenkins/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/jenkins/templates/library/base_v1_1_3/environment.py b/ix-dev/community/jenkins/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/jenkins/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/jenkins/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/jenkins/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/jenkins/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/jenkins/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/jenkins/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/jenkins/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/jenkins/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/jenkins/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/jenkins/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/jenkins/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/jenkins/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/jenkins/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/jenkins/templates/library/base_v1_1_3/network.py b/ix-dev/community/jenkins/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/jenkins/templates/library/base_v1_1_3/network.py rename to ix-dev/community/jenkins/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/jenkins/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/jenkins/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/jenkins/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/jenkins/templates/library/base_v1_1_3/ports.py b/ix-dev/community/jenkins/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/jenkins/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/jenkins/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/jenkins/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/jenkins/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/jenkins/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/jenkins/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/jenkins/templates/library/base_v1_1_3/redis.py b/ix-dev/community/jenkins/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/jenkins/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/jenkins/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/jenkins/templates/library/base_v1_1_3/resources.py b/ix-dev/community/jenkins/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/jenkins/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/jenkins/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/jenkins/templates/library/base_v1_1_3/security.py b/ix-dev/community/jenkins/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/jenkins/templates/library/base_v1_1_3/security.py rename to ix-dev/community/jenkins/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/jenkins/templates/library/base_v1_1_3/storage.py b/ix-dev/community/jenkins/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/jenkins/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/jenkins/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/jenkins/templates/library/base_v1_1_3/utils.py b/ix-dev/community/jenkins/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/jenkins/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/jenkins/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/joplin/app.yaml b/ix-dev/community/joplin/app.yaml index 81e170dc1a..b5d5ec75a9 100644 --- a/ix-dev/community/joplin/app.yaml +++ b/ix-dev/community/joplin/app.yaml @@ -9,8 +9,8 @@ host_mounts: [] icon: https://media.sys.truenas.net/apps/joplin/icons/icon.png keywords: - notes -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -36,4 +36,4 @@ sources: - https://hub.docker.com/r/joplin/server/ title: Joplin train: community -version: 1.1.10 +version: 1.1.11 diff --git a/ix-dev/community/joplin/templates/docker-compose.yaml b/ix-dev/community/joplin/templates/docker-compose.yaml index ff39595846..a7c61afdd6 100644 --- a/ix-dev/community/joplin/templates/docker-compose.yaml +++ b/ix-dev/community/joplin/templates/docker-compose.yaml @@ -58,7 +58,7 @@ services: {% if values.network.dns_opts %} dns_opt: {{ ix_lib.base.network.dns_opts(values.network.dns_opts) | tojson }} {% endif %} - {% set test = ix_lib.base.healthchecks.http_test(port=values.network.web_port, path="/api/ping") %} + {% set test = ix_lib.base.healthchecks.tcp_test(port=values.network.web_port) %} healthcheck: {{ ix_lib.base.healthchecks.check_health(test) | tojson }} environment: {{ ix_lib.base.environment.envs(app={ "APP_PORT": values.network.web_port, diff --git a/ix-dev/community/joplin/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/joplin/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/joplin/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/joplin/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/joplin/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/joplin/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/joplin/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/joplin/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/joplin/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/joplin/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/joplin/templates/library/base_v1_1_3/environment.py b/ix-dev/community/joplin/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/joplin/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/joplin/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/joplin/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/joplin/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/joplin/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/joplin/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/joplin/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/joplin/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/joplin/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/joplin/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/joplin/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/joplin/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/joplin/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/joplin/templates/library/base_v1_1_3/network.py b/ix-dev/community/joplin/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/joplin/templates/library/base_v1_1_3/network.py rename to ix-dev/community/joplin/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/joplin/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/joplin/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/joplin/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/joplin/templates/library/base_v1_1_3/ports.py b/ix-dev/community/joplin/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/joplin/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/joplin/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/joplin/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/joplin/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/joplin/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/joplin/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/joplin/templates/library/base_v1_1_3/redis.py b/ix-dev/community/joplin/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/joplin/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/joplin/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/joplin/templates/library/base_v1_1_3/resources.py b/ix-dev/community/joplin/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/joplin/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/joplin/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/joplin/templates/library/base_v1_1_3/security.py b/ix-dev/community/joplin/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/joplin/templates/library/base_v1_1_3/security.py rename to ix-dev/community/joplin/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/joplin/templates/library/base_v1_1_3/storage.py b/ix-dev/community/joplin/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/joplin/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/joplin/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/joplin/templates/library/base_v1_1_3/utils.py b/ix-dev/community/joplin/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/joplin/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/joplin/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/kapowarr/app.yaml b/ix-dev/community/kapowarr/app.yaml index fbdb0379c7..bbeb5c3bc4 100644 --- a/ix-dev/community/kapowarr/app.yaml +++ b/ix-dev/community/kapowarr/app.yaml @@ -10,8 +10,8 @@ icon: https://media.sys.truenas.net/apps/kapowarr/icons/icon.svg keywords: - comic - media -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -31,4 +31,4 @@ sources: - https://github.com/Casvt/Kapowarr title: Kapowarr train: community -version: 1.0.18 +version: 1.0.19 diff --git a/ix-dev/community/kapowarr/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/kapowarr/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/kapowarr/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/kapowarr/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/kapowarr/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/kapowarr/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/kapowarr/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/kapowarr/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/kapowarr/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/kapowarr/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/kapowarr/templates/library/base_v1_1_3/environment.py b/ix-dev/community/kapowarr/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/kapowarr/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/kapowarr/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/kapowarr/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/kapowarr/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/kapowarr/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/kapowarr/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/kapowarr/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/kapowarr/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/kapowarr/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/kapowarr/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/kapowarr/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/kapowarr/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/kapowarr/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/kapowarr/templates/library/base_v1_1_3/network.py b/ix-dev/community/kapowarr/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/kapowarr/templates/library/base_v1_1_3/network.py rename to ix-dev/community/kapowarr/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/kapowarr/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/kapowarr/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/kapowarr/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/kapowarr/templates/library/base_v1_1_3/ports.py b/ix-dev/community/kapowarr/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/kapowarr/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/kapowarr/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/kapowarr/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/kapowarr/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/kapowarr/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/kapowarr/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/kapowarr/templates/library/base_v1_1_3/redis.py b/ix-dev/community/kapowarr/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/kapowarr/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/kapowarr/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/kapowarr/templates/library/base_v1_1_3/resources.py b/ix-dev/community/kapowarr/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/kapowarr/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/kapowarr/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/kapowarr/templates/library/base_v1_1_3/security.py b/ix-dev/community/kapowarr/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/kapowarr/templates/library/base_v1_1_3/security.py rename to ix-dev/community/kapowarr/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/kapowarr/templates/library/base_v1_1_3/storage.py b/ix-dev/community/kapowarr/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/kapowarr/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/kapowarr/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/kapowarr/templates/library/base_v1_1_3/utils.py b/ix-dev/community/kapowarr/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/kapowarr/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/kapowarr/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/kavita/app.yaml b/ix-dev/community/kavita/app.yaml index 896fd303de..74660b2d72 100644 --- a/ix-dev/community/kavita/app.yaml +++ b/ix-dev/community/kavita/app.yaml @@ -20,8 +20,8 @@ icon: https://media.sys.truenas.net/apps/kavita/icons/icon.png keywords: - ebook - manga -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -44,4 +44,4 @@ sources: - https://www.kavitareader.com title: Kavita train: community -version: 1.0.18 +version: 1.0.19 diff --git a/ix-dev/community/kavita/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/kavita/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/kavita/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/kavita/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/kavita/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/kavita/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/kavita/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/kavita/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/kavita/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/kavita/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/kavita/templates/library/base_v1_1_3/environment.py b/ix-dev/community/kavita/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/kavita/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/kavita/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/kavita/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/kavita/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/kavita/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/kavita/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/kavita/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/kavita/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/kavita/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/kavita/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/kavita/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/kavita/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/kavita/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/kavita/templates/library/base_v1_1_3/network.py b/ix-dev/community/kavita/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/kavita/templates/library/base_v1_1_3/network.py rename to ix-dev/community/kavita/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/kavita/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/kavita/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/kavita/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/kavita/templates/library/base_v1_1_3/ports.py b/ix-dev/community/kavita/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/kavita/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/kavita/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/kavita/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/kavita/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/kavita/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/kavita/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/kavita/templates/library/base_v1_1_3/redis.py b/ix-dev/community/kavita/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/kavita/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/kavita/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/kavita/templates/library/base_v1_1_3/resources.py b/ix-dev/community/kavita/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/kavita/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/kavita/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/kavita/templates/library/base_v1_1_3/security.py b/ix-dev/community/kavita/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/kavita/templates/library/base_v1_1_3/security.py rename to ix-dev/community/kavita/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/kavita/templates/library/base_v1_1_3/storage.py b/ix-dev/community/kavita/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/kavita/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/kavita/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/kavita/templates/library/base_v1_1_3/utils.py b/ix-dev/community/kavita/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/kavita/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/kavita/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/komga/app.yaml b/ix-dev/community/komga/app.yaml index 403369718b..1972899fda 100644 --- a/ix-dev/community/komga/app.yaml +++ b/ix-dev/community/komga/app.yaml @@ -10,8 +10,8 @@ keywords: - media - comics - mangas -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -31,4 +31,4 @@ sources: - https://hub.docker.com/r/gotson/komga title: Komga train: community -version: 1.1.13 +version: 1.1.14 diff --git a/ix-dev/community/komga/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/komga/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/komga/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/komga/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/komga/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/komga/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/komga/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/komga/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/komga/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/komga/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/komga/templates/library/base_v1_1_3/environment.py b/ix-dev/community/komga/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/komga/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/komga/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/komga/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/komga/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/komga/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/komga/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/komga/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/komga/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/komga/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/komga/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/komga/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/komga/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/komga/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/komga/templates/library/base_v1_1_3/network.py b/ix-dev/community/komga/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/komga/templates/library/base_v1_1_3/network.py rename to ix-dev/community/komga/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/komga/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/komga/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/komga/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/komga/templates/library/base_v1_1_3/ports.py b/ix-dev/community/komga/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/komga/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/komga/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/komga/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/komga/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/komga/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/komga/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/komga/templates/library/base_v1_1_3/redis.py b/ix-dev/community/komga/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/komga/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/komga/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/komga/templates/library/base_v1_1_3/resources.py b/ix-dev/community/komga/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/komga/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/komga/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/komga/templates/library/base_v1_1_3/security.py b/ix-dev/community/komga/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/komga/templates/library/base_v1_1_3/security.py rename to ix-dev/community/komga/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/komga/templates/library/base_v1_1_3/storage.py b/ix-dev/community/komga/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/komga/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/komga/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/komga/templates/library/base_v1_1_3/utils.py b/ix-dev/community/komga/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/komga/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/komga/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/lidarr/app.yaml b/ix-dev/community/lidarr/app.yaml index f28e079ee1..f424e00a71 100644 --- a/ix-dev/community/lidarr/app.yaml +++ b/ix-dev/community/lidarr/app.yaml @@ -9,8 +9,8 @@ icon: https://media.sys.truenas.net/apps/lidarr/icons/icon.png keywords: - media - music -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -31,4 +31,4 @@ sources: - https://github.com/Lidarr/Lidarr title: Lidarr train: community -version: 1.1.11 +version: 1.1.12 diff --git a/ix-dev/community/lidarr/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/lidarr/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/lidarr/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/lidarr/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/lidarr/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/lidarr/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/lidarr/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/lidarr/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/lidarr/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/lidarr/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/lidarr/templates/library/base_v1_1_3/environment.py b/ix-dev/community/lidarr/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/lidarr/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/lidarr/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/lidarr/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/lidarr/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/lidarr/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/lidarr/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/lidarr/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/lidarr/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/lidarr/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/lidarr/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/lidarr/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/lidarr/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/lidarr/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/lidarr/templates/library/base_v1_1_3/network.py b/ix-dev/community/lidarr/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/lidarr/templates/library/base_v1_1_3/network.py rename to ix-dev/community/lidarr/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/lidarr/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/lidarr/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/lidarr/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/lidarr/templates/library/base_v1_1_3/ports.py b/ix-dev/community/lidarr/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/lidarr/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/lidarr/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/lidarr/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/lidarr/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/lidarr/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/lidarr/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/lidarr/templates/library/base_v1_1_3/redis.py b/ix-dev/community/lidarr/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/lidarr/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/lidarr/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/lidarr/templates/library/base_v1_1_3/resources.py b/ix-dev/community/lidarr/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/lidarr/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/lidarr/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/lidarr/templates/library/base_v1_1_3/security.py b/ix-dev/community/lidarr/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/lidarr/templates/library/base_v1_1_3/security.py rename to ix-dev/community/lidarr/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/lidarr/templates/library/base_v1_1_3/storage.py b/ix-dev/community/lidarr/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/lidarr/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/lidarr/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/lidarr/templates/library/base_v1_1_3/utils.py b/ix-dev/community/lidarr/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/lidarr/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/lidarr/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/linkding/app.yaml b/ix-dev/community/linkding/app.yaml index f0989dbe6c..e415d65cec 100644 --- a/ix-dev/community/linkding/app.yaml +++ b/ix-dev/community/linkding/app.yaml @@ -8,8 +8,8 @@ host_mounts: [] icon: https://media.sys.truenas.net/apps/linkding/icons/icon.svg keywords: - bookmark -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -33,4 +33,4 @@ sources: - https://hub.docker.com/r/sissbruecker/linkding/ title: Linkding train: community -version: 1.0.16 +version: 1.0.17 diff --git a/ix-dev/community/linkding/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/linkding/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/linkding/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/linkding/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/linkding/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/linkding/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/linkding/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/linkding/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/linkding/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/linkding/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/linkding/templates/library/base_v1_1_3/environment.py b/ix-dev/community/linkding/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/linkding/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/linkding/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/linkding/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/linkding/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/linkding/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/linkding/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/linkding/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/linkding/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/linkding/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/linkding/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/linkding/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/linkding/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/linkding/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/linkding/templates/library/base_v1_1_3/network.py b/ix-dev/community/linkding/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/linkding/templates/library/base_v1_1_3/network.py rename to ix-dev/community/linkding/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/linkding/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/linkding/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/linkding/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/linkding/templates/library/base_v1_1_3/ports.py b/ix-dev/community/linkding/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/linkding/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/linkding/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/linkding/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/linkding/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/linkding/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/linkding/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/linkding/templates/library/base_v1_1_3/redis.py b/ix-dev/community/linkding/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/linkding/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/linkding/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/linkding/templates/library/base_v1_1_3/resources.py b/ix-dev/community/linkding/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/linkding/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/linkding/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/linkding/templates/library/base_v1_1_3/security.py b/ix-dev/community/linkding/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/linkding/templates/library/base_v1_1_3/security.py rename to ix-dev/community/linkding/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/linkding/templates/library/base_v1_1_3/storage.py b/ix-dev/community/linkding/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/linkding/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/linkding/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/linkding/templates/library/base_v1_1_3/utils.py b/ix-dev/community/linkding/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/linkding/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/linkding/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/listmonk/app.yaml b/ix-dev/community/listmonk/app.yaml index 0ba7a70576..eae0446203 100644 --- a/ix-dev/community/listmonk/app.yaml +++ b/ix-dev/community/listmonk/app.yaml @@ -9,8 +9,8 @@ icon: https://media.sys.truenas.net/apps/listmonk/icons/icon.svg keywords: - mailing-list - newsletter -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -36,4 +36,4 @@ sources: - https://github.com/knadh/listmonk title: Listmonk train: community -version: 1.0.8 +version: 1.0.9 diff --git a/ix-dev/community/listmonk/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/listmonk/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/listmonk/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/listmonk/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/listmonk/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/listmonk/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/listmonk/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/listmonk/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/listmonk/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/listmonk/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/listmonk/templates/library/base_v1_1_3/environment.py b/ix-dev/community/listmonk/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/listmonk/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/listmonk/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/listmonk/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/listmonk/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/listmonk/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/listmonk/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/listmonk/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/listmonk/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/listmonk/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/listmonk/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/listmonk/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/listmonk/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/listmonk/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/listmonk/templates/library/base_v1_1_3/network.py b/ix-dev/community/listmonk/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/listmonk/templates/library/base_v1_1_3/network.py rename to ix-dev/community/listmonk/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/listmonk/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/listmonk/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/listmonk/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/listmonk/templates/library/base_v1_1_3/ports.py b/ix-dev/community/listmonk/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/listmonk/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/listmonk/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/listmonk/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/listmonk/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/listmonk/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/listmonk/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/listmonk/templates/library/base_v1_1_3/redis.py b/ix-dev/community/listmonk/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/listmonk/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/listmonk/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/listmonk/templates/library/base_v1_1_3/resources.py b/ix-dev/community/listmonk/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/listmonk/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/listmonk/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/listmonk/templates/library/base_v1_1_3/security.py b/ix-dev/community/listmonk/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/listmonk/templates/library/base_v1_1_3/security.py rename to ix-dev/community/listmonk/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/listmonk/templates/library/base_v1_1_3/storage.py b/ix-dev/community/listmonk/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/listmonk/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/listmonk/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/listmonk/templates/library/base_v1_1_3/utils.py b/ix-dev/community/listmonk/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/listmonk/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/listmonk/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/logseq/app.yaml b/ix-dev/community/logseq/app.yaml index b45a31e864..2109854e47 100644 --- a/ix-dev/community/logseq/app.yaml +++ b/ix-dev/community/logseq/app.yaml @@ -10,8 +10,8 @@ icon: https://media.sys.truenas.net/apps/logseq/icons/icon.png keywords: - knowledge - management -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -28,4 +28,4 @@ sources: - https://github.com/logseq/logseq title: Logseq train: community -version: 1.0.17 +version: 1.0.18 diff --git a/ix-dev/community/logseq/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/logseq/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/logseq/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/logseq/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/logseq/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/logseq/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/logseq/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/logseq/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/logseq/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/logseq/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/logseq/templates/library/base_v1_1_3/environment.py b/ix-dev/community/logseq/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/logseq/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/logseq/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/logseq/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/logseq/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/logseq/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/logseq/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/logseq/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/logseq/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/logseq/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/logseq/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/logseq/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/logseq/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/logseq/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/logseq/templates/library/base_v1_1_3/network.py b/ix-dev/community/logseq/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/logseq/templates/library/base_v1_1_3/network.py rename to ix-dev/community/logseq/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/logseq/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/logseq/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/logseq/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/logseq/templates/library/base_v1_1_3/ports.py b/ix-dev/community/logseq/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/logseq/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/logseq/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/logseq/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/logseq/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/logseq/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/logseq/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/logseq/templates/library/base_v1_1_3/redis.py b/ix-dev/community/logseq/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/logseq/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/logseq/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/logseq/templates/library/base_v1_1_3/resources.py b/ix-dev/community/logseq/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/logseq/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/logseq/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/logseq/templates/library/base_v1_1_3/security.py b/ix-dev/community/logseq/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/logseq/templates/library/base_v1_1_3/security.py rename to ix-dev/community/logseq/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/logseq/templates/library/base_v1_1_3/storage.py b/ix-dev/community/logseq/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/logseq/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/logseq/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/logseq/templates/library/base_v1_1_3/utils.py b/ix-dev/community/logseq/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/logseq/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/logseq/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/mealie/app.yaml b/ix-dev/community/mealie/app.yaml index aadb2ca590..f7ee0cd243 100644 --- a/ix-dev/community/mealie/app.yaml +++ b/ix-dev/community/mealie/app.yaml @@ -9,8 +9,8 @@ icon: https://media.sys.truenas.net/apps/mealie/icons/icon.png keywords: - recipes - meal planner -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -33,4 +33,4 @@ sources: - https://docs.mealie.io/ title: Mealie train: community -version: 1.2.9 +version: 1.2.10 diff --git a/ix-dev/community/mealie/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/mealie/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/mealie/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/mealie/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/mealie/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/mealie/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/mealie/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/mealie/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/mealie/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/mealie/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/mealie/templates/library/base_v1_1_3/environment.py b/ix-dev/community/mealie/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/mealie/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/mealie/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/mealie/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/mealie/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/mealie/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/mealie/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/mealie/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/mealie/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/mealie/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/mealie/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/mealie/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/mealie/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/mealie/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/mealie/templates/library/base_v1_1_3/network.py b/ix-dev/community/mealie/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/mealie/templates/library/base_v1_1_3/network.py rename to ix-dev/community/mealie/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/mealie/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/mealie/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/mealie/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/mealie/templates/library/base_v1_1_3/ports.py b/ix-dev/community/mealie/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/mealie/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/mealie/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/mealie/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/mealie/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/mealie/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/mealie/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/mealie/templates/library/base_v1_1_3/redis.py b/ix-dev/community/mealie/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/mealie/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/mealie/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/mealie/templates/library/base_v1_1_3/resources.py b/ix-dev/community/mealie/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/mealie/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/mealie/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/mealie/templates/library/base_v1_1_3/security.py b/ix-dev/community/mealie/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/mealie/templates/library/base_v1_1_3/security.py rename to ix-dev/community/mealie/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/mealie/templates/library/base_v1_1_3/storage.py b/ix-dev/community/mealie/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/mealie/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/mealie/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/mealie/templates/library/base_v1_1_3/utils.py b/ix-dev/community/mealie/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/mealie/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/mealie/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/metube/app.yaml b/ix-dev/community/metube/app.yaml index 91a2f3855d..d3f1e0fd49 100644 --- a/ix-dev/community/metube/app.yaml +++ b/ix-dev/community/metube/app.yaml @@ -10,8 +10,8 @@ icon: https://media.sys.truenas.net/apps/metube/icons/icon.svg keywords: - youtube-dl - yt-dlp -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -30,4 +30,4 @@ sources: - https://github.com/alexta69/metube title: MeTube train: community -version: 1.1.16 +version: 1.1.17 diff --git a/ix-dev/community/metube/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/metube/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/metube/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/metube/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/metube/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/metube/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/metube/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/metube/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/metube/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/metube/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/metube/templates/library/base_v1_1_3/environment.py b/ix-dev/community/metube/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/metube/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/metube/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/metube/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/metube/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/metube/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/metube/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/metube/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/metube/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/metube/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/metube/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/metube/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/metube/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/metube/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/metube/templates/library/base_v1_1_3/network.py b/ix-dev/community/metube/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/metube/templates/library/base_v1_1_3/network.py rename to ix-dev/community/metube/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/metube/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/metube/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/metube/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/metube/templates/library/base_v1_1_3/ports.py b/ix-dev/community/metube/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/metube/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/metube/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/metube/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/metube/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/metube/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/metube/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/metube/templates/library/base_v1_1_3/redis.py b/ix-dev/community/metube/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/metube/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/metube/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/metube/templates/library/base_v1_1_3/resources.py b/ix-dev/community/metube/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/metube/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/metube/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/metube/templates/library/base_v1_1_3/security.py b/ix-dev/community/metube/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/metube/templates/library/base_v1_1_3/security.py rename to ix-dev/community/metube/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/metube/templates/library/base_v1_1_3/storage.py b/ix-dev/community/metube/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/metube/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/metube/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/metube/templates/library/base_v1_1_3/utils.py b/ix-dev/community/metube/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/metube/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/metube/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/minecraft/app.yaml b/ix-dev/community/minecraft/app.yaml index 25a0f8934d..6fd82af0be 100644 --- a/ix-dev/community/minecraft/app.yaml +++ b/ix-dev/community/minecraft/app.yaml @@ -19,8 +19,8 @@ icon: https://media.sys.truenas.net/apps/minecraft/icons/icon.svg keywords: - world - building -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -38,4 +38,4 @@ sources: - https://github.com/itzg/docker-minecraft-server title: Minecraft train: community -version: 1.11.17 +version: 1.11.18 diff --git a/ix-dev/community/minecraft/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/minecraft/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/minecraft/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/minecraft/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/minecraft/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/minecraft/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/minecraft/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/minecraft/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/minecraft/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/minecraft/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/minecraft/templates/library/base_v1_1_3/environment.py b/ix-dev/community/minecraft/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/minecraft/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/minecraft/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/minecraft/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/minecraft/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/minecraft/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/minecraft/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/minecraft/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/minecraft/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/minecraft/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/minecraft/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/minecraft/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/minecraft/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/minecraft/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/minecraft/templates/library/base_v1_1_3/network.py b/ix-dev/community/minecraft/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/minecraft/templates/library/base_v1_1_3/network.py rename to ix-dev/community/minecraft/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/minecraft/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/minecraft/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/minecraft/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/minecraft/templates/library/base_v1_1_3/ports.py b/ix-dev/community/minecraft/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/minecraft/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/minecraft/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/minecraft/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/minecraft/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/minecraft/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/minecraft/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/minecraft/templates/library/base_v1_1_3/redis.py b/ix-dev/community/minecraft/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/minecraft/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/minecraft/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/minecraft/templates/library/base_v1_1_3/resources.py b/ix-dev/community/minecraft/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/minecraft/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/minecraft/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/minecraft/templates/library/base_v1_1_3/security.py b/ix-dev/community/minecraft/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/minecraft/templates/library/base_v1_1_3/security.py rename to ix-dev/community/minecraft/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/minecraft/templates/library/base_v1_1_3/storage.py b/ix-dev/community/minecraft/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/minecraft/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/minecraft/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/minecraft/templates/library/base_v1_1_3/utils.py b/ix-dev/community/minecraft/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/minecraft/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/minecraft/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/mineos/app.yaml b/ix-dev/community/mineos/app.yaml index 634c5e910f..55f7151289 100644 --- a/ix-dev/community/mineos/app.yaml +++ b/ix-dev/community/mineos/app.yaml @@ -19,8 +19,8 @@ host_mounts: [] icon: https://media.sys.truenas.net/apps/mineos/icons/icon.png keywords: - minecraft -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -39,4 +39,4 @@ sources: - https://github.com/hexparrot/mineos-node title: MineOS train: community -version: 1.0.17 +version: 1.0.18 diff --git a/ix-dev/community/mineos/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/mineos/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/mineos/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/mineos/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/mineos/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/mineos/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/mineos/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/mineos/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/mineos/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/mineos/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/mineos/templates/library/base_v1_1_3/environment.py b/ix-dev/community/mineos/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/mineos/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/mineos/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/mineos/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/mineos/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/mineos/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/mineos/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/mineos/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/mineos/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/mineos/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/mineos/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/mineos/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/mineos/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/mineos/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/mineos/templates/library/base_v1_1_3/network.py b/ix-dev/community/mineos/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/mineos/templates/library/base_v1_1_3/network.py rename to ix-dev/community/mineos/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/mineos/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/mineos/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/mineos/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/mineos/templates/library/base_v1_1_3/ports.py b/ix-dev/community/mineos/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/mineos/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/mineos/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/mineos/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/mineos/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/mineos/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/mineos/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/mineos/templates/library/base_v1_1_3/redis.py b/ix-dev/community/mineos/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/mineos/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/mineos/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/mineos/templates/library/base_v1_1_3/resources.py b/ix-dev/community/mineos/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/mineos/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/mineos/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/mineos/templates/library/base_v1_1_3/security.py b/ix-dev/community/mineos/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/mineos/templates/library/base_v1_1_3/security.py rename to ix-dev/community/mineos/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/mineos/templates/library/base_v1_1_3/storage.py b/ix-dev/community/mineos/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/mineos/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/mineos/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/mineos/templates/library/base_v1_1_3/utils.py b/ix-dev/community/mineos/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/mineos/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/mineos/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/mumble/app.yaml b/ix-dev/community/mumble/app.yaml index 37fbb74d79..e5d1d2b758 100644 --- a/ix-dev/community/mumble/app.yaml +++ b/ix-dev/community/mumble/app.yaml @@ -8,8 +8,8 @@ host_mounts: [] icon: https://media.sys.truenas.net/apps/mumble/icons/icon.svg keywords: - voice -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -27,4 +27,4 @@ sources: - https://www.mumble.info/ title: Mumble train: community -version: 1.1.9 +version: 1.1.10 diff --git a/ix-dev/community/mumble/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/mumble/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/mumble/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/mumble/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/mumble/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/mumble/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/mumble/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/mumble/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/mumble/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/mumble/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/mumble/templates/library/base_v1_1_3/environment.py b/ix-dev/community/mumble/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/mumble/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/mumble/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/mumble/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/mumble/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/mumble/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/mumble/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/mumble/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/mumble/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/mumble/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/mumble/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/mumble/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/mumble/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/mumble/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/mumble/templates/library/base_v1_1_3/network.py b/ix-dev/community/mumble/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/mumble/templates/library/base_v1_1_3/network.py rename to ix-dev/community/mumble/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/mumble/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/mumble/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/mumble/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/mumble/templates/library/base_v1_1_3/ports.py b/ix-dev/community/mumble/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/mumble/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/mumble/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/mumble/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/mumble/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/mumble/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/mumble/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/mumble/templates/library/base_v1_1_3/redis.py b/ix-dev/community/mumble/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/mumble/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/mumble/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/mumble/templates/library/base_v1_1_3/resources.py b/ix-dev/community/mumble/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/mumble/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/mumble/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/mumble/templates/library/base_v1_1_3/security.py b/ix-dev/community/mumble/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/mumble/templates/library/base_v1_1_3/security.py rename to ix-dev/community/mumble/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/mumble/templates/library/base_v1_1_3/storage.py b/ix-dev/community/mumble/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/mumble/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/mumble/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/mumble/templates/library/base_v1_1_3/utils.py b/ix-dev/community/mumble/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/mumble/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/mumble/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/n8n/app.yaml b/ix-dev/community/n8n/app.yaml index 52b139ce86..7f220747a4 100644 --- a/ix-dev/community/n8n/app.yaml +++ b/ix-dev/community/n8n/app.yaml @@ -9,8 +9,8 @@ icon: https://media.sys.truenas.net/apps/n8n/icons/icon.png keywords: - workflows - automation -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -42,4 +42,4 @@ sources: - https://hub.docker.com/r/n8nio/n8n title: n8n train: community -version: 1.3.22 +version: 1.3.23 diff --git a/ix-dev/community/n8n/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/n8n/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/n8n/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/n8n/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/n8n/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/n8n/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/n8n/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/n8n/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/n8n/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/n8n/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/n8n/templates/library/base_v1_1_3/environment.py b/ix-dev/community/n8n/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/n8n/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/n8n/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/n8n/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/n8n/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/n8n/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/n8n/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/n8n/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/n8n/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/n8n/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/n8n/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/n8n/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/n8n/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/n8n/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/n8n/templates/library/base_v1_1_3/network.py b/ix-dev/community/n8n/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/n8n/templates/library/base_v1_1_3/network.py rename to ix-dev/community/n8n/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/n8n/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/n8n/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/n8n/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/n8n/templates/library/base_v1_1_3/ports.py b/ix-dev/community/n8n/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/n8n/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/n8n/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/n8n/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/n8n/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/n8n/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/n8n/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/n8n/templates/library/base_v1_1_3/redis.py b/ix-dev/community/n8n/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/n8n/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/n8n/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/n8n/templates/library/base_v1_1_3/resources.py b/ix-dev/community/n8n/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/n8n/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/n8n/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/n8n/templates/library/base_v1_1_3/security.py b/ix-dev/community/n8n/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/n8n/templates/library/base_v1_1_3/security.py rename to ix-dev/community/n8n/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/n8n/templates/library/base_v1_1_3/storage.py b/ix-dev/community/n8n/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/n8n/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/n8n/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/n8n/templates/library/base_v1_1_3/utils.py b/ix-dev/community/n8n/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/n8n/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/n8n/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/navidrome/app.yaml b/ix-dev/community/navidrome/app.yaml index a483fdac79..d392cfe844 100644 --- a/ix-dev/community/navidrome/app.yaml +++ b/ix-dev/community/navidrome/app.yaml @@ -11,8 +11,8 @@ icon: https://media.sys.truenas.net/apps/navidrome/icons/icon.png keywords: - media - music -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -32,4 +32,4 @@ sources: - https://github.com/navidrome/navidrome/ title: Navidrome train: community -version: 1.0.23 +version: 1.0.24 diff --git a/ix-dev/community/navidrome/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/navidrome/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/navidrome/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/navidrome/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/navidrome/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/navidrome/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/navidrome/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/navidrome/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/navidrome/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/navidrome/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/navidrome/templates/library/base_v1_1_3/environment.py b/ix-dev/community/navidrome/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/navidrome/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/navidrome/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/navidrome/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/navidrome/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/navidrome/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/navidrome/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/navidrome/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/navidrome/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/navidrome/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/navidrome/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/navidrome/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/navidrome/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/navidrome/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/navidrome/templates/library/base_v1_1_3/network.py b/ix-dev/community/navidrome/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/navidrome/templates/library/base_v1_1_3/network.py rename to ix-dev/community/navidrome/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/navidrome/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/navidrome/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/navidrome/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/navidrome/templates/library/base_v1_1_3/ports.py b/ix-dev/community/navidrome/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/navidrome/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/navidrome/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/navidrome/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/navidrome/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/navidrome/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/navidrome/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/navidrome/templates/library/base_v1_1_3/redis.py b/ix-dev/community/navidrome/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/navidrome/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/navidrome/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/navidrome/templates/library/base_v1_1_3/resources.py b/ix-dev/community/navidrome/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/navidrome/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/navidrome/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/navidrome/templates/library/base_v1_1_3/security.py b/ix-dev/community/navidrome/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/navidrome/templates/library/base_v1_1_3/security.py rename to ix-dev/community/navidrome/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/navidrome/templates/library/base_v1_1_3/storage.py b/ix-dev/community/navidrome/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/navidrome/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/navidrome/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/navidrome/templates/library/base_v1_1_3/utils.py b/ix-dev/community/navidrome/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/navidrome/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/navidrome/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/netbootxyz/app.yaml b/ix-dev/community/netbootxyz/app.yaml index 5613eaa384..0b5a998977 100644 --- a/ix-dev/community/netbootxyz/app.yaml +++ b/ix-dev/community/netbootxyz/app.yaml @@ -30,8 +30,8 @@ keywords: - netboot - netbootxyz - netboot.xyz -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -50,4 +50,4 @@ sources: - https://netboot.xyz title: Netboot.xyz train: community -version: 1.0.18 +version: 1.0.19 diff --git a/ix-dev/community/netbootxyz/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/netbootxyz/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/netbootxyz/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/netbootxyz/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/netbootxyz/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/netbootxyz/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/netbootxyz/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/netbootxyz/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/netbootxyz/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/netbootxyz/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/netbootxyz/templates/library/base_v1_1_3/environment.py b/ix-dev/community/netbootxyz/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/netbootxyz/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/netbootxyz/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/netbootxyz/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/netbootxyz/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/netbootxyz/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/netbootxyz/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/netbootxyz/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/netbootxyz/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/netbootxyz/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/netbootxyz/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/netbootxyz/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/netbootxyz/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/netbootxyz/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/netbootxyz/templates/library/base_v1_1_3/network.py b/ix-dev/community/netbootxyz/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/netbootxyz/templates/library/base_v1_1_3/network.py rename to ix-dev/community/netbootxyz/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/netbootxyz/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/netbootxyz/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/netbootxyz/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/netbootxyz/templates/library/base_v1_1_3/ports.py b/ix-dev/community/netbootxyz/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/netbootxyz/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/netbootxyz/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/netbootxyz/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/netbootxyz/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/netbootxyz/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/netbootxyz/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/netbootxyz/templates/library/base_v1_1_3/redis.py b/ix-dev/community/netbootxyz/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/netbootxyz/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/netbootxyz/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/netbootxyz/templates/library/base_v1_1_3/resources.py b/ix-dev/community/netbootxyz/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/netbootxyz/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/netbootxyz/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/netbootxyz/templates/library/base_v1_1_3/security.py b/ix-dev/community/netbootxyz/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/netbootxyz/templates/library/base_v1_1_3/security.py rename to ix-dev/community/netbootxyz/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/netbootxyz/templates/library/base_v1_1_3/storage.py b/ix-dev/community/netbootxyz/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/netbootxyz/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/netbootxyz/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/netbootxyz/templates/library/base_v1_1_3/utils.py b/ix-dev/community/netbootxyz/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/netbootxyz/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/netbootxyz/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/nginx-proxy-manager/app.yaml b/ix-dev/community/nginx-proxy-manager/app.yaml index 1a49bff700..5d13748073 100644 --- a/ix-dev/community/nginx-proxy-manager/app.yaml +++ b/ix-dev/community/nginx-proxy-manager/app.yaml @@ -22,8 +22,8 @@ keywords: - reverse - nginx - proxy -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -44,4 +44,4 @@ sources: - https://hub.docker.com/r/jc21/nginx-proxy-manager title: Nginx Proxy Manager train: community -version: 1.0.19 +version: 1.0.20 diff --git a/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_3/environment.py b/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_3/network.py b/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_3/network.py rename to ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_3/ports.py b/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_3/redis.py b/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_3/resources.py b/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_3/security.py b/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_3/security.py rename to ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_3/storage.py b/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_3/utils.py b/ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/nginx-proxy-manager/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/node-red/app.yaml b/ix-dev/community/node-red/app.yaml index 18a47a7705..ccc684f257 100644 --- a/ix-dev/community/node-red/app.yaml +++ b/ix-dev/community/node-red/app.yaml @@ -9,8 +9,8 @@ host_mounts: [] icon: https://media.sys.truenas.net/apps/node-red/icons/icon.png keywords: - automation -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -29,4 +29,4 @@ sources: - https://github.com/node-red/node-red-docker title: Node-RED train: community -version: 1.0.32 +version: 1.0.33 diff --git a/ix-dev/community/node-red/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/node-red/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/node-red/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/node-red/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/node-red/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/node-red/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/node-red/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/node-red/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/node-red/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/node-red/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/node-red/templates/library/base_v1_1_3/environment.py b/ix-dev/community/node-red/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/node-red/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/node-red/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/node-red/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/node-red/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/node-red/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/node-red/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/node-red/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/node-red/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/node-red/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/node-red/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/node-red/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/node-red/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/node-red/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/node-red/templates/library/base_v1_1_3/network.py b/ix-dev/community/node-red/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/node-red/templates/library/base_v1_1_3/network.py rename to ix-dev/community/node-red/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/node-red/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/node-red/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/node-red/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/node-red/templates/library/base_v1_1_3/ports.py b/ix-dev/community/node-red/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/node-red/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/node-red/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/node-red/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/node-red/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/node-red/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/node-red/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/node-red/templates/library/base_v1_1_3/redis.py b/ix-dev/community/node-red/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/node-red/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/node-red/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/node-red/templates/library/base_v1_1_3/resources.py b/ix-dev/community/node-red/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/node-red/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/node-red/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/node-red/templates/library/base_v1_1_3/security.py b/ix-dev/community/node-red/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/node-red/templates/library/base_v1_1_3/security.py rename to ix-dev/community/node-red/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/node-red/templates/library/base_v1_1_3/storage.py b/ix-dev/community/node-red/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/node-red/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/node-red/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/node-red/templates/library/base_v1_1_3/utils.py b/ix-dev/community/node-red/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/node-red/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/node-red/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/odoo/app.yaml b/ix-dev/community/odoo/app.yaml index 805901ae74..463d682ee1 100644 --- a/ix-dev/community/odoo/app.yaml +++ b/ix-dev/community/odoo/app.yaml @@ -9,8 +9,8 @@ icon: https://media.sys.truenas.net/apps/odoo/icons/icon.png keywords: - erp - odoo -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -30,4 +30,4 @@ sources: - https://github.com/odoo/odoo title: Odoo train: community -version: 1.0.3 +version: 1.0.4 diff --git a/ix-dev/community/odoo/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/odoo/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/odoo/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/odoo/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/odoo/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/odoo/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/odoo/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/odoo/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/odoo/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/odoo/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/odoo/templates/library/base_v1_1_3/environment.py b/ix-dev/community/odoo/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/odoo/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/odoo/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/odoo/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/odoo/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/odoo/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/odoo/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/odoo/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/odoo/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/odoo/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/odoo/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/odoo/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/odoo/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/odoo/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/odoo/templates/library/base_v1_1_3/network.py b/ix-dev/community/odoo/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/odoo/templates/library/base_v1_1_3/network.py rename to ix-dev/community/odoo/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/odoo/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/odoo/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/odoo/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/odoo/templates/library/base_v1_1_3/ports.py b/ix-dev/community/odoo/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/odoo/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/odoo/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/odoo/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/odoo/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/odoo/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/odoo/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/odoo/templates/library/base_v1_1_3/redis.py b/ix-dev/community/odoo/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/odoo/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/odoo/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/odoo/templates/library/base_v1_1_3/resources.py b/ix-dev/community/odoo/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/odoo/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/odoo/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/odoo/templates/library/base_v1_1_3/security.py b/ix-dev/community/odoo/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/odoo/templates/library/base_v1_1_3/security.py rename to ix-dev/community/odoo/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/odoo/templates/library/base_v1_1_3/storage.py b/ix-dev/community/odoo/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/odoo/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/odoo/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/odoo/templates/library/base_v1_1_3/utils.py b/ix-dev/community/odoo/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/odoo/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/odoo/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/omada-controller/app.yaml b/ix-dev/community/omada-controller/app.yaml index 5143a1671e..e3da5e442c 100644 --- a/ix-dev/community/omada-controller/app.yaml +++ b/ix-dev/community/omada-controller/app.yaml @@ -23,8 +23,8 @@ keywords: - controller - omada - tp-link -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -42,4 +42,4 @@ sources: - https://hub.docker.com/r/mbentley/omada-controller title: Bazarr train: community -version: 1.1.9 +version: 1.1.10 diff --git a/ix-dev/community/omada-controller/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/omada-controller/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/omada-controller/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/omada-controller/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/omada-controller/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/omada-controller/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/omada-controller/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/omada-controller/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/omada-controller/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/omada-controller/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/omada-controller/templates/library/base_v1_1_3/environment.py b/ix-dev/community/omada-controller/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/omada-controller/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/omada-controller/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/omada-controller/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/omada-controller/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/omada-controller/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/omada-controller/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/omada-controller/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/omada-controller/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/omada-controller/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/omada-controller/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/omada-controller/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/omada-controller/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/omada-controller/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/omada-controller/templates/library/base_v1_1_3/network.py b/ix-dev/community/omada-controller/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/omada-controller/templates/library/base_v1_1_3/network.py rename to ix-dev/community/omada-controller/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/omada-controller/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/omada-controller/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/omada-controller/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/omada-controller/templates/library/base_v1_1_3/ports.py b/ix-dev/community/omada-controller/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/omada-controller/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/omada-controller/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/omada-controller/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/omada-controller/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/omada-controller/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/omada-controller/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/omada-controller/templates/library/base_v1_1_3/redis.py b/ix-dev/community/omada-controller/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/omada-controller/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/omada-controller/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/omada-controller/templates/library/base_v1_1_3/resources.py b/ix-dev/community/omada-controller/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/omada-controller/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/omada-controller/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/omada-controller/templates/library/base_v1_1_3/security.py b/ix-dev/community/omada-controller/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/omada-controller/templates/library/base_v1_1_3/security.py rename to ix-dev/community/omada-controller/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/omada-controller/templates/library/base_v1_1_3/storage.py b/ix-dev/community/omada-controller/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/omada-controller/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/omada-controller/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/omada-controller/templates/library/base_v1_1_3/utils.py b/ix-dev/community/omada-controller/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/omada-controller/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/omada-controller/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/organizr/app.yaml b/ix-dev/community/organizr/app.yaml index fb1ee0dbbf..37534684c7 100644 --- a/ix-dev/community/organizr/app.yaml +++ b/ix-dev/community/organizr/app.yaml @@ -19,8 +19,8 @@ icon: https://media.sys.truenas.net/apps/organizr/icons/icon.png keywords: - dashboard - organizr -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -40,4 +40,4 @@ sources: - https://github.com/causefx/Organizr title: Organizr train: community -version: 1.0.17 +version: 1.0.18 diff --git a/ix-dev/community/organizr/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/organizr/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/organizr/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/organizr/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/organizr/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/organizr/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/organizr/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/organizr/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/organizr/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/organizr/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/organizr/templates/library/base_v1_1_3/environment.py b/ix-dev/community/organizr/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/organizr/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/organizr/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/organizr/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/organizr/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/organizr/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/organizr/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/organizr/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/organizr/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/organizr/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/organizr/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/organizr/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/organizr/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/organizr/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/organizr/templates/library/base_v1_1_3/network.py b/ix-dev/community/organizr/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/organizr/templates/library/base_v1_1_3/network.py rename to ix-dev/community/organizr/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/organizr/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/organizr/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/organizr/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/organizr/templates/library/base_v1_1_3/ports.py b/ix-dev/community/organizr/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/organizr/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/organizr/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/organizr/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/organizr/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/organizr/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/organizr/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/organizr/templates/library/base_v1_1_3/redis.py b/ix-dev/community/organizr/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/organizr/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/organizr/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/organizr/templates/library/base_v1_1_3/resources.py b/ix-dev/community/organizr/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/organizr/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/organizr/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/organizr/templates/library/base_v1_1_3/security.py b/ix-dev/community/organizr/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/organizr/templates/library/base_v1_1_3/security.py rename to ix-dev/community/organizr/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/organizr/templates/library/base_v1_1_3/storage.py b/ix-dev/community/organizr/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/organizr/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/organizr/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/organizr/templates/library/base_v1_1_3/utils.py b/ix-dev/community/organizr/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/organizr/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/organizr/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/overseerr/app.yaml b/ix-dev/community/overseerr/app.yaml index 501259abc4..97fc6d8a0c 100644 --- a/ix-dev/community/overseerr/app.yaml +++ b/ix-dev/community/overseerr/app.yaml @@ -9,8 +9,8 @@ host_mounts: [] icon: https://media.sys.truenas.net/apps/overseerr/icons/icon.svg keywords: - media -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -28,4 +28,4 @@ sources: - https://github.com/sct/overseerr title: Overseerr train: community -version: 1.0.17 +version: 1.0.18 diff --git a/ix-dev/community/overseerr/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/overseerr/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/overseerr/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/overseerr/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/overseerr/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/overseerr/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/overseerr/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/overseerr/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/overseerr/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/overseerr/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/overseerr/templates/library/base_v1_1_3/environment.py b/ix-dev/community/overseerr/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/overseerr/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/overseerr/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/overseerr/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/overseerr/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/overseerr/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/overseerr/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/overseerr/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/overseerr/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/overseerr/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/overseerr/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/overseerr/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/overseerr/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/overseerr/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/overseerr/templates/library/base_v1_1_3/network.py b/ix-dev/community/overseerr/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/overseerr/templates/library/base_v1_1_3/network.py rename to ix-dev/community/overseerr/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/overseerr/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/overseerr/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/overseerr/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/overseerr/templates/library/base_v1_1_3/ports.py b/ix-dev/community/overseerr/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/overseerr/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/overseerr/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/overseerr/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/overseerr/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/overseerr/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/overseerr/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/overseerr/templates/library/base_v1_1_3/redis.py b/ix-dev/community/overseerr/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/overseerr/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/overseerr/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/overseerr/templates/library/base_v1_1_3/resources.py b/ix-dev/community/overseerr/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/overseerr/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/overseerr/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/overseerr/templates/library/base_v1_1_3/security.py b/ix-dev/community/overseerr/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/overseerr/templates/library/base_v1_1_3/security.py rename to ix-dev/community/overseerr/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/overseerr/templates/library/base_v1_1_3/storage.py b/ix-dev/community/overseerr/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/overseerr/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/overseerr/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/overseerr/templates/library/base_v1_1_3/utils.py b/ix-dev/community/overseerr/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/overseerr/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/overseerr/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/palworld/app.yaml b/ix-dev/community/palworld/app.yaml index c63f4b01b4..a63c29ec0b 100644 --- a/ix-dev/community/palworld/app.yaml +++ b/ix-dev/community/palworld/app.yaml @@ -28,8 +28,8 @@ icon: https://media.sys.truenas.net/apps/palworld/icons/icon.webp keywords: - game - palworld -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -47,4 +47,4 @@ sources: - https://github.com/ich777/docker-steamcmd-server/tree/palworld title: Palworld train: community -version: 1.0.19 +version: 1.0.20 diff --git a/ix-dev/community/palworld/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/palworld/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/palworld/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/palworld/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/palworld/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/palworld/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/palworld/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/palworld/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/palworld/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/palworld/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/palworld/templates/library/base_v1_1_3/environment.py b/ix-dev/community/palworld/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/palworld/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/palworld/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/palworld/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/palworld/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/palworld/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/palworld/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/palworld/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/palworld/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/palworld/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/palworld/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/palworld/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/palworld/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/palworld/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/palworld/templates/library/base_v1_1_3/network.py b/ix-dev/community/palworld/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/palworld/templates/library/base_v1_1_3/network.py rename to ix-dev/community/palworld/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/palworld/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/palworld/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/palworld/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/palworld/templates/library/base_v1_1_3/ports.py b/ix-dev/community/palworld/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/palworld/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/palworld/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/palworld/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/palworld/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/palworld/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/palworld/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/palworld/templates/library/base_v1_1_3/redis.py b/ix-dev/community/palworld/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/palworld/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/palworld/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/palworld/templates/library/base_v1_1_3/resources.py b/ix-dev/community/palworld/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/palworld/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/palworld/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/palworld/templates/library/base_v1_1_3/security.py b/ix-dev/community/palworld/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/palworld/templates/library/base_v1_1_3/security.py rename to ix-dev/community/palworld/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/palworld/templates/library/base_v1_1_3/storage.py b/ix-dev/community/palworld/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/palworld/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/palworld/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/palworld/templates/library/base_v1_1_3/utils.py b/ix-dev/community/palworld/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/palworld/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/palworld/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/paperless-ngx/app.yaml b/ix-dev/community/paperless-ngx/app.yaml index 9a07aa56d7..a1186c153f 100644 --- a/ix-dev/community/paperless-ngx/app.yaml +++ b/ix-dev/community/paperless-ngx/app.yaml @@ -20,8 +20,8 @@ icon: https://media.sys.truenas.net/apps/paperless-ngx/icons/icon.svg keywords: - document - management -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -57,4 +57,4 @@ sources: - https://github.com/paperless-ngx/paperless-ngx title: Paperless-ngx train: community -version: 1.0.11 +version: 1.0.12 diff --git a/ix-dev/community/paperless-ngx/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/paperless-ngx/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/paperless-ngx/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/paperless-ngx/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/paperless-ngx/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/paperless-ngx/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/paperless-ngx/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/paperless-ngx/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/paperless-ngx/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/paperless-ngx/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/paperless-ngx/templates/library/base_v1_1_3/environment.py b/ix-dev/community/paperless-ngx/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/paperless-ngx/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/paperless-ngx/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/paperless-ngx/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/paperless-ngx/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/paperless-ngx/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/paperless-ngx/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/paperless-ngx/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/paperless-ngx/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/paperless-ngx/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/paperless-ngx/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/paperless-ngx/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/paperless-ngx/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/paperless-ngx/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/paperless-ngx/templates/library/base_v1_1_3/network.py b/ix-dev/community/paperless-ngx/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/paperless-ngx/templates/library/base_v1_1_3/network.py rename to ix-dev/community/paperless-ngx/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/paperless-ngx/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/paperless-ngx/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/paperless-ngx/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/paperless-ngx/templates/library/base_v1_1_3/ports.py b/ix-dev/community/paperless-ngx/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/paperless-ngx/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/paperless-ngx/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/paperless-ngx/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/paperless-ngx/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/paperless-ngx/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/paperless-ngx/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/paperless-ngx/templates/library/base_v1_1_3/redis.py b/ix-dev/community/paperless-ngx/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/paperless-ngx/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/paperless-ngx/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/paperless-ngx/templates/library/base_v1_1_3/resources.py b/ix-dev/community/paperless-ngx/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/paperless-ngx/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/paperless-ngx/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/paperless-ngx/templates/library/base_v1_1_3/security.py b/ix-dev/community/paperless-ngx/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/paperless-ngx/templates/library/base_v1_1_3/security.py rename to ix-dev/community/paperless-ngx/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/paperless-ngx/templates/library/base_v1_1_3/storage.py b/ix-dev/community/paperless-ngx/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/paperless-ngx/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/paperless-ngx/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/paperless-ngx/templates/library/base_v1_1_3/utils.py b/ix-dev/community/paperless-ngx/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/paperless-ngx/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/paperless-ngx/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/passbolt/app.yaml b/ix-dev/community/passbolt/app.yaml index 4b44e7644f..d1369f6eec 100644 --- a/ix-dev/community/passbolt/app.yaml +++ b/ix-dev/community/passbolt/app.yaml @@ -9,8 +9,8 @@ icon: https://media.sys.truenas.net/apps/passbolt/icons/icon.svg keywords: - password - manager -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -37,4 +37,4 @@ sources: - https://www.passbolt.com title: Passbolt train: community -version: 1.0.6 +version: 1.0.7 diff --git a/ix-dev/community/passbolt/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/passbolt/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/passbolt/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/passbolt/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/passbolt/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/passbolt/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/passbolt/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/passbolt/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/passbolt/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/passbolt/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/passbolt/templates/library/base_v1_1_3/environment.py b/ix-dev/community/passbolt/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/passbolt/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/passbolt/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/passbolt/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/passbolt/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/passbolt/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/passbolt/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/passbolt/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/passbolt/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/passbolt/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/passbolt/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/passbolt/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/passbolt/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/passbolt/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/passbolt/templates/library/base_v1_1_3/network.py b/ix-dev/community/passbolt/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/passbolt/templates/library/base_v1_1_3/network.py rename to ix-dev/community/passbolt/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/passbolt/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/passbolt/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/passbolt/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/passbolt/templates/library/base_v1_1_3/ports.py b/ix-dev/community/passbolt/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/passbolt/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/passbolt/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/passbolt/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/passbolt/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/passbolt/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/passbolt/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/passbolt/templates/library/base_v1_1_3/redis.py b/ix-dev/community/passbolt/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/passbolt/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/passbolt/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/passbolt/templates/library/base_v1_1_3/resources.py b/ix-dev/community/passbolt/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/passbolt/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/passbolt/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/passbolt/templates/library/base_v1_1_3/security.py b/ix-dev/community/passbolt/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/passbolt/templates/library/base_v1_1_3/security.py rename to ix-dev/community/passbolt/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/passbolt/templates/library/base_v1_1_3/storage.py b/ix-dev/community/passbolt/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/passbolt/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/passbolt/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/passbolt/templates/library/base_v1_1_3/utils.py b/ix-dev/community/passbolt/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/passbolt/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/passbolt/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/pgadmin/app.yaml b/ix-dev/community/pgadmin/app.yaml index 284bcb0a1a..91e254876c 100644 --- a/ix-dev/community/pgadmin/app.yaml +++ b/ix-dev/community/pgadmin/app.yaml @@ -12,8 +12,8 @@ icon: https://media.sys.truenas.net/apps/pgadmin/icons/icon.png keywords: - database - management -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -34,4 +34,4 @@ sources: - https://www.pgadmin.org/ title: pgAdmin train: community -version: 1.0.4 +version: 1.0.5 diff --git a/ix-dev/community/pgadmin/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/pgadmin/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/pgadmin/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/pgadmin/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/pgadmin/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/pgadmin/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/pgadmin/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/pgadmin/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/pgadmin/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/pgadmin/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/pgadmin/templates/library/base_v1_1_3/environment.py b/ix-dev/community/pgadmin/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/pgadmin/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/pgadmin/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/pgadmin/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/pgadmin/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/pgadmin/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/pgadmin/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/pgadmin/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/pgadmin/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/pgadmin/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/pgadmin/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/pgadmin/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/pgadmin/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/pgadmin/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/pgadmin/templates/library/base_v1_1_3/network.py b/ix-dev/community/pgadmin/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/pgadmin/templates/library/base_v1_1_3/network.py rename to ix-dev/community/pgadmin/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/pgadmin/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/pgadmin/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/pgadmin/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/pgadmin/templates/library/base_v1_1_3/ports.py b/ix-dev/community/pgadmin/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/pgadmin/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/pgadmin/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/pgadmin/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/pgadmin/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/pgadmin/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/pgadmin/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/pgadmin/templates/library/base_v1_1_3/redis.py b/ix-dev/community/pgadmin/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/pgadmin/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/pgadmin/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/pgadmin/templates/library/base_v1_1_3/resources.py b/ix-dev/community/pgadmin/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/pgadmin/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/pgadmin/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/pgadmin/templates/library/base_v1_1_3/security.py b/ix-dev/community/pgadmin/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/pgadmin/templates/library/base_v1_1_3/security.py rename to ix-dev/community/pgadmin/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/pgadmin/templates/library/base_v1_1_3/storage.py b/ix-dev/community/pgadmin/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/pgadmin/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/pgadmin/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/pgadmin/templates/library/base_v1_1_3/utils.py b/ix-dev/community/pgadmin/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/pgadmin/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/pgadmin/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/pigallery2/app.yaml b/ix-dev/community/pigallery2/app.yaml index 7df3986ede..f9e6a9dd74 100644 --- a/ix-dev/community/pigallery2/app.yaml +++ b/ix-dev/community/pigallery2/app.yaml @@ -10,8 +10,8 @@ icon: https://media.sys.truenas.net/apps/pigallery2/icons/icon.png keywords: - photo - media -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -39,4 +39,4 @@ sources: - https://github.com/bpatrik/pigallery2 title: PiGallery2 train: community -version: 1.0.5 +version: 1.0.6 diff --git a/ix-dev/community/pigallery2/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/pigallery2/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/pigallery2/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/pigallery2/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/pigallery2/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/pigallery2/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/pigallery2/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/pigallery2/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/pigallery2/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/pigallery2/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/pigallery2/templates/library/base_v1_1_3/environment.py b/ix-dev/community/pigallery2/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/pigallery2/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/pigallery2/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/pigallery2/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/pigallery2/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/pigallery2/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/pigallery2/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/pigallery2/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/pigallery2/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/pigallery2/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/pigallery2/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/pigallery2/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/pigallery2/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/pigallery2/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/pigallery2/templates/library/base_v1_1_3/network.py b/ix-dev/community/pigallery2/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/pigallery2/templates/library/base_v1_1_3/network.py rename to ix-dev/community/pigallery2/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/pigallery2/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/pigallery2/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/pigallery2/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/pigallery2/templates/library/base_v1_1_3/ports.py b/ix-dev/community/pigallery2/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/pigallery2/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/pigallery2/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/pigallery2/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/pigallery2/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/pigallery2/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/pigallery2/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/pigallery2/templates/library/base_v1_1_3/redis.py b/ix-dev/community/pigallery2/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/pigallery2/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/pigallery2/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/pigallery2/templates/library/base_v1_1_3/resources.py b/ix-dev/community/pigallery2/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/pigallery2/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/pigallery2/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/pigallery2/templates/library/base_v1_1_3/security.py b/ix-dev/community/pigallery2/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/pigallery2/templates/library/base_v1_1_3/security.py rename to ix-dev/community/pigallery2/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/pigallery2/templates/library/base_v1_1_3/storage.py b/ix-dev/community/pigallery2/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/pigallery2/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/pigallery2/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/pigallery2/templates/library/base_v1_1_3/utils.py b/ix-dev/community/pigallery2/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/pigallery2/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/pigallery2/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/piwigo/app.yaml b/ix-dev/community/piwigo/app.yaml index 7474864ccb..62aa6d522f 100644 --- a/ix-dev/community/piwigo/app.yaml +++ b/ix-dev/community/piwigo/app.yaml @@ -22,8 +22,8 @@ icon: https://media.sys.truenas.net/apps/piwigo/icons/icon.svg keywords: - photo - gallery -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -47,4 +47,4 @@ sources: - https://hub.docker.com/r/linuxserver/piwigo title: Piwigo train: community -version: 1.0.5 +version: 1.0.6 diff --git a/ix-dev/community/piwigo/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/piwigo/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/piwigo/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/piwigo/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/piwigo/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/piwigo/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/piwigo/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/piwigo/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/piwigo/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/piwigo/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/piwigo/templates/library/base_v1_1_3/environment.py b/ix-dev/community/piwigo/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/piwigo/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/piwigo/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/piwigo/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/piwigo/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/piwigo/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/piwigo/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/piwigo/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/piwigo/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/piwigo/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/piwigo/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/piwigo/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/piwigo/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/piwigo/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/piwigo/templates/library/base_v1_1_3/network.py b/ix-dev/community/piwigo/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/piwigo/templates/library/base_v1_1_3/network.py rename to ix-dev/community/piwigo/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/piwigo/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/piwigo/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/piwigo/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/piwigo/templates/library/base_v1_1_3/ports.py b/ix-dev/community/piwigo/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/piwigo/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/piwigo/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/piwigo/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/piwigo/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/piwigo/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/piwigo/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/piwigo/templates/library/base_v1_1_3/redis.py b/ix-dev/community/piwigo/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/piwigo/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/piwigo/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/piwigo/templates/library/base_v1_1_3/resources.py b/ix-dev/community/piwigo/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/piwigo/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/piwigo/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/piwigo/templates/library/base_v1_1_3/security.py b/ix-dev/community/piwigo/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/piwigo/templates/library/base_v1_1_3/security.py rename to ix-dev/community/piwigo/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/piwigo/templates/library/base_v1_1_3/storage.py b/ix-dev/community/piwigo/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/piwigo/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/piwigo/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/piwigo/templates/library/base_v1_1_3/utils.py b/ix-dev/community/piwigo/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/piwigo/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/piwigo/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/planka/app.yaml b/ix-dev/community/planka/app.yaml index ea51fa2ce6..384be8fa44 100644 --- a/ix-dev/community/planka/app.yaml +++ b/ix-dev/community/planka/app.yaml @@ -10,8 +10,8 @@ keywords: - kanban - project - task -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -35,4 +35,4 @@ sources: - https://github.com/plankanban/planka title: Planka train: community -version: 1.0.10 +version: 1.0.11 diff --git a/ix-dev/community/planka/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/planka/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/planka/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/planka/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/planka/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/planka/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/planka/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/planka/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/planka/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/planka/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/planka/templates/library/base_v1_1_3/environment.py b/ix-dev/community/planka/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/planka/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/planka/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/planka/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/planka/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/planka/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/planka/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/planka/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/planka/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/planka/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/planka/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/planka/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/planka/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/planka/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/planka/templates/library/base_v1_1_3/network.py b/ix-dev/community/planka/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/planka/templates/library/base_v1_1_3/network.py rename to ix-dev/community/planka/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/planka/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/planka/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/planka/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/planka/templates/library/base_v1_1_3/ports.py b/ix-dev/community/planka/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/planka/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/planka/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/planka/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/planka/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/planka/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/planka/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/planka/templates/library/base_v1_1_3/redis.py b/ix-dev/community/planka/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/planka/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/planka/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/planka/templates/library/base_v1_1_3/resources.py b/ix-dev/community/planka/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/planka/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/planka/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/planka/templates/library/base_v1_1_3/security.py b/ix-dev/community/planka/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/planka/templates/library/base_v1_1_3/security.py rename to ix-dev/community/planka/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/planka/templates/library/base_v1_1_3/storage.py b/ix-dev/community/planka/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/planka/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/planka/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/planka/templates/library/base_v1_1_3/utils.py b/ix-dev/community/planka/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/planka/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/planka/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/plex-auto-languages/app.yaml b/ix-dev/community/plex-auto-languages/app.yaml index b4e6b5eb26..7410237226 100644 --- a/ix-dev/community/plex-auto-languages/app.yaml +++ b/ix-dev/community/plex-auto-languages/app.yaml @@ -9,8 +9,8 @@ icon: https://media.sys.truenas.net/apps/plex-auto-languages/icons/icon.svg keywords: - plex - languages -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -28,4 +28,4 @@ sources: - https://hub.docker.com/r/remirigal/plex-auto-languages title: Plex Auto Languages train: community -version: 1.0.15 +version: 1.0.16 diff --git a/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/plex-auto-languages/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/plex-auto-languages/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_3/environment.py b/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/plex-auto-languages/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/plex-auto-languages/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/plex-auto-languages/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/plex-auto-languages/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/plex-auto-languages/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/plex-auto-languages/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_3/network.py b/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/plex-auto-languages/templates/library/base_v1_1_3/network.py rename to ix-dev/community/plex-auto-languages/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_3/ports.py b/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/plex-auto-languages/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/plex-auto-languages/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/plex-auto-languages/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/plex-auto-languages/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_3/redis.py b/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/plex-auto-languages/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/plex-auto-languages/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_3/resources.py b/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/plex-auto-languages/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/plex-auto-languages/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_3/security.py b/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/plex-auto-languages/templates/library/base_v1_1_3/security.py rename to ix-dev/community/plex-auto-languages/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_3/storage.py b/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/plex-auto-languages/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/plex-auto-languages/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_3/utils.py b/ix-dev/community/plex-auto-languages/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/plex-auto-languages/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/plex-auto-languages/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/portainer/app.yaml b/ix-dev/community/portainer/app.yaml index a86cc6b90e..54e33aebc1 100644 --- a/ix-dev/community/portainer/app.yaml +++ b/ix-dev/community/portainer/app.yaml @@ -28,8 +28,8 @@ keywords: - docker - compose - container -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -49,4 +49,4 @@ sources: - https://github.com/portainer/portainer title: Portainer train: community -version: 1.2.13 +version: 1.2.14 diff --git a/ix-dev/community/portainer/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/portainer/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/portainer/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/portainer/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/portainer/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/portainer/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/portainer/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/portainer/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/portainer/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/portainer/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/portainer/templates/library/base_v1_1_3/environment.py b/ix-dev/community/portainer/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/portainer/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/portainer/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/portainer/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/portainer/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/portainer/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/portainer/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/portainer/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/portainer/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/portainer/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/portainer/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/portainer/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/portainer/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/portainer/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/portainer/templates/library/base_v1_1_3/network.py b/ix-dev/community/portainer/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/portainer/templates/library/base_v1_1_3/network.py rename to ix-dev/community/portainer/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/portainer/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/portainer/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/portainer/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/portainer/templates/library/base_v1_1_3/ports.py b/ix-dev/community/portainer/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/portainer/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/portainer/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/portainer/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/portainer/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/portainer/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/portainer/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/portainer/templates/library/base_v1_1_3/redis.py b/ix-dev/community/portainer/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/portainer/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/portainer/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/portainer/templates/library/base_v1_1_3/resources.py b/ix-dev/community/portainer/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/portainer/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/portainer/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/portainer/templates/library/base_v1_1_3/security.py b/ix-dev/community/portainer/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/portainer/templates/library/base_v1_1_3/security.py rename to ix-dev/community/portainer/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/portainer/templates/library/base_v1_1_3/storage.py b/ix-dev/community/portainer/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/portainer/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/portainer/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/portainer/templates/library/base_v1_1_3/utils.py b/ix-dev/community/portainer/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/portainer/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/portainer/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/prowlarr/app.yaml b/ix-dev/community/prowlarr/app.yaml index 98ca504136..f9ed28e38b 100644 --- a/ix-dev/community/prowlarr/app.yaml +++ b/ix-dev/community/prowlarr/app.yaml @@ -9,8 +9,8 @@ host_mounts: [] icon: https://media.sys.truenas.net/apps/prowlarr/icons/icon.png keywords: - indexer -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -29,4 +29,4 @@ sources: - https://prowlarr.com title: Prowlarr train: community -version: 1.2.12 +version: 1.2.13 diff --git a/ix-dev/community/prowlarr/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/prowlarr/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/prowlarr/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/prowlarr/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/prowlarr/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/prowlarr/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/prowlarr/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/prowlarr/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/prowlarr/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/prowlarr/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/prowlarr/templates/library/base_v1_1_3/environment.py b/ix-dev/community/prowlarr/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/prowlarr/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/prowlarr/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/prowlarr/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/prowlarr/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/prowlarr/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/prowlarr/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/prowlarr/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/prowlarr/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/prowlarr/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/prowlarr/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/prowlarr/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/prowlarr/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/prowlarr/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/prowlarr/templates/library/base_v1_1_3/network.py b/ix-dev/community/prowlarr/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/prowlarr/templates/library/base_v1_1_3/network.py rename to ix-dev/community/prowlarr/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/prowlarr/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/prowlarr/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/prowlarr/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/prowlarr/templates/library/base_v1_1_3/ports.py b/ix-dev/community/prowlarr/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/prowlarr/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/prowlarr/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/prowlarr/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/prowlarr/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/prowlarr/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/prowlarr/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/prowlarr/templates/library/base_v1_1_3/redis.py b/ix-dev/community/prowlarr/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/prowlarr/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/prowlarr/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/prowlarr/templates/library/base_v1_1_3/resources.py b/ix-dev/community/prowlarr/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/prowlarr/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/prowlarr/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/prowlarr/templates/library/base_v1_1_3/security.py b/ix-dev/community/prowlarr/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/prowlarr/templates/library/base_v1_1_3/security.py rename to ix-dev/community/prowlarr/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/prowlarr/templates/library/base_v1_1_3/storage.py b/ix-dev/community/prowlarr/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/prowlarr/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/prowlarr/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/prowlarr/templates/library/base_v1_1_3/utils.py b/ix-dev/community/prowlarr/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/prowlarr/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/prowlarr/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/qbittorrent/app.yaml b/ix-dev/community/qbittorrent/app.yaml index fdac7a6860..adc1ccdc69 100644 --- a/ix-dev/community/qbittorrent/app.yaml +++ b/ix-dev/community/qbittorrent/app.yaml @@ -11,8 +11,8 @@ keywords: - media - torrent - download -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -31,4 +31,4 @@ sources: - https://www.qbittorrent.org/ title: qBittorrent train: community -version: 1.0.27 +version: 1.0.28 diff --git a/ix-dev/community/qbittorrent/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/qbittorrent/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/qbittorrent/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/qbittorrent/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/qbittorrent/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/qbittorrent/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/qbittorrent/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/qbittorrent/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/qbittorrent/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/qbittorrent/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/qbittorrent/templates/library/base_v1_1_3/environment.py b/ix-dev/community/qbittorrent/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/qbittorrent/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/qbittorrent/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/qbittorrent/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/qbittorrent/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/qbittorrent/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/qbittorrent/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/qbittorrent/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/qbittorrent/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/qbittorrent/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/qbittorrent/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/qbittorrent/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/qbittorrent/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/qbittorrent/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/qbittorrent/templates/library/base_v1_1_3/network.py b/ix-dev/community/qbittorrent/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/qbittorrent/templates/library/base_v1_1_3/network.py rename to ix-dev/community/qbittorrent/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/qbittorrent/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/qbittorrent/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/qbittorrent/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/qbittorrent/templates/library/base_v1_1_3/ports.py b/ix-dev/community/qbittorrent/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/qbittorrent/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/qbittorrent/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/qbittorrent/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/qbittorrent/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/qbittorrent/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/qbittorrent/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/qbittorrent/templates/library/base_v1_1_3/redis.py b/ix-dev/community/qbittorrent/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/qbittorrent/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/qbittorrent/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/qbittorrent/templates/library/base_v1_1_3/resources.py b/ix-dev/community/qbittorrent/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/qbittorrent/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/qbittorrent/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/qbittorrent/templates/library/base_v1_1_3/security.py b/ix-dev/community/qbittorrent/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/qbittorrent/templates/library/base_v1_1_3/security.py rename to ix-dev/community/qbittorrent/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/qbittorrent/templates/library/base_v1_1_3/storage.py b/ix-dev/community/qbittorrent/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/qbittorrent/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/qbittorrent/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/qbittorrent/templates/library/base_v1_1_3/utils.py b/ix-dev/community/qbittorrent/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/qbittorrent/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/qbittorrent/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/radarr/app.yaml b/ix-dev/community/radarr/app.yaml index 20b1d017f2..2b20465546 100644 --- a/ix-dev/community/radarr/app.yaml +++ b/ix-dev/community/radarr/app.yaml @@ -9,8 +9,8 @@ icon: https://media.sys.truenas.net/apps/radarr/icons/icon.png keywords: - media - movies -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -32,4 +32,4 @@ sources: - https://github.com/Radarr/Radarr title: Radarr train: community -version: 1.1.11 +version: 1.1.12 diff --git a/ix-dev/community/radarr/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/radarr/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/radarr/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/radarr/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/radarr/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/radarr/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/radarr/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/radarr/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/radarr/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/radarr/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/radarr/templates/library/base_v1_1_3/environment.py b/ix-dev/community/radarr/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/radarr/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/radarr/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/radarr/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/radarr/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/radarr/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/radarr/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/radarr/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/radarr/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/radarr/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/radarr/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/radarr/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/radarr/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/radarr/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/radarr/templates/library/base_v1_1_3/network.py b/ix-dev/community/radarr/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/radarr/templates/library/base_v1_1_3/network.py rename to ix-dev/community/radarr/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/radarr/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/radarr/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/radarr/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/radarr/templates/library/base_v1_1_3/ports.py b/ix-dev/community/radarr/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/radarr/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/radarr/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/radarr/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/radarr/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/radarr/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/radarr/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/radarr/templates/library/base_v1_1_3/redis.py b/ix-dev/community/radarr/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/radarr/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/radarr/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/radarr/templates/library/base_v1_1_3/resources.py b/ix-dev/community/radarr/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/radarr/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/radarr/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/radarr/templates/library/base_v1_1_3/security.py b/ix-dev/community/radarr/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/radarr/templates/library/base_v1_1_3/security.py rename to ix-dev/community/radarr/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/radarr/templates/library/base_v1_1_3/storage.py b/ix-dev/community/radarr/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/radarr/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/radarr/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/radarr/templates/library/base_v1_1_3/utils.py b/ix-dev/community/radarr/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/radarr/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/radarr/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/readarr/app.yaml b/ix-dev/community/readarr/app.yaml index b0032c353a..dda961b817 100644 --- a/ix-dev/community/readarr/app.yaml +++ b/ix-dev/community/readarr/app.yaml @@ -11,8 +11,8 @@ keywords: - media - ebook - audiobook -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -33,4 +33,4 @@ sources: - https://github.com/Readarr/Readarr title: Readarr train: community -version: 1.0.18 +version: 1.0.19 diff --git a/ix-dev/community/readarr/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/readarr/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/readarr/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/readarr/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/readarr/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/readarr/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/readarr/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/readarr/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/readarr/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/readarr/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/readarr/templates/library/base_v1_1_3/environment.py b/ix-dev/community/readarr/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/readarr/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/readarr/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/readarr/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/readarr/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/readarr/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/readarr/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/readarr/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/readarr/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/readarr/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/readarr/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/readarr/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/readarr/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/readarr/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/readarr/templates/library/base_v1_1_3/network.py b/ix-dev/community/readarr/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/readarr/templates/library/base_v1_1_3/network.py rename to ix-dev/community/readarr/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/readarr/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/readarr/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/readarr/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/readarr/templates/library/base_v1_1_3/ports.py b/ix-dev/community/readarr/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/readarr/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/readarr/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/readarr/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/readarr/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/readarr/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/readarr/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/readarr/templates/library/base_v1_1_3/redis.py b/ix-dev/community/readarr/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/readarr/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/readarr/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/readarr/templates/library/base_v1_1_3/resources.py b/ix-dev/community/readarr/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/readarr/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/readarr/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/readarr/templates/library/base_v1_1_3/security.py b/ix-dev/community/readarr/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/readarr/templates/library/base_v1_1_3/security.py rename to ix-dev/community/readarr/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/readarr/templates/library/base_v1_1_3/storage.py b/ix-dev/community/readarr/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/readarr/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/readarr/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/readarr/templates/library/base_v1_1_3/utils.py b/ix-dev/community/readarr/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/readarr/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/readarr/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/recyclarr/app.yaml b/ix-dev/community/recyclarr/app.yaml index eb9122d4ed..c69360f58e 100644 --- a/ix-dev/community/recyclarr/app.yaml +++ b/ix-dev/community/recyclarr/app.yaml @@ -11,8 +11,8 @@ keywords: - sync - sonarr - radarr -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -30,4 +30,4 @@ sources: - https://github.com/recyclarr/recyclarr/tree/recyclarr title: Recyclarr train: community -version: 1.0.7 +version: 1.0.8 diff --git a/ix-dev/community/recyclarr/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/recyclarr/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/recyclarr/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/recyclarr/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/recyclarr/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/recyclarr/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/recyclarr/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/recyclarr/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/recyclarr/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/recyclarr/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/recyclarr/templates/library/base_v1_1_3/environment.py b/ix-dev/community/recyclarr/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/recyclarr/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/recyclarr/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/recyclarr/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/recyclarr/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/recyclarr/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/recyclarr/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/recyclarr/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/recyclarr/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/recyclarr/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/recyclarr/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/recyclarr/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/recyclarr/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/recyclarr/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/recyclarr/templates/library/base_v1_1_3/network.py b/ix-dev/community/recyclarr/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/recyclarr/templates/library/base_v1_1_3/network.py rename to ix-dev/community/recyclarr/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/recyclarr/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/recyclarr/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/recyclarr/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/recyclarr/templates/library/base_v1_1_3/ports.py b/ix-dev/community/recyclarr/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/recyclarr/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/recyclarr/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/recyclarr/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/recyclarr/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/recyclarr/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/recyclarr/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/recyclarr/templates/library/base_v1_1_3/redis.py b/ix-dev/community/recyclarr/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/recyclarr/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/recyclarr/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/recyclarr/templates/library/base_v1_1_3/resources.py b/ix-dev/community/recyclarr/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/recyclarr/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/recyclarr/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/recyclarr/templates/library/base_v1_1_3/security.py b/ix-dev/community/recyclarr/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/recyclarr/templates/library/base_v1_1_3/security.py rename to ix-dev/community/recyclarr/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/recyclarr/templates/library/base_v1_1_3/storage.py b/ix-dev/community/recyclarr/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/recyclarr/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/recyclarr/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/recyclarr/templates/library/base_v1_1_3/utils.py b/ix-dev/community/recyclarr/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/recyclarr/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/recyclarr/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/redis/app.yaml b/ix-dev/community/redis/app.yaml index b805989fbc..43e445b7ca 100644 --- a/ix-dev/community/redis/app.yaml +++ b/ix-dev/community/redis/app.yaml @@ -9,8 +9,8 @@ host_mounts: [] icon: https://media.sys.truenas.net/apps/redis/icons/icon.png keywords: - cache -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -29,4 +29,4 @@ sources: - https://redis.io/ title: Redis train: community -version: 1.0.6 +version: 1.0.7 diff --git a/ix-dev/community/redis/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/redis/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/redis/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/redis/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/redis/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/redis/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/redis/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/redis/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/redis/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/redis/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/redis/templates/library/base_v1_1_3/environment.py b/ix-dev/community/redis/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/redis/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/redis/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/redis/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/redis/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/redis/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/redis/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/redis/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/redis/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/redis/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/redis/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/redis/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/redis/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/redis/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/redis/templates/library/base_v1_1_3/network.py b/ix-dev/community/redis/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/redis/templates/library/base_v1_1_3/network.py rename to ix-dev/community/redis/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/redis/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/redis/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/redis/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/redis/templates/library/base_v1_1_3/ports.py b/ix-dev/community/redis/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/redis/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/redis/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/redis/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/redis/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/redis/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/redis/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/redis/templates/library/base_v1_1_3/redis.py b/ix-dev/community/redis/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/redis/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/redis/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/redis/templates/library/base_v1_1_3/resources.py b/ix-dev/community/redis/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/redis/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/redis/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/redis/templates/library/base_v1_1_3/security.py b/ix-dev/community/redis/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/redis/templates/library/base_v1_1_3/security.py rename to ix-dev/community/redis/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/redis/templates/library/base_v1_1_3/storage.py b/ix-dev/community/redis/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/redis/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/redis/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/redis/templates/library/base_v1_1_3/utils.py b/ix-dev/community/redis/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/redis/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/redis/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/roundcube/app.yaml b/ix-dev/community/roundcube/app.yaml index a1d562a34a..b93f4047ef 100644 --- a/ix-dev/community/roundcube/app.yaml +++ b/ix-dev/community/roundcube/app.yaml @@ -20,8 +20,8 @@ icon: https://media.sys.truenas.net/apps/roundcube/icons/icon.png keywords: - webmail - email -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -49,4 +49,4 @@ sources: - https://hub.docker.com/r/roundcube/roundcubemail/ title: Roundcube train: community -version: 1.0.6 +version: 1.0.7 diff --git a/ix-dev/community/roundcube/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/roundcube/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/roundcube/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/roundcube/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/roundcube/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/roundcube/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/roundcube/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/roundcube/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/roundcube/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/roundcube/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/roundcube/templates/library/base_v1_1_3/environment.py b/ix-dev/community/roundcube/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/roundcube/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/roundcube/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/roundcube/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/roundcube/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/roundcube/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/roundcube/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/roundcube/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/roundcube/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/roundcube/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/roundcube/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/roundcube/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/roundcube/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/roundcube/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/roundcube/templates/library/base_v1_1_3/network.py b/ix-dev/community/roundcube/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/roundcube/templates/library/base_v1_1_3/network.py rename to ix-dev/community/roundcube/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/roundcube/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/roundcube/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/roundcube/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/roundcube/templates/library/base_v1_1_3/ports.py b/ix-dev/community/roundcube/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/roundcube/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/roundcube/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/roundcube/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/roundcube/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/roundcube/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/roundcube/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/roundcube/templates/library/base_v1_1_3/redis.py b/ix-dev/community/roundcube/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/roundcube/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/roundcube/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/roundcube/templates/library/base_v1_1_3/resources.py b/ix-dev/community/roundcube/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/roundcube/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/roundcube/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/roundcube/templates/library/base_v1_1_3/security.py b/ix-dev/community/roundcube/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/roundcube/templates/library/base_v1_1_3/security.py rename to ix-dev/community/roundcube/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/roundcube/templates/library/base_v1_1_3/storage.py b/ix-dev/community/roundcube/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/roundcube/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/roundcube/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/roundcube/templates/library/base_v1_1_3/utils.py b/ix-dev/community/roundcube/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/roundcube/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/roundcube/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/rsyncd/app.yaml b/ix-dev/community/rsyncd/app.yaml index 2d09066674..2482e35b4e 100644 --- a/ix-dev/community/rsyncd/app.yaml +++ b/ix-dev/community/rsyncd/app.yaml @@ -22,8 +22,8 @@ keywords: - sync - rsync - file transfer -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -41,4 +41,4 @@ sources: - https://hub.docker.com/r/ixsystems/rsyncd title: Rsync Daemon train: community -version: 1.0.13 +version: 1.0.14 diff --git a/ix-dev/community/rsyncd/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/rsyncd/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/rsyncd/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/rsyncd/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/rsyncd/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/rsyncd/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/rsyncd/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/rsyncd/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/rsyncd/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/rsyncd/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/rsyncd/templates/library/base_v1_1_3/environment.py b/ix-dev/community/rsyncd/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/rsyncd/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/rsyncd/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/rsyncd/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/rsyncd/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/rsyncd/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/rsyncd/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/rsyncd/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/rsyncd/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/rsyncd/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/rsyncd/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/rsyncd/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/rsyncd/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/rsyncd/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/rsyncd/templates/library/base_v1_1_3/network.py b/ix-dev/community/rsyncd/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/rsyncd/templates/library/base_v1_1_3/network.py rename to ix-dev/community/rsyncd/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/rsyncd/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/rsyncd/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/rsyncd/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/rsyncd/templates/library/base_v1_1_3/ports.py b/ix-dev/community/rsyncd/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/rsyncd/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/rsyncd/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/rsyncd/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/rsyncd/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/rsyncd/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/rsyncd/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/rsyncd/templates/library/base_v1_1_3/redis.py b/ix-dev/community/rsyncd/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/rsyncd/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/rsyncd/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/rsyncd/templates/library/base_v1_1_3/resources.py b/ix-dev/community/rsyncd/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/rsyncd/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/rsyncd/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/rsyncd/templates/library/base_v1_1_3/security.py b/ix-dev/community/rsyncd/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/rsyncd/templates/library/base_v1_1_3/security.py rename to ix-dev/community/rsyncd/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/rsyncd/templates/library/base_v1_1_3/storage.py b/ix-dev/community/rsyncd/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/rsyncd/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/rsyncd/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/rsyncd/templates/library/base_v1_1_3/utils.py b/ix-dev/community/rsyncd/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/rsyncd/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/rsyncd/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/rust-desk/app.yaml b/ix-dev/community/rust-desk/app.yaml index fe973abdd6..fa4f5be738 100644 --- a/ix-dev/community/rust-desk/app.yaml +++ b/ix-dev/community/rust-desk/app.yaml @@ -9,8 +9,8 @@ icon: https://media.sys.truenas.net/apps/rust-desk/icons/icon.png keywords: - remote - desktop -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -28,4 +28,4 @@ sources: - https://github.com/rustdesk/rustdesk-server title: Rust Desk train: community -version: 1.0.6 +version: 1.0.7 diff --git a/ix-dev/community/rust-desk/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/rust-desk/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/rust-desk/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/rust-desk/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/rust-desk/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/rust-desk/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/rust-desk/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/rust-desk/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/rust-desk/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/rust-desk/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/rust-desk/templates/library/base_v1_1_3/environment.py b/ix-dev/community/rust-desk/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/rust-desk/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/rust-desk/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/rust-desk/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/rust-desk/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/rust-desk/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/rust-desk/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/rust-desk/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/rust-desk/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/rust-desk/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/rust-desk/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/rust-desk/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/rust-desk/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/rust-desk/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/rust-desk/templates/library/base_v1_1_3/network.py b/ix-dev/community/rust-desk/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/rust-desk/templates/library/base_v1_1_3/network.py rename to ix-dev/community/rust-desk/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/rust-desk/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/rust-desk/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/rust-desk/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/rust-desk/templates/library/base_v1_1_3/ports.py b/ix-dev/community/rust-desk/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/rust-desk/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/rust-desk/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/rust-desk/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/rust-desk/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/rust-desk/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/rust-desk/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/rust-desk/templates/library/base_v1_1_3/redis.py b/ix-dev/community/rust-desk/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/rust-desk/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/rust-desk/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/rust-desk/templates/library/base_v1_1_3/resources.py b/ix-dev/community/rust-desk/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/rust-desk/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/rust-desk/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/rust-desk/templates/library/base_v1_1_3/security.py b/ix-dev/community/rust-desk/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/rust-desk/templates/library/base_v1_1_3/security.py rename to ix-dev/community/rust-desk/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/rust-desk/templates/library/base_v1_1_3/storage.py b/ix-dev/community/rust-desk/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/rust-desk/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/rust-desk/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/rust-desk/templates/library/base_v1_1_3/utils.py b/ix-dev/community/rust-desk/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/rust-desk/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/rust-desk/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/sabnzbd/app.yaml b/ix-dev/community/sabnzbd/app.yaml index f4c8a79940..645955f4f9 100644 --- a/ix-dev/community/sabnzbd/app.yaml +++ b/ix-dev/community/sabnzbd/app.yaml @@ -10,8 +10,8 @@ keywords: - media - usenet - newsreader -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -32,4 +32,4 @@ sources: - https://sabnzbd.org/ title: SABnzbd train: community -version: 1.0.6 +version: 1.0.7 diff --git a/ix-dev/community/sabnzbd/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/sabnzbd/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/sabnzbd/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/sabnzbd/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/sabnzbd/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/sabnzbd/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/sabnzbd/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/sabnzbd/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/sabnzbd/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/sabnzbd/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/sabnzbd/templates/library/base_v1_1_3/environment.py b/ix-dev/community/sabnzbd/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/sabnzbd/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/sabnzbd/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/sabnzbd/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/sabnzbd/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/sabnzbd/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/sabnzbd/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/sabnzbd/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/sabnzbd/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/sabnzbd/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/sabnzbd/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/sabnzbd/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/sabnzbd/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/sabnzbd/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/sabnzbd/templates/library/base_v1_1_3/network.py b/ix-dev/community/sabnzbd/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/sabnzbd/templates/library/base_v1_1_3/network.py rename to ix-dev/community/sabnzbd/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/sabnzbd/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/sabnzbd/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/sabnzbd/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/sabnzbd/templates/library/base_v1_1_3/ports.py b/ix-dev/community/sabnzbd/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/sabnzbd/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/sabnzbd/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/sabnzbd/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/sabnzbd/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/sabnzbd/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/sabnzbd/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/sabnzbd/templates/library/base_v1_1_3/redis.py b/ix-dev/community/sabnzbd/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/sabnzbd/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/sabnzbd/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/sabnzbd/templates/library/base_v1_1_3/resources.py b/ix-dev/community/sabnzbd/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/sabnzbd/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/sabnzbd/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/sabnzbd/templates/library/base_v1_1_3/security.py b/ix-dev/community/sabnzbd/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/sabnzbd/templates/library/base_v1_1_3/security.py rename to ix-dev/community/sabnzbd/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/sabnzbd/templates/library/base_v1_1_3/storage.py b/ix-dev/community/sabnzbd/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/sabnzbd/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/sabnzbd/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/sabnzbd/templates/library/base_v1_1_3/utils.py b/ix-dev/community/sabnzbd/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/sabnzbd/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/sabnzbd/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/searxng/app.yaml b/ix-dev/community/searxng/app.yaml index 1c83a3ece4..2e1078f4f5 100644 --- a/ix-dev/community/searxng/app.yaml +++ b/ix-dev/community/searxng/app.yaml @@ -12,8 +12,8 @@ host_mounts: [] icon: https://media.sys.truenas.net/apps/searxng/icons/icon.svg keywords: - search -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -31,4 +31,4 @@ sources: - https://github.com/searxng/searxng title: SearXNG train: community -version: 1.0.15 +version: 1.0.16 diff --git a/ix-dev/community/searxng/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/searxng/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/searxng/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/searxng/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/searxng/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/searxng/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/searxng/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/searxng/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/searxng/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/searxng/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/searxng/templates/library/base_v1_1_3/environment.py b/ix-dev/community/searxng/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/searxng/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/searxng/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/searxng/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/searxng/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/searxng/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/searxng/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/searxng/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/searxng/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/searxng/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/searxng/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/searxng/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/searxng/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/searxng/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/searxng/templates/library/base_v1_1_3/network.py b/ix-dev/community/searxng/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/searxng/templates/library/base_v1_1_3/network.py rename to ix-dev/community/searxng/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/searxng/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/searxng/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/searxng/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/searxng/templates/library/base_v1_1_3/ports.py b/ix-dev/community/searxng/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/searxng/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/searxng/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/searxng/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/searxng/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/searxng/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/searxng/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/searxng/templates/library/base_v1_1_3/redis.py b/ix-dev/community/searxng/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/searxng/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/searxng/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/searxng/templates/library/base_v1_1_3/resources.py b/ix-dev/community/searxng/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/searxng/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/searxng/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/searxng/templates/library/base_v1_1_3/security.py b/ix-dev/community/searxng/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/searxng/templates/library/base_v1_1_3/security.py rename to ix-dev/community/searxng/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/searxng/templates/library/base_v1_1_3/storage.py b/ix-dev/community/searxng/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/searxng/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/searxng/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/searxng/templates/library/base_v1_1_3/utils.py b/ix-dev/community/searxng/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/searxng/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/searxng/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/sftpgo/app.yaml b/ix-dev/community/sftpgo/app.yaml index 8f274b09d7..a6d43ce69e 100644 --- a/ix-dev/community/sftpgo/app.yaml +++ b/ix-dev/community/sftpgo/app.yaml @@ -9,8 +9,8 @@ host_mounts: [] icon: https://media.sys.truenas.net/apps/sftpgo/icons/icon.png keywords: - sftp -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -28,4 +28,4 @@ sources: - https://github.com/drakkan/sftpgo title: SFTPGo train: community -version: 1.0.6 +version: 1.0.7 diff --git a/ix-dev/community/sftpgo/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/sftpgo/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/sftpgo/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/sftpgo/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/sftpgo/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/sftpgo/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/sftpgo/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/sftpgo/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/sftpgo/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/sftpgo/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/sftpgo/templates/library/base_v1_1_3/environment.py b/ix-dev/community/sftpgo/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/sftpgo/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/sftpgo/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/sftpgo/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/sftpgo/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/sftpgo/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/sftpgo/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/sftpgo/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/sftpgo/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/sftpgo/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/sftpgo/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/sftpgo/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/sftpgo/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/sftpgo/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/sftpgo/templates/library/base_v1_1_3/network.py b/ix-dev/community/sftpgo/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/sftpgo/templates/library/base_v1_1_3/network.py rename to ix-dev/community/sftpgo/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/sftpgo/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/sftpgo/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/sftpgo/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/sftpgo/templates/library/base_v1_1_3/ports.py b/ix-dev/community/sftpgo/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/sftpgo/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/sftpgo/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/sftpgo/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/sftpgo/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/sftpgo/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/sftpgo/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/sftpgo/templates/library/base_v1_1_3/redis.py b/ix-dev/community/sftpgo/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/sftpgo/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/sftpgo/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/sftpgo/templates/library/base_v1_1_3/resources.py b/ix-dev/community/sftpgo/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/sftpgo/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/sftpgo/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/sftpgo/templates/library/base_v1_1_3/security.py b/ix-dev/community/sftpgo/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/sftpgo/templates/library/base_v1_1_3/security.py rename to ix-dev/community/sftpgo/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/sftpgo/templates/library/base_v1_1_3/storage.py b/ix-dev/community/sftpgo/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/sftpgo/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/sftpgo/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/sftpgo/templates/library/base_v1_1_3/utils.py b/ix-dev/community/sftpgo/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/sftpgo/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/sftpgo/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/sonarr/app.yaml b/ix-dev/community/sonarr/app.yaml index b17d0ff8ed..3af2babe7b 100644 --- a/ix-dev/community/sonarr/app.yaml +++ b/ix-dev/community/sonarr/app.yaml @@ -9,8 +9,8 @@ icon: https://media.sys.truenas.net/apps/sonarr/icons/icon.png keywords: - media - series -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -31,4 +31,4 @@ sources: - https://github.com/Sonarr/Sonarr title: Sonarr train: community -version: 1.0.18 +version: 1.0.19 diff --git a/ix-dev/community/sonarr/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/sonarr/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/sonarr/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/sonarr/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/sonarr/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/sonarr/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/sonarr/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/sonarr/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/sonarr/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/sonarr/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/sonarr/templates/library/base_v1_1_3/environment.py b/ix-dev/community/sonarr/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/sonarr/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/sonarr/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/sonarr/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/sonarr/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/sonarr/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/sonarr/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/sonarr/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/sonarr/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/sonarr/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/sonarr/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/sonarr/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/sonarr/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/sonarr/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/sonarr/templates/library/base_v1_1_3/network.py b/ix-dev/community/sonarr/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/sonarr/templates/library/base_v1_1_3/network.py rename to ix-dev/community/sonarr/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/sonarr/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/sonarr/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/sonarr/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/sonarr/templates/library/base_v1_1_3/ports.py b/ix-dev/community/sonarr/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/sonarr/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/sonarr/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/sonarr/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/sonarr/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/sonarr/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/sonarr/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/sonarr/templates/library/base_v1_1_3/redis.py b/ix-dev/community/sonarr/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/sonarr/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/sonarr/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/sonarr/templates/library/base_v1_1_3/resources.py b/ix-dev/community/sonarr/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/sonarr/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/sonarr/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/sonarr/templates/library/base_v1_1_3/security.py b/ix-dev/community/sonarr/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/sonarr/templates/library/base_v1_1_3/security.py rename to ix-dev/community/sonarr/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/sonarr/templates/library/base_v1_1_3/storage.py b/ix-dev/community/sonarr/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/sonarr/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/sonarr/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/sonarr/templates/library/base_v1_1_3/utils.py b/ix-dev/community/sonarr/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/sonarr/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/sonarr/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/tailscale/app.yaml b/ix-dev/community/tailscale/app.yaml index e208c56025..eb27eee6bc 100644 --- a/ix-dev/community/tailscale/app.yaml +++ b/ix-dev/community/tailscale/app.yaml @@ -23,8 +23,8 @@ icon: https://media.sys.truenas.net/apps/tailscale/icons/icon.png keywords: - vpn - tailscale -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -42,4 +42,4 @@ sources: - https://hub.docker.com/r/tailscale/tailscale title: Tailscale train: community -version: 1.1.14 +version: 1.1.15 diff --git a/ix-dev/community/tailscale/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/tailscale/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/tailscale/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/tailscale/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/tailscale/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/tailscale/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/tailscale/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/tailscale/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/tailscale/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/tailscale/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/tailscale/templates/library/base_v1_1_3/environment.py b/ix-dev/community/tailscale/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/tailscale/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/tailscale/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/tailscale/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/tailscale/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/tailscale/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/tailscale/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/tailscale/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/tailscale/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/tailscale/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/tailscale/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/tailscale/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/tailscale/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/tailscale/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/tailscale/templates/library/base_v1_1_3/network.py b/ix-dev/community/tailscale/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/tailscale/templates/library/base_v1_1_3/network.py rename to ix-dev/community/tailscale/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/tailscale/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/tailscale/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/tailscale/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/tailscale/templates/library/base_v1_1_3/ports.py b/ix-dev/community/tailscale/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/tailscale/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/tailscale/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/tailscale/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/tailscale/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/tailscale/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/tailscale/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/tailscale/templates/library/base_v1_1_3/redis.py b/ix-dev/community/tailscale/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/tailscale/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/tailscale/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/tailscale/templates/library/base_v1_1_3/resources.py b/ix-dev/community/tailscale/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/tailscale/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/tailscale/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/tailscale/templates/library/base_v1_1_3/security.py b/ix-dev/community/tailscale/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/tailscale/templates/library/base_v1_1_3/security.py rename to ix-dev/community/tailscale/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/tailscale/templates/library/base_v1_1_3/storage.py b/ix-dev/community/tailscale/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/tailscale/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/tailscale/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/tailscale/templates/library/base_v1_1_3/utils.py b/ix-dev/community/tailscale/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/tailscale/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/tailscale/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/tailscale/templates/library/community/tailscale/v1_1_14/util.py b/ix-dev/community/tailscale/templates/library/community/tailscale/v1_1_15/util.py similarity index 93% rename from ix-dev/community/tailscale/templates/library/community/tailscale/v1_1_14/util.py rename to ix-dev/community/tailscale/templates/library/community/tailscale/v1_1_15/util.py index 505f3e72fc..c0ce1e2517 100644 --- a/ix-dev/community/tailscale/templates/library/community/tailscale/v1_1_14/util.py +++ b/ix-dev/community/tailscale/templates/library/community/tailscale/v1_1_15/util.py @@ -1,4 +1,4 @@ -from base_v1_1_3 import utils +from base_v1_1_4 import utils def get_args(data): diff --git a/ix-dev/community/tautulli/app.yaml b/ix-dev/community/tautulli/app.yaml index 6129e268d9..a82e67cd97 100644 --- a/ix-dev/community/tautulli/app.yaml +++ b/ix-dev/community/tautulli/app.yaml @@ -11,8 +11,8 @@ keywords: - media - analytics - notifications -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -34,4 +34,4 @@ sources: - https://github.com/Tautulli/Tautulli title: Tautulli train: community -version: 1.0.20 +version: 1.0.21 diff --git a/ix-dev/community/tautulli/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/tautulli/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/tautulli/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/tautulli/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/tautulli/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/tautulli/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/tautulli/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/tautulli/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/tautulli/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/tautulli/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/tautulli/templates/library/base_v1_1_3/environment.py b/ix-dev/community/tautulli/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/tautulli/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/tautulli/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/tautulli/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/tautulli/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/tautulli/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/tautulli/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/tautulli/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/tautulli/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/tautulli/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/tautulli/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/tautulli/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/tautulli/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/tautulli/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/tautulli/templates/library/base_v1_1_3/network.py b/ix-dev/community/tautulli/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/tautulli/templates/library/base_v1_1_3/network.py rename to ix-dev/community/tautulli/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/tautulli/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/tautulli/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/tautulli/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/tautulli/templates/library/base_v1_1_3/ports.py b/ix-dev/community/tautulli/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/tautulli/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/tautulli/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/tautulli/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/tautulli/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/tautulli/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/tautulli/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/tautulli/templates/library/base_v1_1_3/redis.py b/ix-dev/community/tautulli/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/tautulli/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/tautulli/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/tautulli/templates/library/base_v1_1_3/resources.py b/ix-dev/community/tautulli/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/tautulli/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/tautulli/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/tautulli/templates/library/base_v1_1_3/security.py b/ix-dev/community/tautulli/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/tautulli/templates/library/base_v1_1_3/security.py rename to ix-dev/community/tautulli/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/tautulli/templates/library/base_v1_1_3/storage.py b/ix-dev/community/tautulli/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/tautulli/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/tautulli/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/tautulli/templates/library/base_v1_1_3/utils.py b/ix-dev/community/tautulli/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/tautulli/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/tautulli/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/tdarr/app.yaml b/ix-dev/community/tdarr/app.yaml index ee056c546c..6112678eec 100644 --- a/ix-dev/community/tdarr/app.yaml +++ b/ix-dev/community/tdarr/app.yaml @@ -18,8 +18,8 @@ icon: https://media.sys.truenas.net/apps/tdarr/icons/icon.png keywords: - encode - transcode -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -40,4 +40,4 @@ sources: - https://docs.tdarr.io/docs title: Tdarr train: community -version: 1.0.8 +version: 1.0.9 diff --git a/ix-dev/community/tdarr/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/tdarr/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/tdarr/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/tdarr/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/tdarr/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/tdarr/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/tdarr/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/tdarr/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/tdarr/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/tdarr/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/tdarr/templates/library/base_v1_1_3/environment.py b/ix-dev/community/tdarr/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/tdarr/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/tdarr/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/tdarr/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/tdarr/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/tdarr/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/tdarr/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/tdarr/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/tdarr/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/tdarr/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/tdarr/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/tdarr/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/tdarr/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/tdarr/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/tdarr/templates/library/base_v1_1_3/network.py b/ix-dev/community/tdarr/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/tdarr/templates/library/base_v1_1_3/network.py rename to ix-dev/community/tdarr/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/tdarr/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/tdarr/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/tdarr/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/tdarr/templates/library/base_v1_1_3/ports.py b/ix-dev/community/tdarr/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/tdarr/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/tdarr/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/tdarr/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/tdarr/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/tdarr/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/tdarr/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/tdarr/templates/library/base_v1_1_3/redis.py b/ix-dev/community/tdarr/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/tdarr/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/tdarr/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/tdarr/templates/library/base_v1_1_3/resources.py b/ix-dev/community/tdarr/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/tdarr/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/tdarr/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/tdarr/templates/library/base_v1_1_3/security.py b/ix-dev/community/tdarr/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/tdarr/templates/library/base_v1_1_3/security.py rename to ix-dev/community/tdarr/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/tdarr/templates/library/base_v1_1_3/storage.py b/ix-dev/community/tdarr/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/tdarr/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/tdarr/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/tdarr/templates/library/base_v1_1_3/utils.py b/ix-dev/community/tdarr/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/tdarr/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/tdarr/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/terraria/app.yaml b/ix-dev/community/terraria/app.yaml index 95bbaea7f2..96ba4c00ad 100644 --- a/ix-dev/community/terraria/app.yaml +++ b/ix-dev/community/terraria/app.yaml @@ -13,8 +13,8 @@ keywords: - game - terraria - world -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -32,4 +32,4 @@ sources: - https://github.com/ryansheehan/terraria title: Terraria train: community -version: 1.0.5 +version: 1.0.6 diff --git a/ix-dev/community/terraria/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/terraria/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/terraria/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/terraria/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/terraria/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/terraria/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/terraria/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/terraria/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/terraria/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/terraria/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/terraria/templates/library/base_v1_1_3/environment.py b/ix-dev/community/terraria/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/terraria/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/terraria/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/terraria/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/terraria/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/terraria/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/terraria/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/terraria/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/terraria/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/terraria/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/terraria/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/terraria/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/terraria/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/terraria/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/terraria/templates/library/base_v1_1_3/network.py b/ix-dev/community/terraria/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/terraria/templates/library/base_v1_1_3/network.py rename to ix-dev/community/terraria/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/terraria/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/terraria/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/terraria/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/terraria/templates/library/base_v1_1_3/ports.py b/ix-dev/community/terraria/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/terraria/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/terraria/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/terraria/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/terraria/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/terraria/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/terraria/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/terraria/templates/library/base_v1_1_3/redis.py b/ix-dev/community/terraria/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/terraria/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/terraria/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/terraria/templates/library/base_v1_1_3/resources.py b/ix-dev/community/terraria/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/terraria/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/terraria/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/terraria/templates/library/base_v1_1_3/security.py b/ix-dev/community/terraria/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/terraria/templates/library/base_v1_1_3/security.py rename to ix-dev/community/terraria/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/terraria/templates/library/base_v1_1_3/storage.py b/ix-dev/community/terraria/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/terraria/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/terraria/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/terraria/templates/library/base_v1_1_3/utils.py b/ix-dev/community/terraria/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/terraria/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/terraria/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/tftpd-hpa/app.yaml b/ix-dev/community/tftpd-hpa/app.yaml index 9a91c6d91d..7735985c93 100644 --- a/ix-dev/community/tftpd-hpa/app.yaml +++ b/ix-dev/community/tftpd-hpa/app.yaml @@ -17,8 +17,8 @@ icon: https://media.sys.truenas.net/apps/tftpd-hpa/icons/icon.png keywords: - tftp - netboot -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -36,4 +36,4 @@ sources: - https://hub.docker.com/r/ixsystems/tftpd-hpa title: TFTP Server train: community -version: 1.0.9 +version: 1.0.10 diff --git a/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/tftpd-hpa/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/tftpd-hpa/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_3/environment.py b/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/tftpd-hpa/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/tftpd-hpa/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/tftpd-hpa/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/tftpd-hpa/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/tftpd-hpa/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/tftpd-hpa/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_3/network.py b/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/tftpd-hpa/templates/library/base_v1_1_3/network.py rename to ix-dev/community/tftpd-hpa/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_3/ports.py b/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/tftpd-hpa/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/tftpd-hpa/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/tftpd-hpa/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/tftpd-hpa/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_3/redis.py b/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/tftpd-hpa/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/tftpd-hpa/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_3/resources.py b/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/tftpd-hpa/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/tftpd-hpa/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_3/security.py b/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/tftpd-hpa/templates/library/base_v1_1_3/security.py rename to ix-dev/community/tftpd-hpa/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_3/storage.py b/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/tftpd-hpa/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/tftpd-hpa/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_3/utils.py b/ix-dev/community/tftpd-hpa/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/tftpd-hpa/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/tftpd-hpa/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/tiny-media-manager/app.yaml b/ix-dev/community/tiny-media-manager/app.yaml index f08a32df5c..03e89d2f35 100644 --- a/ix-dev/community/tiny-media-manager/app.yaml +++ b/ix-dev/community/tiny-media-manager/app.yaml @@ -16,8 +16,8 @@ keywords: - media - tv-shows - movies -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -39,4 +39,4 @@ sources: - https://hub.docker.com/r/tinymediamanager/tinymediamanager title: Tiny Media Manager train: community -version: 1.0.5 +version: 1.0.6 diff --git a/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/tiny-media-manager/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/tiny-media-manager/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_3/environment.py b/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/tiny-media-manager/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/tiny-media-manager/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/tiny-media-manager/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/tiny-media-manager/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/tiny-media-manager/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/tiny-media-manager/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_3/network.py b/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/tiny-media-manager/templates/library/base_v1_1_3/network.py rename to ix-dev/community/tiny-media-manager/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_3/ports.py b/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/tiny-media-manager/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/tiny-media-manager/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/tiny-media-manager/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/tiny-media-manager/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_3/redis.py b/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/tiny-media-manager/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/tiny-media-manager/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_3/resources.py b/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/tiny-media-manager/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/tiny-media-manager/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_3/security.py b/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/tiny-media-manager/templates/library/base_v1_1_3/security.py rename to ix-dev/community/tiny-media-manager/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_3/storage.py b/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/tiny-media-manager/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/tiny-media-manager/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_3/utils.py b/ix-dev/community/tiny-media-manager/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/tiny-media-manager/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/tiny-media-manager/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/transmission/app.yaml b/ix-dev/community/transmission/app.yaml index 5cc2c11e75..e83bb36bbd 100644 --- a/ix-dev/community/transmission/app.yaml +++ b/ix-dev/community/transmission/app.yaml @@ -10,8 +10,8 @@ keywords: - media - torrent - download -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -29,4 +29,4 @@ sources: - https://transmissionbt.com/ title: Transmission train: community -version: 1.0.5 +version: 1.0.6 diff --git a/ix-dev/community/transmission/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/transmission/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/transmission/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/transmission/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/transmission/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/transmission/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/transmission/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/transmission/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/transmission/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/transmission/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/transmission/templates/library/base_v1_1_3/environment.py b/ix-dev/community/transmission/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/transmission/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/transmission/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/transmission/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/transmission/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/transmission/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/transmission/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/transmission/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/transmission/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/transmission/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/transmission/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/transmission/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/transmission/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/transmission/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/transmission/templates/library/base_v1_1_3/network.py b/ix-dev/community/transmission/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/transmission/templates/library/base_v1_1_3/network.py rename to ix-dev/community/transmission/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/transmission/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/transmission/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/transmission/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/transmission/templates/library/base_v1_1_3/ports.py b/ix-dev/community/transmission/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/transmission/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/transmission/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/transmission/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/transmission/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/transmission/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/transmission/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/transmission/templates/library/base_v1_1_3/redis.py b/ix-dev/community/transmission/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/transmission/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/transmission/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/transmission/templates/library/base_v1_1_3/resources.py b/ix-dev/community/transmission/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/transmission/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/transmission/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/transmission/templates/library/base_v1_1_3/security.py b/ix-dev/community/transmission/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/transmission/templates/library/base_v1_1_3/security.py rename to ix-dev/community/transmission/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/transmission/templates/library/base_v1_1_3/storage.py b/ix-dev/community/transmission/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/transmission/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/transmission/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/transmission/templates/library/base_v1_1_3/utils.py b/ix-dev/community/transmission/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/transmission/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/transmission/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/twofactor-auth/app.yaml b/ix-dev/community/twofactor-auth/app.yaml index d193f416d4..17b4c6ca7e 100644 --- a/ix-dev/community/twofactor-auth/app.yaml +++ b/ix-dev/community/twofactor-auth/app.yaml @@ -11,8 +11,8 @@ keywords: - security - 2fa - otp -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -31,4 +31,4 @@ sources: - https://hub.docker.com/r/2fauth/2fauth/ title: 2FAuth train: community -version: 1.0.6 +version: 1.0.7 diff --git a/ix-dev/community/twofactor-auth/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/twofactor-auth/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/twofactor-auth/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/twofactor-auth/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/twofactor-auth/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/twofactor-auth/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/twofactor-auth/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/twofactor-auth/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/twofactor-auth/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/twofactor-auth/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/twofactor-auth/templates/library/base_v1_1_3/environment.py b/ix-dev/community/twofactor-auth/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/twofactor-auth/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/twofactor-auth/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/twofactor-auth/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/twofactor-auth/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/twofactor-auth/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/twofactor-auth/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/twofactor-auth/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/twofactor-auth/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/twofactor-auth/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/twofactor-auth/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/twofactor-auth/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/twofactor-auth/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/twofactor-auth/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/twofactor-auth/templates/library/base_v1_1_3/network.py b/ix-dev/community/twofactor-auth/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/twofactor-auth/templates/library/base_v1_1_3/network.py rename to ix-dev/community/twofactor-auth/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/twofactor-auth/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/twofactor-auth/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/twofactor-auth/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/twofactor-auth/templates/library/base_v1_1_3/ports.py b/ix-dev/community/twofactor-auth/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/twofactor-auth/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/twofactor-auth/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/twofactor-auth/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/twofactor-auth/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/twofactor-auth/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/twofactor-auth/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/twofactor-auth/templates/library/base_v1_1_3/redis.py b/ix-dev/community/twofactor-auth/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/twofactor-auth/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/twofactor-auth/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/twofactor-auth/templates/library/base_v1_1_3/resources.py b/ix-dev/community/twofactor-auth/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/twofactor-auth/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/twofactor-auth/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/twofactor-auth/templates/library/base_v1_1_3/security.py b/ix-dev/community/twofactor-auth/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/twofactor-auth/templates/library/base_v1_1_3/security.py rename to ix-dev/community/twofactor-auth/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/twofactor-auth/templates/library/base_v1_1_3/storage.py b/ix-dev/community/twofactor-auth/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/twofactor-auth/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/twofactor-auth/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/twofactor-auth/templates/library/base_v1_1_3/utils.py b/ix-dev/community/twofactor-auth/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/twofactor-auth/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/twofactor-auth/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/unifi-controller/app.yaml b/ix-dev/community/unifi-controller/app.yaml index 4a513498d7..3667f07b51 100644 --- a/ix-dev/community/unifi-controller/app.yaml +++ b/ix-dev/community/unifi-controller/app.yaml @@ -10,8 +10,8 @@ keywords: - controller - unifi - network -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -30,4 +30,4 @@ sources: - https://hub.docker.com/r/goofball222/unifi title: Unifi Controller train: community -version: 1.2.10 +version: 1.2.11 diff --git a/ix-dev/community/unifi-controller/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/unifi-controller/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/unifi-controller/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/unifi-controller/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/unifi-controller/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/unifi-controller/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/unifi-controller/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/unifi-controller/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/unifi-controller/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/unifi-controller/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/unifi-controller/templates/library/base_v1_1_3/environment.py b/ix-dev/community/unifi-controller/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/unifi-controller/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/unifi-controller/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/unifi-controller/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/unifi-controller/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/unifi-controller/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/unifi-controller/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/unifi-controller/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/unifi-controller/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/unifi-controller/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/unifi-controller/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/unifi-controller/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/unifi-controller/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/unifi-controller/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/unifi-controller/templates/library/base_v1_1_3/network.py b/ix-dev/community/unifi-controller/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/unifi-controller/templates/library/base_v1_1_3/network.py rename to ix-dev/community/unifi-controller/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/unifi-controller/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/unifi-controller/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/unifi-controller/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/unifi-controller/templates/library/base_v1_1_3/ports.py b/ix-dev/community/unifi-controller/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/unifi-controller/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/unifi-controller/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/unifi-controller/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/unifi-controller/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/unifi-controller/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/unifi-controller/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/unifi-controller/templates/library/base_v1_1_3/redis.py b/ix-dev/community/unifi-controller/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/unifi-controller/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/unifi-controller/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/unifi-controller/templates/library/base_v1_1_3/resources.py b/ix-dev/community/unifi-controller/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/unifi-controller/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/unifi-controller/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/unifi-controller/templates/library/base_v1_1_3/security.py b/ix-dev/community/unifi-controller/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/unifi-controller/templates/library/base_v1_1_3/security.py rename to ix-dev/community/unifi-controller/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/unifi-controller/templates/library/base_v1_1_3/storage.py b/ix-dev/community/unifi-controller/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/unifi-controller/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/unifi-controller/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/unifi-controller/templates/library/base_v1_1_3/utils.py b/ix-dev/community/unifi-controller/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/unifi-controller/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/unifi-controller/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/unifi-protect-backup/app.yaml b/ix-dev/community/unifi-protect-backup/app.yaml index efad761ca1..5e95f9953d 100644 --- a/ix-dev/community/unifi-protect-backup/app.yaml +++ b/ix-dev/community/unifi-protect-backup/app.yaml @@ -18,8 +18,8 @@ icon: https://media.sys.truenas.net/apps/unifi-protect-backup/icons/icon.svg keywords: - backup - unifi-protect -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -37,4 +37,4 @@ sources: - https://github.com/ep1cman/unifi-protect-backup/pkgs/container/unifi-protect-backup title: Unifi Protect Backup train: community -version: 1.0.16 +version: 1.0.17 diff --git a/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_3/environment.py b/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_3/network.py b/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_3/network.py rename to ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_3/ports.py b/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_3/redis.py b/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_3/resources.py b/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_3/security.py b/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_3/security.py rename to ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_3/storage.py b/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_3/utils.py b/ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/unifi-protect-backup/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/vaultwarden/app.yaml b/ix-dev/community/vaultwarden/app.yaml index 5b7de00253..a5abd79800 100644 --- a/ix-dev/community/vaultwarden/app.yaml +++ b/ix-dev/community/vaultwarden/app.yaml @@ -10,8 +10,8 @@ icon: https://media.sys.truenas.net/apps/vaultwarden/icons/icon.png keywords: - password - manager -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -34,4 +34,4 @@ sources: - https://github.com/dani-garcia/vaultwarden title: Vaultwarden train: community -version: 1.0.6 +version: 1.0.7 diff --git a/ix-dev/community/vaultwarden/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/vaultwarden/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/vaultwarden/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/vaultwarden/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/vaultwarden/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/vaultwarden/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/vaultwarden/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/vaultwarden/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/vaultwarden/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/vaultwarden/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/vaultwarden/templates/library/base_v1_1_3/environment.py b/ix-dev/community/vaultwarden/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/vaultwarden/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/vaultwarden/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/vaultwarden/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/vaultwarden/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/vaultwarden/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/vaultwarden/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/vaultwarden/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/vaultwarden/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/vaultwarden/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/vaultwarden/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/vaultwarden/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/vaultwarden/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/vaultwarden/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/vaultwarden/templates/library/base_v1_1_3/network.py b/ix-dev/community/vaultwarden/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/vaultwarden/templates/library/base_v1_1_3/network.py rename to ix-dev/community/vaultwarden/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/vaultwarden/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/vaultwarden/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/vaultwarden/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/vaultwarden/templates/library/base_v1_1_3/ports.py b/ix-dev/community/vaultwarden/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/vaultwarden/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/vaultwarden/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/vaultwarden/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/vaultwarden/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/vaultwarden/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/vaultwarden/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/vaultwarden/templates/library/base_v1_1_3/redis.py b/ix-dev/community/vaultwarden/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/vaultwarden/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/vaultwarden/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/vaultwarden/templates/library/base_v1_1_3/resources.py b/ix-dev/community/vaultwarden/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/vaultwarden/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/vaultwarden/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/vaultwarden/templates/library/base_v1_1_3/security.py b/ix-dev/community/vaultwarden/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/vaultwarden/templates/library/base_v1_1_3/security.py rename to ix-dev/community/vaultwarden/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/vaultwarden/templates/library/base_v1_1_3/storage.py b/ix-dev/community/vaultwarden/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/vaultwarden/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/vaultwarden/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/vaultwarden/templates/library/base_v1_1_3/utils.py b/ix-dev/community/vaultwarden/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/vaultwarden/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/vaultwarden/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/vikunja/app.yaml b/ix-dev/community/vikunja/app.yaml index 93f4cb6303..b6f2b7551d 100644 --- a/ix-dev/community/vikunja/app.yaml +++ b/ix-dev/community/vikunja/app.yaml @@ -8,8 +8,8 @@ host_mounts: [] icon: https://media.sys.truenas.net/apps/vikunja/icons/icon.png keywords: - todo -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -46,4 +46,4 @@ sources: - https://vikunja.io/ title: Vikunja train: community -version: 1.2.13 +version: 1.2.14 diff --git a/ix-dev/community/vikunja/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/vikunja/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/vikunja/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/vikunja/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/vikunja/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/vikunja/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/vikunja/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/vikunja/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/vikunja/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/vikunja/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/vikunja/templates/library/base_v1_1_3/environment.py b/ix-dev/community/vikunja/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/vikunja/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/vikunja/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/vikunja/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/vikunja/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/vikunja/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/vikunja/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/vikunja/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/vikunja/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/vikunja/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/vikunja/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/vikunja/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/vikunja/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/vikunja/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/vikunja/templates/library/base_v1_1_3/network.py b/ix-dev/community/vikunja/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/vikunja/templates/library/base_v1_1_3/network.py rename to ix-dev/community/vikunja/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/vikunja/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/vikunja/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/vikunja/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/vikunja/templates/library/base_v1_1_3/ports.py b/ix-dev/community/vikunja/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/vikunja/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/vikunja/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/vikunja/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/vikunja/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/vikunja/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/vikunja/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/vikunja/templates/library/base_v1_1_3/redis.py b/ix-dev/community/vikunja/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/vikunja/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/vikunja/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/vikunja/templates/library/base_v1_1_3/resources.py b/ix-dev/community/vikunja/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/vikunja/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/vikunja/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/vikunja/templates/library/base_v1_1_3/security.py b/ix-dev/community/vikunja/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/vikunja/templates/library/base_v1_1_3/security.py rename to ix-dev/community/vikunja/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/vikunja/templates/library/base_v1_1_3/storage.py b/ix-dev/community/vikunja/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/vikunja/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/vikunja/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/vikunja/templates/library/base_v1_1_3/utils.py b/ix-dev/community/vikunja/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/vikunja/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/vikunja/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/webdav/app.yaml b/ix-dev/community/webdav/app.yaml index e39604df33..7e1ec57bfa 100644 --- a/ix-dev/community/webdav/app.yaml +++ b/ix-dev/community/webdav/app.yaml @@ -10,8 +10,8 @@ icon: https://media.sys.truenas.net/apps/webdav/icons/icon.png keywords: - webdav - file-sharing -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -28,4 +28,4 @@ sources: - http://www.webdav.org/ title: WebDAV train: community -version: 1.0.12 +version: 1.0.13 diff --git a/ix-dev/community/webdav/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/webdav/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/webdav/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/webdav/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/webdav/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/webdav/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/webdav/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/webdav/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/webdav/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/webdav/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/webdav/templates/library/base_v1_1_3/environment.py b/ix-dev/community/webdav/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/webdav/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/webdav/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/webdav/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/webdav/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/webdav/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/webdav/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/webdav/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/webdav/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/webdav/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/webdav/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/webdav/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/webdav/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/webdav/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/webdav/templates/library/base_v1_1_3/network.py b/ix-dev/community/webdav/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/webdav/templates/library/base_v1_1_3/network.py rename to ix-dev/community/webdav/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/webdav/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/webdav/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/webdav/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/webdav/templates/library/base_v1_1_3/ports.py b/ix-dev/community/webdav/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/webdav/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/webdav/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/webdav/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/webdav/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/webdav/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/webdav/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/webdav/templates/library/base_v1_1_3/redis.py b/ix-dev/community/webdav/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/webdav/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/webdav/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/webdav/templates/library/base_v1_1_3/resources.py b/ix-dev/community/webdav/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/webdav/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/webdav/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/webdav/templates/library/base_v1_1_3/security.py b/ix-dev/community/webdav/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/webdav/templates/library/base_v1_1_3/security.py rename to ix-dev/community/webdav/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/webdav/templates/library/base_v1_1_3/storage.py b/ix-dev/community/webdav/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/webdav/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/webdav/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/webdav/templates/library/base_v1_1_3/utils.py b/ix-dev/community/webdav/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/webdav/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/webdav/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/whoogle/app.yaml b/ix-dev/community/whoogle/app.yaml index 3e17812c4f..1610b886db 100644 --- a/ix-dev/community/whoogle/app.yaml +++ b/ix-dev/community/whoogle/app.yaml @@ -9,8 +9,8 @@ icon: https://media.sys.truenas.net/apps/whoogle/icons/icon.png keywords: - search - engine -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -30,4 +30,4 @@ sources: - https://hub.docker.com/r/benbusby/whoogle-search title: Whoogle train: community -version: 1.0.19 +version: 1.0.20 diff --git a/ix-dev/community/whoogle/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/whoogle/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/whoogle/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/whoogle/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/whoogle/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/whoogle/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/whoogle/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/whoogle/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/whoogle/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/whoogle/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/whoogle/templates/library/base_v1_1_3/environment.py b/ix-dev/community/whoogle/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/whoogle/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/whoogle/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/whoogle/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/whoogle/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/whoogle/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/whoogle/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/whoogle/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/whoogle/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/whoogle/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/whoogle/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/whoogle/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/whoogle/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/whoogle/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/whoogle/templates/library/base_v1_1_3/network.py b/ix-dev/community/whoogle/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/whoogle/templates/library/base_v1_1_3/network.py rename to ix-dev/community/whoogle/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/whoogle/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/whoogle/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/whoogle/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/whoogle/templates/library/base_v1_1_3/ports.py b/ix-dev/community/whoogle/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/whoogle/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/whoogle/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/whoogle/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/whoogle/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/whoogle/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/whoogle/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/whoogle/templates/library/base_v1_1_3/redis.py b/ix-dev/community/whoogle/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/whoogle/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/whoogle/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/whoogle/templates/library/base_v1_1_3/resources.py b/ix-dev/community/whoogle/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/whoogle/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/whoogle/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/whoogle/templates/library/base_v1_1_3/security.py b/ix-dev/community/whoogle/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/whoogle/templates/library/base_v1_1_3/security.py rename to ix-dev/community/whoogle/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/whoogle/templates/library/base_v1_1_3/storage.py b/ix-dev/community/whoogle/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/whoogle/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/whoogle/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/whoogle/templates/library/base_v1_1_3/utils.py b/ix-dev/community/whoogle/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/whoogle/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/whoogle/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/wordpress/app.yaml b/ix-dev/community/wordpress/app.yaml index bae03916c3..8a5cb1bebc 100644 --- a/ix-dev/community/wordpress/app.yaml +++ b/ix-dev/community/wordpress/app.yaml @@ -11,8 +11,8 @@ icon: https://media.sys.truenas.net/apps/wordpress/icons/icon.png keywords: - cms - blog -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -38,4 +38,4 @@ sources: - https://hub.docker.com/_/wordpress title: Wordpress train: community -version: 1.0.6 +version: 1.0.7 diff --git a/ix-dev/community/wordpress/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/wordpress/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/wordpress/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/wordpress/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/wordpress/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/wordpress/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/wordpress/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/wordpress/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/wordpress/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/wordpress/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/wordpress/templates/library/base_v1_1_3/environment.py b/ix-dev/community/wordpress/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/wordpress/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/wordpress/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/wordpress/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/wordpress/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/wordpress/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/wordpress/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/wordpress/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/wordpress/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/wordpress/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/wordpress/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/wordpress/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/wordpress/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/wordpress/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/wordpress/templates/library/base_v1_1_3/network.py b/ix-dev/community/wordpress/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/wordpress/templates/library/base_v1_1_3/network.py rename to ix-dev/community/wordpress/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/wordpress/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/wordpress/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/wordpress/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/wordpress/templates/library/base_v1_1_3/ports.py b/ix-dev/community/wordpress/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/wordpress/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/wordpress/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/wordpress/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/wordpress/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/wordpress/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/wordpress/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/wordpress/templates/library/base_v1_1_3/redis.py b/ix-dev/community/wordpress/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/wordpress/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/wordpress/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/wordpress/templates/library/base_v1_1_3/resources.py b/ix-dev/community/wordpress/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/wordpress/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/wordpress/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/wordpress/templates/library/base_v1_1_3/security.py b/ix-dev/community/wordpress/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/wordpress/templates/library/base_v1_1_3/security.py rename to ix-dev/community/wordpress/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/wordpress/templates/library/base_v1_1_3/storage.py b/ix-dev/community/wordpress/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/wordpress/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/wordpress/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/wordpress/templates/library/base_v1_1_3/utils.py b/ix-dev/community/wordpress/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/wordpress/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/wordpress/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/community/zerotier/app.yaml b/ix-dev/community/zerotier/app.yaml index 2f3fa64d7e..f1fc2ec6de 100644 --- a/ix-dev/community/zerotier/app.yaml +++ b/ix-dev/community/zerotier/app.yaml @@ -34,8 +34,8 @@ icon: https://media.sys.truenas.net/apps/zerotier/icons/icon.png keywords: - vpn - zerotier -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -53,4 +53,4 @@ sources: - https://hub.docker.com/r/zerotier/zerotier title: Zerotier train: community -version: 1.0.18 +version: 1.0.19 diff --git a/ix-dev/community/zerotier/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/community/zerotier/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/community/zerotier/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/zerotier/templates/library/base_v1_1_3/permissions.py b/ix-dev/community/zerotier/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/community/zerotier/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/community/zerotier/templates/library/base_v1_1_3/__init__.py b/ix-dev/community/zerotier/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/community/zerotier/templates/library/base_v1_1_3/__init__.py rename to ix-dev/community/zerotier/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/community/zerotier/templates/library/base_v1_1_3/environment.py b/ix-dev/community/zerotier/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/community/zerotier/templates/library/base_v1_1_3/environment.py rename to ix-dev/community/zerotier/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/community/zerotier/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/community/zerotier/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/community/zerotier/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/community/zerotier/templates/library/base_v1_1_3/mariadb.py b/ix-dev/community/zerotier/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/community/zerotier/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/community/zerotier/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/community/zerotier/templates/library/base_v1_1_3/metadata.py b/ix-dev/community/zerotier/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/community/zerotier/templates/library/base_v1_1_3/metadata.py rename to ix-dev/community/zerotier/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/community/zerotier/templates/library/base_v1_1_3/network.py b/ix-dev/community/zerotier/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/community/zerotier/templates/library/base_v1_1_3/network.py rename to ix-dev/community/zerotier/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/community/zerotier/templates/library/base_v1_1_4/permissions.py b/ix-dev/community/zerotier/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/community/zerotier/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/community/zerotier/templates/library/base_v1_1_3/ports.py b/ix-dev/community/zerotier/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/community/zerotier/templates/library/base_v1_1_3/ports.py rename to ix-dev/community/zerotier/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/community/zerotier/templates/library/base_v1_1_3/postgres.py b/ix-dev/community/zerotier/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/community/zerotier/templates/library/base_v1_1_3/postgres.py rename to ix-dev/community/zerotier/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/community/zerotier/templates/library/base_v1_1_3/redis.py b/ix-dev/community/zerotier/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/community/zerotier/templates/library/base_v1_1_3/redis.py rename to ix-dev/community/zerotier/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/community/zerotier/templates/library/base_v1_1_3/resources.py b/ix-dev/community/zerotier/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/community/zerotier/templates/library/base_v1_1_3/resources.py rename to ix-dev/community/zerotier/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/community/zerotier/templates/library/base_v1_1_3/security.py b/ix-dev/community/zerotier/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/community/zerotier/templates/library/base_v1_1_3/security.py rename to ix-dev/community/zerotier/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/community/zerotier/templates/library/base_v1_1_3/storage.py b/ix-dev/community/zerotier/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/community/zerotier/templates/library/base_v1_1_3/storage.py rename to ix-dev/community/zerotier/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/community/zerotier/templates/library/base_v1_1_3/utils.py b/ix-dev/community/zerotier/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/community/zerotier/templates/library/base_v1_1_3/utils.py rename to ix-dev/community/zerotier/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/enterprise/minio/app.yaml b/ix-dev/enterprise/minio/app.yaml index aa8fd32df1..126acc727c 100644 --- a/ix-dev/enterprise/minio/app.yaml +++ b/ix-dev/enterprise/minio/app.yaml @@ -11,8 +11,8 @@ keywords: - minio - cloud - s3 -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -31,4 +31,4 @@ sources: - https://github.com/minio/minio title: MinIO train: enterprise -version: 1.1.6 +version: 1.1.7 diff --git a/ix-dev/enterprise/minio/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/enterprise/minio/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/enterprise/minio/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/enterprise/minio/templates/library/base_v1_1_3/permissions.py b/ix-dev/enterprise/minio/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/enterprise/minio/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/enterprise/minio/templates/library/base_v1_1_3/__init__.py b/ix-dev/enterprise/minio/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/enterprise/minio/templates/library/base_v1_1_3/__init__.py rename to ix-dev/enterprise/minio/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/enterprise/minio/templates/library/base_v1_1_3/environment.py b/ix-dev/enterprise/minio/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/enterprise/minio/templates/library/base_v1_1_3/environment.py rename to ix-dev/enterprise/minio/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/enterprise/minio/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/enterprise/minio/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/enterprise/minio/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/enterprise/minio/templates/library/base_v1_1_3/mariadb.py b/ix-dev/enterprise/minio/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/enterprise/minio/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/enterprise/minio/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/enterprise/minio/templates/library/base_v1_1_3/metadata.py b/ix-dev/enterprise/minio/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/enterprise/minio/templates/library/base_v1_1_3/metadata.py rename to ix-dev/enterprise/minio/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/enterprise/minio/templates/library/base_v1_1_3/network.py b/ix-dev/enterprise/minio/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/enterprise/minio/templates/library/base_v1_1_3/network.py rename to ix-dev/enterprise/minio/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/enterprise/minio/templates/library/base_v1_1_4/permissions.py b/ix-dev/enterprise/minio/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/enterprise/minio/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/enterprise/minio/templates/library/base_v1_1_3/ports.py b/ix-dev/enterprise/minio/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/enterprise/minio/templates/library/base_v1_1_3/ports.py rename to ix-dev/enterprise/minio/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/enterprise/minio/templates/library/base_v1_1_3/postgres.py b/ix-dev/enterprise/minio/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/enterprise/minio/templates/library/base_v1_1_3/postgres.py rename to ix-dev/enterprise/minio/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/enterprise/minio/templates/library/base_v1_1_3/redis.py b/ix-dev/enterprise/minio/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/enterprise/minio/templates/library/base_v1_1_3/redis.py rename to ix-dev/enterprise/minio/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/enterprise/minio/templates/library/base_v1_1_3/resources.py b/ix-dev/enterprise/minio/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/enterprise/minio/templates/library/base_v1_1_3/resources.py rename to ix-dev/enterprise/minio/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/enterprise/minio/templates/library/base_v1_1_3/security.py b/ix-dev/enterprise/minio/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/enterprise/minio/templates/library/base_v1_1_3/security.py rename to ix-dev/enterprise/minio/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/enterprise/minio/templates/library/base_v1_1_3/storage.py b/ix-dev/enterprise/minio/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/enterprise/minio/templates/library/base_v1_1_3/storage.py rename to ix-dev/enterprise/minio/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/enterprise/minio/templates/library/base_v1_1_3/utils.py b/ix-dev/enterprise/minio/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/enterprise/minio/templates/library/base_v1_1_3/utils.py rename to ix-dev/enterprise/minio/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/enterprise/minio/templates/library/enterprise/minio/v1_1_6/__init__.py b/ix-dev/enterprise/minio/templates/library/enterprise/minio/v1_1_7/__init__.py similarity index 100% rename from ix-dev/enterprise/minio/templates/library/enterprise/minio/v1_1_6/__init__.py rename to ix-dev/enterprise/minio/templates/library/enterprise/minio/v1_1_7/__init__.py diff --git a/ix-dev/enterprise/minio/templates/library/enterprise/minio/v1_1_6/data.py b/ix-dev/enterprise/minio/templates/library/enterprise/minio/v1_1_7/data.py similarity index 98% rename from ix-dev/enterprise/minio/templates/library/enterprise/minio/v1_1_6/data.py rename to ix-dev/enterprise/minio/templates/library/enterprise/minio/v1_1_7/data.py index 7553cddf67..a6e7fd07c4 100644 --- a/ix-dev/enterprise/minio/templates/library/enterprise/minio/v1_1_6/data.py +++ b/ix-dev/enterprise/minio/templates/library/enterprise/minio/v1_1_7/data.py @@ -1,4 +1,4 @@ -from base_v1_1_3 import utils +from base_v1_1_4 import utils def validate(data): diff --git a/ix-dev/enterprise/syncthing/app.yaml b/ix-dev/enterprise/syncthing/app.yaml index ef0306a5e0..f97d2c51a5 100644 --- a/ix-dev/enterprise/syncthing/app.yaml +++ b/ix-dev/enterprise/syncthing/app.yaml @@ -25,8 +25,8 @@ icon: https://media.sys.truenas.net/apps/syncthing/icons/icon.svg keywords: - sync - file-sharing -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -49,4 +49,4 @@ sources: - https://hub.docker.com/r/syncthing/syncthing title: Syncthing train: enterprise -version: 1.0.14 +version: 1.0.15 diff --git a/ix-dev/enterprise/syncthing/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/enterprise/syncthing/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/enterprise/syncthing/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/enterprise/syncthing/templates/library/base_v1_1_3/permissions.py b/ix-dev/enterprise/syncthing/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/enterprise/syncthing/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/enterprise/syncthing/templates/library/base_v1_1_3/__init__.py b/ix-dev/enterprise/syncthing/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/enterprise/syncthing/templates/library/base_v1_1_3/__init__.py rename to ix-dev/enterprise/syncthing/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/enterprise/syncthing/templates/library/base_v1_1_3/environment.py b/ix-dev/enterprise/syncthing/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/enterprise/syncthing/templates/library/base_v1_1_3/environment.py rename to ix-dev/enterprise/syncthing/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/enterprise/syncthing/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/enterprise/syncthing/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/enterprise/syncthing/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/enterprise/syncthing/templates/library/base_v1_1_3/mariadb.py b/ix-dev/enterprise/syncthing/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/enterprise/syncthing/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/enterprise/syncthing/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/enterprise/syncthing/templates/library/base_v1_1_3/metadata.py b/ix-dev/enterprise/syncthing/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/enterprise/syncthing/templates/library/base_v1_1_3/metadata.py rename to ix-dev/enterprise/syncthing/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/enterprise/syncthing/templates/library/base_v1_1_3/network.py b/ix-dev/enterprise/syncthing/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/enterprise/syncthing/templates/library/base_v1_1_3/network.py rename to ix-dev/enterprise/syncthing/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/enterprise/syncthing/templates/library/base_v1_1_4/permissions.py b/ix-dev/enterprise/syncthing/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/enterprise/syncthing/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/enterprise/syncthing/templates/library/base_v1_1_3/ports.py b/ix-dev/enterprise/syncthing/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/enterprise/syncthing/templates/library/base_v1_1_3/ports.py rename to ix-dev/enterprise/syncthing/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/enterprise/syncthing/templates/library/base_v1_1_3/postgres.py b/ix-dev/enterprise/syncthing/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/enterprise/syncthing/templates/library/base_v1_1_3/postgres.py rename to ix-dev/enterprise/syncthing/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/enterprise/syncthing/templates/library/base_v1_1_3/redis.py b/ix-dev/enterprise/syncthing/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/enterprise/syncthing/templates/library/base_v1_1_3/redis.py rename to ix-dev/enterprise/syncthing/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/enterprise/syncthing/templates/library/base_v1_1_3/resources.py b/ix-dev/enterprise/syncthing/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/enterprise/syncthing/templates/library/base_v1_1_3/resources.py rename to ix-dev/enterprise/syncthing/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/enterprise/syncthing/templates/library/base_v1_1_3/security.py b/ix-dev/enterprise/syncthing/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/enterprise/syncthing/templates/library/base_v1_1_3/security.py rename to ix-dev/enterprise/syncthing/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/enterprise/syncthing/templates/library/base_v1_1_3/storage.py b/ix-dev/enterprise/syncthing/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/enterprise/syncthing/templates/library/base_v1_1_3/storage.py rename to ix-dev/enterprise/syncthing/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/enterprise/syncthing/templates/library/base_v1_1_3/utils.py b/ix-dev/enterprise/syncthing/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/enterprise/syncthing/templates/library/base_v1_1_3/utils.py rename to ix-dev/enterprise/syncthing/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/stable/collabora/app.yaml b/ix-dev/stable/collabora/app.yaml index 565b9e8372..f9c9a1372b 100644 --- a/ix-dev/stable/collabora/app.yaml +++ b/ix-dev/stable/collabora/app.yaml @@ -27,8 +27,8 @@ keywords: - office - documents - productivity -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -53,4 +53,4 @@ sources: - https://hub.docker.com/r/collabora/code title: Collabora train: stable -version: 1.1.14 +version: 1.1.15 diff --git a/ix-dev/stable/collabora/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/stable/collabora/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/stable/collabora/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/stable/collabora/templates/library/base_v1_1_3/permissions.py b/ix-dev/stable/collabora/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/stable/collabora/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/stable/collabora/templates/library/base_v1_1_3/__init__.py b/ix-dev/stable/collabora/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/stable/collabora/templates/library/base_v1_1_3/__init__.py rename to ix-dev/stable/collabora/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/stable/collabora/templates/library/base_v1_1_3/environment.py b/ix-dev/stable/collabora/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/stable/collabora/templates/library/base_v1_1_3/environment.py rename to ix-dev/stable/collabora/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/stable/collabora/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/stable/collabora/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/stable/collabora/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/stable/collabora/templates/library/base_v1_1_3/mariadb.py b/ix-dev/stable/collabora/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/stable/collabora/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/stable/collabora/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/stable/collabora/templates/library/base_v1_1_3/metadata.py b/ix-dev/stable/collabora/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/stable/collabora/templates/library/base_v1_1_3/metadata.py rename to ix-dev/stable/collabora/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/stable/collabora/templates/library/base_v1_1_3/network.py b/ix-dev/stable/collabora/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/stable/collabora/templates/library/base_v1_1_3/network.py rename to ix-dev/stable/collabora/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/stable/collabora/templates/library/base_v1_1_4/permissions.py b/ix-dev/stable/collabora/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/stable/collabora/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/stable/collabora/templates/library/base_v1_1_3/ports.py b/ix-dev/stable/collabora/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/stable/collabora/templates/library/base_v1_1_3/ports.py rename to ix-dev/stable/collabora/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/stable/collabora/templates/library/base_v1_1_3/postgres.py b/ix-dev/stable/collabora/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/stable/collabora/templates/library/base_v1_1_3/postgres.py rename to ix-dev/stable/collabora/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/stable/collabora/templates/library/base_v1_1_3/redis.py b/ix-dev/stable/collabora/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/stable/collabora/templates/library/base_v1_1_3/redis.py rename to ix-dev/stable/collabora/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/stable/collabora/templates/library/base_v1_1_3/resources.py b/ix-dev/stable/collabora/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/stable/collabora/templates/library/base_v1_1_3/resources.py rename to ix-dev/stable/collabora/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/stable/collabora/templates/library/base_v1_1_3/security.py b/ix-dev/stable/collabora/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/stable/collabora/templates/library/base_v1_1_3/security.py rename to ix-dev/stable/collabora/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/stable/collabora/templates/library/base_v1_1_3/storage.py b/ix-dev/stable/collabora/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/stable/collabora/templates/library/base_v1_1_3/storage.py rename to ix-dev/stable/collabora/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/stable/collabora/templates/library/base_v1_1_3/utils.py b/ix-dev/stable/collabora/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/stable/collabora/templates/library/base_v1_1_3/utils.py rename to ix-dev/stable/collabora/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/stable/diskoverdata/app.yaml b/ix-dev/stable/diskoverdata/app.yaml index 7412302b41..b741b5c4d8 100644 --- a/ix-dev/stable/diskoverdata/app.yaml +++ b/ix-dev/stable/diskoverdata/app.yaml @@ -23,8 +23,8 @@ keywords: - monitoring - management - discovery -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -50,4 +50,4 @@ sources: - https://github.com/linuxserver/docker-diskover title: Diskover Data train: stable -version: 1.3.7 +version: 1.3.8 diff --git a/ix-dev/stable/diskoverdata/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/stable/diskoverdata/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/stable/diskoverdata/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/stable/diskoverdata/templates/library/base_v1_1_3/permissions.py b/ix-dev/stable/diskoverdata/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/stable/diskoverdata/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/stable/diskoverdata/templates/library/base_v1_1_3/__init__.py b/ix-dev/stable/diskoverdata/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/stable/diskoverdata/templates/library/base_v1_1_3/__init__.py rename to ix-dev/stable/diskoverdata/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/stable/diskoverdata/templates/library/base_v1_1_3/environment.py b/ix-dev/stable/diskoverdata/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/stable/diskoverdata/templates/library/base_v1_1_3/environment.py rename to ix-dev/stable/diskoverdata/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/stable/diskoverdata/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/stable/diskoverdata/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/stable/diskoverdata/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/stable/diskoverdata/templates/library/base_v1_1_3/mariadb.py b/ix-dev/stable/diskoverdata/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/stable/diskoverdata/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/stable/diskoverdata/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/stable/diskoverdata/templates/library/base_v1_1_3/metadata.py b/ix-dev/stable/diskoverdata/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/stable/diskoverdata/templates/library/base_v1_1_3/metadata.py rename to ix-dev/stable/diskoverdata/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/stable/diskoverdata/templates/library/base_v1_1_3/network.py b/ix-dev/stable/diskoverdata/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/stable/diskoverdata/templates/library/base_v1_1_3/network.py rename to ix-dev/stable/diskoverdata/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/stable/diskoverdata/templates/library/base_v1_1_4/permissions.py b/ix-dev/stable/diskoverdata/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/stable/diskoverdata/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/stable/diskoverdata/templates/library/base_v1_1_3/ports.py b/ix-dev/stable/diskoverdata/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/stable/diskoverdata/templates/library/base_v1_1_3/ports.py rename to ix-dev/stable/diskoverdata/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/stable/diskoverdata/templates/library/base_v1_1_3/postgres.py b/ix-dev/stable/diskoverdata/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/stable/diskoverdata/templates/library/base_v1_1_3/postgres.py rename to ix-dev/stable/diskoverdata/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/stable/diskoverdata/templates/library/base_v1_1_3/redis.py b/ix-dev/stable/diskoverdata/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/stable/diskoverdata/templates/library/base_v1_1_3/redis.py rename to ix-dev/stable/diskoverdata/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/stable/diskoverdata/templates/library/base_v1_1_3/resources.py b/ix-dev/stable/diskoverdata/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/stable/diskoverdata/templates/library/base_v1_1_3/resources.py rename to ix-dev/stable/diskoverdata/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/stable/diskoverdata/templates/library/base_v1_1_3/security.py b/ix-dev/stable/diskoverdata/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/stable/diskoverdata/templates/library/base_v1_1_3/security.py rename to ix-dev/stable/diskoverdata/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/stable/diskoverdata/templates/library/base_v1_1_3/storage.py b/ix-dev/stable/diskoverdata/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/stable/diskoverdata/templates/library/base_v1_1_3/storage.py rename to ix-dev/stable/diskoverdata/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/stable/diskoverdata/templates/library/base_v1_1_3/utils.py b/ix-dev/stable/diskoverdata/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/stable/diskoverdata/templates/library/base_v1_1_3/utils.py rename to ix-dev/stable/diskoverdata/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/stable/elastic-search/app.yaml b/ix-dev/stable/elastic-search/app.yaml index 0bfa026acc..e6c01ff439 100644 --- a/ix-dev/stable/elastic-search/app.yaml +++ b/ix-dev/stable/elastic-search/app.yaml @@ -10,8 +10,8 @@ icon: https://media.sys.truenas.net/apps/elastic-search/icons/icon.svg keywords: - search - elastic -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -30,4 +30,4 @@ sources: - https://www.elastic.co/guide/en/elasticsearch/reference/master/docker.html#docker-configuration-methods title: Elastic Search train: stable -version: 1.1.11 +version: 1.1.12 diff --git a/ix-dev/stable/elastic-search/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/stable/elastic-search/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/stable/elastic-search/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/stable/elastic-search/templates/library/base_v1_1_3/permissions.py b/ix-dev/stable/elastic-search/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/stable/elastic-search/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/stable/elastic-search/templates/library/base_v1_1_3/__init__.py b/ix-dev/stable/elastic-search/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/stable/elastic-search/templates/library/base_v1_1_3/__init__.py rename to ix-dev/stable/elastic-search/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/stable/elastic-search/templates/library/base_v1_1_3/environment.py b/ix-dev/stable/elastic-search/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/stable/elastic-search/templates/library/base_v1_1_3/environment.py rename to ix-dev/stable/elastic-search/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/stable/elastic-search/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/stable/elastic-search/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/stable/elastic-search/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/stable/elastic-search/templates/library/base_v1_1_3/mariadb.py b/ix-dev/stable/elastic-search/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/stable/elastic-search/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/stable/elastic-search/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/stable/elastic-search/templates/library/base_v1_1_3/metadata.py b/ix-dev/stable/elastic-search/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/stable/elastic-search/templates/library/base_v1_1_3/metadata.py rename to ix-dev/stable/elastic-search/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/stable/elastic-search/templates/library/base_v1_1_3/network.py b/ix-dev/stable/elastic-search/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/stable/elastic-search/templates/library/base_v1_1_3/network.py rename to ix-dev/stable/elastic-search/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/stable/elastic-search/templates/library/base_v1_1_4/permissions.py b/ix-dev/stable/elastic-search/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/stable/elastic-search/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/stable/elastic-search/templates/library/base_v1_1_3/ports.py b/ix-dev/stable/elastic-search/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/stable/elastic-search/templates/library/base_v1_1_3/ports.py rename to ix-dev/stable/elastic-search/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/stable/elastic-search/templates/library/base_v1_1_3/postgres.py b/ix-dev/stable/elastic-search/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/stable/elastic-search/templates/library/base_v1_1_3/postgres.py rename to ix-dev/stable/elastic-search/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/stable/elastic-search/templates/library/base_v1_1_3/redis.py b/ix-dev/stable/elastic-search/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/stable/elastic-search/templates/library/base_v1_1_3/redis.py rename to ix-dev/stable/elastic-search/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/stable/elastic-search/templates/library/base_v1_1_3/resources.py b/ix-dev/stable/elastic-search/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/stable/elastic-search/templates/library/base_v1_1_3/resources.py rename to ix-dev/stable/elastic-search/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/stable/elastic-search/templates/library/base_v1_1_3/security.py b/ix-dev/stable/elastic-search/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/stable/elastic-search/templates/library/base_v1_1_3/security.py rename to ix-dev/stable/elastic-search/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/stable/elastic-search/templates/library/base_v1_1_3/storage.py b/ix-dev/stable/elastic-search/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/stable/elastic-search/templates/library/base_v1_1_3/storage.py rename to ix-dev/stable/elastic-search/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/stable/elastic-search/templates/library/base_v1_1_3/utils.py b/ix-dev/stable/elastic-search/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/stable/elastic-search/templates/library/base_v1_1_3/utils.py rename to ix-dev/stable/elastic-search/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/stable/emby/app.yaml b/ix-dev/stable/emby/app.yaml index 8642af6eb5..17f034ea9f 100644 --- a/ix-dev/stable/emby/app.yaml +++ b/ix-dev/stable/emby/app.yaml @@ -27,8 +27,8 @@ keywords: - series - tv - streaming -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -49,4 +49,4 @@ sources: - https://github.com/truenas/charts/tree/master/charts/emby title: Emby Server train: stable -version: 1.1.12 +version: 1.1.13 diff --git a/ix-dev/stable/emby/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/stable/emby/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/stable/emby/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/stable/emby/templates/library/base_v1_1_3/permissions.py b/ix-dev/stable/emby/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/stable/emby/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/stable/emby/templates/library/base_v1_1_3/__init__.py b/ix-dev/stable/emby/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/stable/emby/templates/library/base_v1_1_3/__init__.py rename to ix-dev/stable/emby/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/stable/emby/templates/library/base_v1_1_3/environment.py b/ix-dev/stable/emby/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/stable/emby/templates/library/base_v1_1_3/environment.py rename to ix-dev/stable/emby/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/stable/emby/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/stable/emby/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/stable/emby/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/stable/emby/templates/library/base_v1_1_3/mariadb.py b/ix-dev/stable/emby/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/stable/emby/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/stable/emby/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/stable/emby/templates/library/base_v1_1_3/metadata.py b/ix-dev/stable/emby/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/stable/emby/templates/library/base_v1_1_3/metadata.py rename to ix-dev/stable/emby/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/stable/emby/templates/library/base_v1_1_3/network.py b/ix-dev/stable/emby/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/stable/emby/templates/library/base_v1_1_3/network.py rename to ix-dev/stable/emby/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/stable/emby/templates/library/base_v1_1_4/permissions.py b/ix-dev/stable/emby/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/stable/emby/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/stable/emby/templates/library/base_v1_1_3/ports.py b/ix-dev/stable/emby/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/stable/emby/templates/library/base_v1_1_3/ports.py rename to ix-dev/stable/emby/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/stable/emby/templates/library/base_v1_1_3/postgres.py b/ix-dev/stable/emby/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/stable/emby/templates/library/base_v1_1_3/postgres.py rename to ix-dev/stable/emby/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/stable/emby/templates/library/base_v1_1_3/redis.py b/ix-dev/stable/emby/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/stable/emby/templates/library/base_v1_1_3/redis.py rename to ix-dev/stable/emby/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/stable/emby/templates/library/base_v1_1_3/resources.py b/ix-dev/stable/emby/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/stable/emby/templates/library/base_v1_1_3/resources.py rename to ix-dev/stable/emby/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/stable/emby/templates/library/base_v1_1_3/security.py b/ix-dev/stable/emby/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/stable/emby/templates/library/base_v1_1_3/security.py rename to ix-dev/stable/emby/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/stable/emby/templates/library/base_v1_1_3/storage.py b/ix-dev/stable/emby/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/stable/emby/templates/library/base_v1_1_3/storage.py rename to ix-dev/stable/emby/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/stable/emby/templates/library/base_v1_1_3/utils.py b/ix-dev/stable/emby/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/stable/emby/templates/library/base_v1_1_3/utils.py rename to ix-dev/stable/emby/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/stable/home-assistant/app.yaml b/ix-dev/stable/home-assistant/app.yaml index be3144525b..3c99c1100b 100644 --- a/ix-dev/stable/home-assistant/app.yaml +++ b/ix-dev/stable/home-assistant/app.yaml @@ -20,8 +20,8 @@ icon: https://media.sys.truenas.net/apps/home-assistant/icons/icon.png keywords: - home-automation - assistant -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -45,4 +45,4 @@ sources: - https://github.com/truenas/charts/tree/master/charts/home-assistant title: Home Assistant train: stable -version: 1.2.20 +version: 1.2.21 diff --git a/ix-dev/stable/home-assistant/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/stable/home-assistant/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/stable/home-assistant/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/stable/home-assistant/templates/library/base_v1_1_3/permissions.py b/ix-dev/stable/home-assistant/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/stable/home-assistant/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/stable/home-assistant/templates/library/base_v1_1_3/__init__.py b/ix-dev/stable/home-assistant/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/stable/home-assistant/templates/library/base_v1_1_3/__init__.py rename to ix-dev/stable/home-assistant/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/stable/home-assistant/templates/library/base_v1_1_3/environment.py b/ix-dev/stable/home-assistant/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/stable/home-assistant/templates/library/base_v1_1_3/environment.py rename to ix-dev/stable/home-assistant/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/stable/home-assistant/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/stable/home-assistant/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/stable/home-assistant/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/stable/home-assistant/templates/library/base_v1_1_3/mariadb.py b/ix-dev/stable/home-assistant/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/stable/home-assistant/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/stable/home-assistant/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/stable/home-assistant/templates/library/base_v1_1_3/metadata.py b/ix-dev/stable/home-assistant/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/stable/home-assistant/templates/library/base_v1_1_3/metadata.py rename to ix-dev/stable/home-assistant/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/stable/home-assistant/templates/library/base_v1_1_3/network.py b/ix-dev/stable/home-assistant/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/stable/home-assistant/templates/library/base_v1_1_3/network.py rename to ix-dev/stable/home-assistant/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/stable/home-assistant/templates/library/base_v1_1_4/permissions.py b/ix-dev/stable/home-assistant/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/stable/home-assistant/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/stable/home-assistant/templates/library/base_v1_1_3/ports.py b/ix-dev/stable/home-assistant/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/stable/home-assistant/templates/library/base_v1_1_3/ports.py rename to ix-dev/stable/home-assistant/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/stable/home-assistant/templates/library/base_v1_1_3/postgres.py b/ix-dev/stable/home-assistant/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/stable/home-assistant/templates/library/base_v1_1_3/postgres.py rename to ix-dev/stable/home-assistant/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/stable/home-assistant/templates/library/base_v1_1_3/redis.py b/ix-dev/stable/home-assistant/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/stable/home-assistant/templates/library/base_v1_1_3/redis.py rename to ix-dev/stable/home-assistant/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/stable/home-assistant/templates/library/base_v1_1_3/resources.py b/ix-dev/stable/home-assistant/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/stable/home-assistant/templates/library/base_v1_1_3/resources.py rename to ix-dev/stable/home-assistant/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/stable/home-assistant/templates/library/base_v1_1_3/security.py b/ix-dev/stable/home-assistant/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/stable/home-assistant/templates/library/base_v1_1_3/security.py rename to ix-dev/stable/home-assistant/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/stable/home-assistant/templates/library/base_v1_1_3/storage.py b/ix-dev/stable/home-assistant/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/stable/home-assistant/templates/library/base_v1_1_3/storage.py rename to ix-dev/stable/home-assistant/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/stable/home-assistant/templates/library/base_v1_1_3/utils.py b/ix-dev/stable/home-assistant/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/stable/home-assistant/templates/library/base_v1_1_3/utils.py rename to ix-dev/stable/home-assistant/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/stable/ix-app/app.yaml b/ix-dev/stable/ix-app/app.yaml index 605eb7e29f..3cd8d5ea9f 100644 --- a/ix-dev/stable/ix-app/app.yaml +++ b/ix-dev/stable/ix-app/app.yaml @@ -7,8 +7,8 @@ home: https://www.truenas.com/ host_mounts: [] icon: https://media.sys.truenas.net/apps/ix-chart/icons/icon.webp keywords: [] -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -19,4 +19,4 @@ screenshots: [] sources: [] title: iX App train: stable -version: 1.0.10 +version: 1.0.11 diff --git a/ix-dev/stable/ix-app/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/stable/ix-app/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/stable/ix-app/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/stable/ix-app/templates/library/base_v1_1_3/permissions.py b/ix-dev/stable/ix-app/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/stable/ix-app/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/stable/ix-app/templates/library/base_v1_1_3/__init__.py b/ix-dev/stable/ix-app/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/stable/ix-app/templates/library/base_v1_1_3/__init__.py rename to ix-dev/stable/ix-app/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/stable/ix-app/templates/library/base_v1_1_3/environment.py b/ix-dev/stable/ix-app/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/stable/ix-app/templates/library/base_v1_1_3/environment.py rename to ix-dev/stable/ix-app/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/stable/ix-app/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/stable/ix-app/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/stable/ix-app/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/stable/ix-app/templates/library/base_v1_1_3/mariadb.py b/ix-dev/stable/ix-app/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/stable/ix-app/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/stable/ix-app/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/stable/ix-app/templates/library/base_v1_1_3/metadata.py b/ix-dev/stable/ix-app/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/stable/ix-app/templates/library/base_v1_1_3/metadata.py rename to ix-dev/stable/ix-app/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/stable/ix-app/templates/library/base_v1_1_3/network.py b/ix-dev/stable/ix-app/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/stable/ix-app/templates/library/base_v1_1_3/network.py rename to ix-dev/stable/ix-app/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/stable/ix-app/templates/library/base_v1_1_4/permissions.py b/ix-dev/stable/ix-app/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/stable/ix-app/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/stable/ix-app/templates/library/base_v1_1_3/ports.py b/ix-dev/stable/ix-app/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/stable/ix-app/templates/library/base_v1_1_3/ports.py rename to ix-dev/stable/ix-app/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/stable/ix-app/templates/library/base_v1_1_3/postgres.py b/ix-dev/stable/ix-app/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/stable/ix-app/templates/library/base_v1_1_3/postgres.py rename to ix-dev/stable/ix-app/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/stable/ix-app/templates/library/base_v1_1_3/redis.py b/ix-dev/stable/ix-app/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/stable/ix-app/templates/library/base_v1_1_3/redis.py rename to ix-dev/stable/ix-app/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/stable/ix-app/templates/library/base_v1_1_3/resources.py b/ix-dev/stable/ix-app/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/stable/ix-app/templates/library/base_v1_1_3/resources.py rename to ix-dev/stable/ix-app/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/stable/ix-app/templates/library/base_v1_1_3/security.py b/ix-dev/stable/ix-app/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/stable/ix-app/templates/library/base_v1_1_3/security.py rename to ix-dev/stable/ix-app/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/stable/ix-app/templates/library/base_v1_1_3/storage.py b/ix-dev/stable/ix-app/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/stable/ix-app/templates/library/base_v1_1_3/storage.py rename to ix-dev/stable/ix-app/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/stable/ix-app/templates/library/base_v1_1_3/utils.py b/ix-dev/stable/ix-app/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/stable/ix-app/templates/library/base_v1_1_3/utils.py rename to ix-dev/stable/ix-app/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/stable/minio/app.yaml b/ix-dev/stable/minio/app.yaml index cc352b0dc7..a61b95bffc 100644 --- a/ix-dev/stable/minio/app.yaml +++ b/ix-dev/stable/minio/app.yaml @@ -10,8 +10,8 @@ keywords: - storage - object-storage - S3 -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -31,4 +31,4 @@ sources: - https://github.com/minio/minio title: MinIO train: stable -version: 1.1.12 +version: 1.1.13 diff --git a/ix-dev/stable/minio/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/stable/minio/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/stable/minio/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/stable/minio/templates/library/base_v1_1_3/permissions.py b/ix-dev/stable/minio/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/stable/minio/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/stable/minio/templates/library/base_v1_1_3/__init__.py b/ix-dev/stable/minio/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/stable/minio/templates/library/base_v1_1_3/__init__.py rename to ix-dev/stable/minio/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/stable/minio/templates/library/base_v1_1_3/environment.py b/ix-dev/stable/minio/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/stable/minio/templates/library/base_v1_1_3/environment.py rename to ix-dev/stable/minio/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/stable/minio/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/stable/minio/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/stable/minio/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/stable/minio/templates/library/base_v1_1_3/mariadb.py b/ix-dev/stable/minio/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/stable/minio/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/stable/minio/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/stable/minio/templates/library/base_v1_1_3/metadata.py b/ix-dev/stable/minio/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/stable/minio/templates/library/base_v1_1_3/metadata.py rename to ix-dev/stable/minio/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/stable/minio/templates/library/base_v1_1_3/network.py b/ix-dev/stable/minio/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/stable/minio/templates/library/base_v1_1_3/network.py rename to ix-dev/stable/minio/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/stable/minio/templates/library/base_v1_1_4/permissions.py b/ix-dev/stable/minio/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/stable/minio/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/stable/minio/templates/library/base_v1_1_3/ports.py b/ix-dev/stable/minio/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/stable/minio/templates/library/base_v1_1_3/ports.py rename to ix-dev/stable/minio/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/stable/minio/templates/library/base_v1_1_3/postgres.py b/ix-dev/stable/minio/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/stable/minio/templates/library/base_v1_1_3/postgres.py rename to ix-dev/stable/minio/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/stable/minio/templates/library/base_v1_1_3/redis.py b/ix-dev/stable/minio/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/stable/minio/templates/library/base_v1_1_3/redis.py rename to ix-dev/stable/minio/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/stable/minio/templates/library/base_v1_1_3/resources.py b/ix-dev/stable/minio/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/stable/minio/templates/library/base_v1_1_3/resources.py rename to ix-dev/stable/minio/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/stable/minio/templates/library/base_v1_1_3/security.py b/ix-dev/stable/minio/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/stable/minio/templates/library/base_v1_1_3/security.py rename to ix-dev/stable/minio/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/stable/minio/templates/library/base_v1_1_3/storage.py b/ix-dev/stable/minio/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/stable/minio/templates/library/base_v1_1_3/storage.py rename to ix-dev/stable/minio/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/stable/minio/templates/library/base_v1_1_3/utils.py b/ix-dev/stable/minio/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/stable/minio/templates/library/base_v1_1_3/utils.py rename to ix-dev/stable/minio/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/stable/netdata/app.yaml b/ix-dev/stable/netdata/app.yaml index 872992ab96..e6b8d8b2f4 100644 --- a/ix-dev/stable/netdata/app.yaml +++ b/ix-dev/stable/netdata/app.yaml @@ -34,8 +34,8 @@ keywords: - alerting - metric - monitoring -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -58,4 +58,4 @@ sources: - https://github.com/netdata/netdata title: Netdata train: stable -version: 1.1.13 +version: 1.1.14 diff --git a/ix-dev/stable/netdata/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/stable/netdata/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/stable/netdata/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/stable/netdata/templates/library/base_v1_1_3/permissions.py b/ix-dev/stable/netdata/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/stable/netdata/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/stable/netdata/templates/library/base_v1_1_3/__init__.py b/ix-dev/stable/netdata/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/stable/netdata/templates/library/base_v1_1_3/__init__.py rename to ix-dev/stable/netdata/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/stable/netdata/templates/library/base_v1_1_3/environment.py b/ix-dev/stable/netdata/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/stable/netdata/templates/library/base_v1_1_3/environment.py rename to ix-dev/stable/netdata/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/stable/netdata/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/stable/netdata/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/stable/netdata/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/stable/netdata/templates/library/base_v1_1_3/mariadb.py b/ix-dev/stable/netdata/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/stable/netdata/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/stable/netdata/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/stable/netdata/templates/library/base_v1_1_3/metadata.py b/ix-dev/stable/netdata/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/stable/netdata/templates/library/base_v1_1_3/metadata.py rename to ix-dev/stable/netdata/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/stable/netdata/templates/library/base_v1_1_3/network.py b/ix-dev/stable/netdata/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/stable/netdata/templates/library/base_v1_1_3/network.py rename to ix-dev/stable/netdata/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/stable/netdata/templates/library/base_v1_1_4/permissions.py b/ix-dev/stable/netdata/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/stable/netdata/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/stable/netdata/templates/library/base_v1_1_3/ports.py b/ix-dev/stable/netdata/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/stable/netdata/templates/library/base_v1_1_3/ports.py rename to ix-dev/stable/netdata/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/stable/netdata/templates/library/base_v1_1_3/postgres.py b/ix-dev/stable/netdata/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/stable/netdata/templates/library/base_v1_1_3/postgres.py rename to ix-dev/stable/netdata/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/stable/netdata/templates/library/base_v1_1_3/redis.py b/ix-dev/stable/netdata/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/stable/netdata/templates/library/base_v1_1_3/redis.py rename to ix-dev/stable/netdata/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/stable/netdata/templates/library/base_v1_1_3/resources.py b/ix-dev/stable/netdata/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/stable/netdata/templates/library/base_v1_1_3/resources.py rename to ix-dev/stable/netdata/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/stable/netdata/templates/library/base_v1_1_3/security.py b/ix-dev/stable/netdata/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/stable/netdata/templates/library/base_v1_1_3/security.py rename to ix-dev/stable/netdata/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/stable/netdata/templates/library/base_v1_1_3/storage.py b/ix-dev/stable/netdata/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/stable/netdata/templates/library/base_v1_1_3/storage.py rename to ix-dev/stable/netdata/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/stable/netdata/templates/library/base_v1_1_3/utils.py b/ix-dev/stable/netdata/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/stable/netdata/templates/library/base_v1_1_3/utils.py rename to ix-dev/stable/netdata/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/stable/nextcloud/app.yaml b/ix-dev/stable/nextcloud/app.yaml index 25b0a0cf7e..7be405dcb6 100644 --- a/ix-dev/stable/nextcloud/app.yaml +++ b/ix-dev/stable/nextcloud/app.yaml @@ -2,8 +2,7 @@ app_version: 30.0.0 capabilities: - description: Nextcloud and Nginx are able to chown files. name: CHOWN -- description: Nextcloud and Nginx are able to bypass permission checks - for it's sub-processes. +- description: Nextcloud and Nginx are able to bypass permission checks for it's sub-processes. name: FOWNER - description: Nextcloud and Nginx are able to bypass permission checks. name: DAC_OVERRIDE @@ -29,8 +28,8 @@ keywords: - http - web - php -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -67,4 +66,4 @@ sources: - https://github.com/truenas/charts/tree/master/charts/nextcloud title: Nextcloud train: stable -version: 1.3.19 +version: 1.3.20 diff --git a/ix-dev/stable/nextcloud/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/stable/nextcloud/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/stable/nextcloud/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/stable/nextcloud/templates/library/base_v1_1_3/permissions.py b/ix-dev/stable/nextcloud/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/stable/nextcloud/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/stable/nextcloud/templates/library/base_v1_1_3/__init__.py b/ix-dev/stable/nextcloud/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/stable/nextcloud/templates/library/base_v1_1_3/__init__.py rename to ix-dev/stable/nextcloud/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/stable/nextcloud/templates/library/base_v1_1_3/environment.py b/ix-dev/stable/nextcloud/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/stable/nextcloud/templates/library/base_v1_1_3/environment.py rename to ix-dev/stable/nextcloud/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/stable/nextcloud/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/stable/nextcloud/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/stable/nextcloud/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/stable/nextcloud/templates/library/base_v1_1_3/mariadb.py b/ix-dev/stable/nextcloud/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/stable/nextcloud/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/stable/nextcloud/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/stable/nextcloud/templates/library/base_v1_1_3/metadata.py b/ix-dev/stable/nextcloud/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/stable/nextcloud/templates/library/base_v1_1_3/metadata.py rename to ix-dev/stable/nextcloud/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/stable/nextcloud/templates/library/base_v1_1_3/network.py b/ix-dev/stable/nextcloud/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/stable/nextcloud/templates/library/base_v1_1_3/network.py rename to ix-dev/stable/nextcloud/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/stable/nextcloud/templates/library/base_v1_1_4/permissions.py b/ix-dev/stable/nextcloud/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/stable/nextcloud/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/stable/nextcloud/templates/library/base_v1_1_3/ports.py b/ix-dev/stable/nextcloud/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/stable/nextcloud/templates/library/base_v1_1_3/ports.py rename to ix-dev/stable/nextcloud/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/stable/nextcloud/templates/library/base_v1_1_3/postgres.py b/ix-dev/stable/nextcloud/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/stable/nextcloud/templates/library/base_v1_1_3/postgres.py rename to ix-dev/stable/nextcloud/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/stable/nextcloud/templates/library/base_v1_1_3/redis.py b/ix-dev/stable/nextcloud/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/stable/nextcloud/templates/library/base_v1_1_3/redis.py rename to ix-dev/stable/nextcloud/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/stable/nextcloud/templates/library/base_v1_1_3/resources.py b/ix-dev/stable/nextcloud/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/stable/nextcloud/templates/library/base_v1_1_3/resources.py rename to ix-dev/stable/nextcloud/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/stable/nextcloud/templates/library/base_v1_1_3/security.py b/ix-dev/stable/nextcloud/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/stable/nextcloud/templates/library/base_v1_1_3/security.py rename to ix-dev/stable/nextcloud/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/stable/nextcloud/templates/library/base_v1_1_3/storage.py b/ix-dev/stable/nextcloud/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/stable/nextcloud/templates/library/base_v1_1_3/storage.py rename to ix-dev/stable/nextcloud/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/stable/nextcloud/templates/library/base_v1_1_3/utils.py b/ix-dev/stable/nextcloud/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/stable/nextcloud/templates/library/base_v1_1_3/utils.py rename to ix-dev/stable/nextcloud/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/stable/photoprism/app.yaml b/ix-dev/stable/photoprism/app.yaml index e8ebb294d9..3dd82228b4 100644 --- a/ix-dev/stable/photoprism/app.yaml +++ b/ix-dev/stable/photoprism/app.yaml @@ -22,8 +22,8 @@ keywords: - media - photos - image -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -42,4 +42,4 @@ sources: - https://photoprism.app/ title: Photoprism train: stable -version: 1.1.13 +version: 1.1.14 diff --git a/ix-dev/stable/photoprism/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/stable/photoprism/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/stable/photoprism/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/stable/photoprism/templates/library/base_v1_1_3/permissions.py b/ix-dev/stable/photoprism/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/stable/photoprism/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/stable/photoprism/templates/library/base_v1_1_3/__init__.py b/ix-dev/stable/photoprism/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/stable/photoprism/templates/library/base_v1_1_3/__init__.py rename to ix-dev/stable/photoprism/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/stable/photoprism/templates/library/base_v1_1_3/environment.py b/ix-dev/stable/photoprism/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/stable/photoprism/templates/library/base_v1_1_3/environment.py rename to ix-dev/stable/photoprism/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/stable/photoprism/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/stable/photoprism/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/stable/photoprism/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/stable/photoprism/templates/library/base_v1_1_3/mariadb.py b/ix-dev/stable/photoprism/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/stable/photoprism/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/stable/photoprism/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/stable/photoprism/templates/library/base_v1_1_3/metadata.py b/ix-dev/stable/photoprism/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/stable/photoprism/templates/library/base_v1_1_3/metadata.py rename to ix-dev/stable/photoprism/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/stable/photoprism/templates/library/base_v1_1_3/network.py b/ix-dev/stable/photoprism/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/stable/photoprism/templates/library/base_v1_1_3/network.py rename to ix-dev/stable/photoprism/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/stable/photoprism/templates/library/base_v1_1_4/permissions.py b/ix-dev/stable/photoprism/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/stable/photoprism/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/stable/photoprism/templates/library/base_v1_1_3/ports.py b/ix-dev/stable/photoprism/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/stable/photoprism/templates/library/base_v1_1_3/ports.py rename to ix-dev/stable/photoprism/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/stable/photoprism/templates/library/base_v1_1_3/postgres.py b/ix-dev/stable/photoprism/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/stable/photoprism/templates/library/base_v1_1_3/postgres.py rename to ix-dev/stable/photoprism/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/stable/photoprism/templates/library/base_v1_1_3/redis.py b/ix-dev/stable/photoprism/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/stable/photoprism/templates/library/base_v1_1_3/redis.py rename to ix-dev/stable/photoprism/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/stable/photoprism/templates/library/base_v1_1_3/resources.py b/ix-dev/stable/photoprism/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/stable/photoprism/templates/library/base_v1_1_3/resources.py rename to ix-dev/stable/photoprism/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/stable/photoprism/templates/library/base_v1_1_3/security.py b/ix-dev/stable/photoprism/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/stable/photoprism/templates/library/base_v1_1_3/security.py rename to ix-dev/stable/photoprism/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/stable/photoprism/templates/library/base_v1_1_3/storage.py b/ix-dev/stable/photoprism/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/stable/photoprism/templates/library/base_v1_1_3/storage.py rename to ix-dev/stable/photoprism/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/stable/photoprism/templates/library/base_v1_1_3/utils.py b/ix-dev/stable/photoprism/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/stable/photoprism/templates/library/base_v1_1_3/utils.py rename to ix-dev/stable/photoprism/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/stable/pihole/app.yaml b/ix-dev/stable/pihole/app.yaml index bd569765f7..eab25408ae 100644 --- a/ix-dev/stable/pihole/app.yaml +++ b/ix-dev/stable/pihole/app.yaml @@ -33,8 +33,8 @@ icon: https://media.sys.truenas.net/apps/pihole/icons/icon.png keywords: - networking - dns -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -53,4 +53,4 @@ sources: - https://github.com/truenas/charts/tree/master/charts/pihole title: Pi-hole train: stable -version: 1.1.10 +version: 1.1.11 diff --git a/ix-dev/stable/pihole/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/stable/pihole/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/stable/pihole/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/stable/pihole/templates/library/base_v1_1_3/permissions.py b/ix-dev/stable/pihole/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/stable/pihole/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/stable/pihole/templates/library/base_v1_1_3/__init__.py b/ix-dev/stable/pihole/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/stable/pihole/templates/library/base_v1_1_3/__init__.py rename to ix-dev/stable/pihole/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/stable/pihole/templates/library/base_v1_1_3/environment.py b/ix-dev/stable/pihole/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/stable/pihole/templates/library/base_v1_1_3/environment.py rename to ix-dev/stable/pihole/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/stable/pihole/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/stable/pihole/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/stable/pihole/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/stable/pihole/templates/library/base_v1_1_3/mariadb.py b/ix-dev/stable/pihole/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/stable/pihole/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/stable/pihole/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/stable/pihole/templates/library/base_v1_1_3/metadata.py b/ix-dev/stable/pihole/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/stable/pihole/templates/library/base_v1_1_3/metadata.py rename to ix-dev/stable/pihole/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/stable/pihole/templates/library/base_v1_1_3/network.py b/ix-dev/stable/pihole/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/stable/pihole/templates/library/base_v1_1_3/network.py rename to ix-dev/stable/pihole/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/stable/pihole/templates/library/base_v1_1_4/permissions.py b/ix-dev/stable/pihole/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/stable/pihole/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/stable/pihole/templates/library/base_v1_1_3/ports.py b/ix-dev/stable/pihole/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/stable/pihole/templates/library/base_v1_1_3/ports.py rename to ix-dev/stable/pihole/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/stable/pihole/templates/library/base_v1_1_3/postgres.py b/ix-dev/stable/pihole/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/stable/pihole/templates/library/base_v1_1_3/postgres.py rename to ix-dev/stable/pihole/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/stable/pihole/templates/library/base_v1_1_3/redis.py b/ix-dev/stable/pihole/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/stable/pihole/templates/library/base_v1_1_3/redis.py rename to ix-dev/stable/pihole/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/stable/pihole/templates/library/base_v1_1_3/resources.py b/ix-dev/stable/pihole/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/stable/pihole/templates/library/base_v1_1_3/resources.py rename to ix-dev/stable/pihole/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/stable/pihole/templates/library/base_v1_1_3/security.py b/ix-dev/stable/pihole/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/stable/pihole/templates/library/base_v1_1_3/security.py rename to ix-dev/stable/pihole/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/stable/pihole/templates/library/base_v1_1_3/storage.py b/ix-dev/stable/pihole/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/stable/pihole/templates/library/base_v1_1_3/storage.py rename to ix-dev/stable/pihole/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/stable/pihole/templates/library/base_v1_1_3/utils.py b/ix-dev/stable/pihole/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/stable/pihole/templates/library/base_v1_1_3/utils.py rename to ix-dev/stable/pihole/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/stable/plex/app.yaml b/ix-dev/stable/plex/app.yaml index e783e30d67..7594552958 100644 --- a/ix-dev/stable/plex/app.yaml +++ b/ix-dev/stable/plex/app.yaml @@ -27,8 +27,8 @@ keywords: - series - tv - streaming -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -48,4 +48,4 @@ sources: - https://hub.docker.com/r/plexinc/pms-docker title: Plex train: stable -version: 1.0.22 +version: 1.0.23 diff --git a/ix-dev/stable/plex/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/stable/plex/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/stable/plex/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/stable/plex/templates/library/base_v1_1_3/permissions.py b/ix-dev/stable/plex/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/stable/plex/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/stable/plex/templates/library/base_v1_1_3/__init__.py b/ix-dev/stable/plex/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/stable/plex/templates/library/base_v1_1_3/__init__.py rename to ix-dev/stable/plex/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/stable/plex/templates/library/base_v1_1_3/environment.py b/ix-dev/stable/plex/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/stable/plex/templates/library/base_v1_1_3/environment.py rename to ix-dev/stable/plex/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/stable/plex/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/stable/plex/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/stable/plex/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/stable/plex/templates/library/base_v1_1_3/mariadb.py b/ix-dev/stable/plex/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/stable/plex/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/stable/plex/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/stable/plex/templates/library/base_v1_1_3/metadata.py b/ix-dev/stable/plex/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/stable/plex/templates/library/base_v1_1_3/metadata.py rename to ix-dev/stable/plex/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/stable/plex/templates/library/base_v1_1_3/network.py b/ix-dev/stable/plex/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/stable/plex/templates/library/base_v1_1_3/network.py rename to ix-dev/stable/plex/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/stable/plex/templates/library/base_v1_1_4/permissions.py b/ix-dev/stable/plex/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/stable/plex/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/stable/plex/templates/library/base_v1_1_3/ports.py b/ix-dev/stable/plex/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/stable/plex/templates/library/base_v1_1_3/ports.py rename to ix-dev/stable/plex/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/stable/plex/templates/library/base_v1_1_3/postgres.py b/ix-dev/stable/plex/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/stable/plex/templates/library/base_v1_1_3/postgres.py rename to ix-dev/stable/plex/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/stable/plex/templates/library/base_v1_1_3/redis.py b/ix-dev/stable/plex/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/stable/plex/templates/library/base_v1_1_3/redis.py rename to ix-dev/stable/plex/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/stable/plex/templates/library/base_v1_1_3/resources.py b/ix-dev/stable/plex/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/stable/plex/templates/library/base_v1_1_3/resources.py rename to ix-dev/stable/plex/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/stable/plex/templates/library/base_v1_1_3/security.py b/ix-dev/stable/plex/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/stable/plex/templates/library/base_v1_1_3/security.py rename to ix-dev/stable/plex/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/stable/plex/templates/library/base_v1_1_3/storage.py b/ix-dev/stable/plex/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/stable/plex/templates/library/base_v1_1_3/storage.py rename to ix-dev/stable/plex/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/stable/plex/templates/library/base_v1_1_3/utils.py b/ix-dev/stable/plex/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/stable/plex/templates/library/base_v1_1_3/utils.py rename to ix-dev/stable/plex/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/stable/prometheus/app.yaml b/ix-dev/stable/prometheus/app.yaml index cef05c3b08..f3c57bb0a8 100644 --- a/ix-dev/stable/prometheus/app.yaml +++ b/ix-dev/stable/prometheus/app.yaml @@ -9,8 +9,8 @@ icon: https://media.sys.truenas.net/apps/prometheus/icons/icon.png keywords: - metrics - prometheus -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -30,4 +30,4 @@ sources: - https://prometheus.io title: Prometheus train: stable -version: 1.1.10 +version: 1.1.11 diff --git a/ix-dev/stable/prometheus/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/stable/prometheus/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/stable/prometheus/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/stable/prometheus/templates/library/base_v1_1_3/permissions.py b/ix-dev/stable/prometheus/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/stable/prometheus/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/stable/prometheus/templates/library/base_v1_1_3/__init__.py b/ix-dev/stable/prometheus/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/stable/prometheus/templates/library/base_v1_1_3/__init__.py rename to ix-dev/stable/prometheus/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/stable/prometheus/templates/library/base_v1_1_3/environment.py b/ix-dev/stable/prometheus/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/stable/prometheus/templates/library/base_v1_1_3/environment.py rename to ix-dev/stable/prometheus/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/stable/prometheus/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/stable/prometheus/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/stable/prometheus/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/stable/prometheus/templates/library/base_v1_1_3/mariadb.py b/ix-dev/stable/prometheus/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/stable/prometheus/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/stable/prometheus/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/stable/prometheus/templates/library/base_v1_1_3/metadata.py b/ix-dev/stable/prometheus/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/stable/prometheus/templates/library/base_v1_1_3/metadata.py rename to ix-dev/stable/prometheus/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/stable/prometheus/templates/library/base_v1_1_3/network.py b/ix-dev/stable/prometheus/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/stable/prometheus/templates/library/base_v1_1_3/network.py rename to ix-dev/stable/prometheus/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/stable/prometheus/templates/library/base_v1_1_4/permissions.py b/ix-dev/stable/prometheus/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/stable/prometheus/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/stable/prometheus/templates/library/base_v1_1_3/ports.py b/ix-dev/stable/prometheus/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/stable/prometheus/templates/library/base_v1_1_3/ports.py rename to ix-dev/stable/prometheus/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/stable/prometheus/templates/library/base_v1_1_3/postgres.py b/ix-dev/stable/prometheus/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/stable/prometheus/templates/library/base_v1_1_3/postgres.py rename to ix-dev/stable/prometheus/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/stable/prometheus/templates/library/base_v1_1_3/redis.py b/ix-dev/stable/prometheus/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/stable/prometheus/templates/library/base_v1_1_3/redis.py rename to ix-dev/stable/prometheus/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/stable/prometheus/templates/library/base_v1_1_3/resources.py b/ix-dev/stable/prometheus/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/stable/prometheus/templates/library/base_v1_1_3/resources.py rename to ix-dev/stable/prometheus/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/stable/prometheus/templates/library/base_v1_1_3/security.py b/ix-dev/stable/prometheus/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/stable/prometheus/templates/library/base_v1_1_3/security.py rename to ix-dev/stable/prometheus/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/stable/prometheus/templates/library/base_v1_1_3/storage.py b/ix-dev/stable/prometheus/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/stable/prometheus/templates/library/base_v1_1_3/storage.py rename to ix-dev/stable/prometheus/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/stable/prometheus/templates/library/base_v1_1_3/utils.py b/ix-dev/stable/prometheus/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/stable/prometheus/templates/library/base_v1_1_3/utils.py rename to ix-dev/stable/prometheus/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/stable/storj/app.yaml b/ix-dev/stable/storj/app.yaml index e7763516c1..c1d1587937 100644 --- a/ix-dev/stable/storj/app.yaml +++ b/ix-dev/stable/storj/app.yaml @@ -18,8 +18,8 @@ keywords: - networking - financial - file-sharing -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -37,4 +37,4 @@ sources: - https://www.storj.io title: Storj train: stable -version: 1.1.9 +version: 1.1.10 diff --git a/ix-dev/stable/storj/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/stable/storj/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/stable/storj/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/stable/storj/templates/library/base_v1_1_3/permissions.py b/ix-dev/stable/storj/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/stable/storj/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/stable/storj/templates/library/base_v1_1_3/__init__.py b/ix-dev/stable/storj/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/stable/storj/templates/library/base_v1_1_3/__init__.py rename to ix-dev/stable/storj/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/stable/storj/templates/library/base_v1_1_3/environment.py b/ix-dev/stable/storj/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/stable/storj/templates/library/base_v1_1_3/environment.py rename to ix-dev/stable/storj/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/stable/storj/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/stable/storj/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/stable/storj/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/stable/storj/templates/library/base_v1_1_3/mariadb.py b/ix-dev/stable/storj/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/stable/storj/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/stable/storj/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/stable/storj/templates/library/base_v1_1_3/metadata.py b/ix-dev/stable/storj/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/stable/storj/templates/library/base_v1_1_3/metadata.py rename to ix-dev/stable/storj/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/stable/storj/templates/library/base_v1_1_3/network.py b/ix-dev/stable/storj/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/stable/storj/templates/library/base_v1_1_3/network.py rename to ix-dev/stable/storj/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/stable/storj/templates/library/base_v1_1_4/permissions.py b/ix-dev/stable/storj/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/stable/storj/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/stable/storj/templates/library/base_v1_1_3/ports.py b/ix-dev/stable/storj/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/stable/storj/templates/library/base_v1_1_3/ports.py rename to ix-dev/stable/storj/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/stable/storj/templates/library/base_v1_1_3/postgres.py b/ix-dev/stable/storj/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/stable/storj/templates/library/base_v1_1_3/postgres.py rename to ix-dev/stable/storj/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/stable/storj/templates/library/base_v1_1_3/redis.py b/ix-dev/stable/storj/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/stable/storj/templates/library/base_v1_1_3/redis.py rename to ix-dev/stable/storj/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/stable/storj/templates/library/base_v1_1_3/resources.py b/ix-dev/stable/storj/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/stable/storj/templates/library/base_v1_1_3/resources.py rename to ix-dev/stable/storj/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/stable/storj/templates/library/base_v1_1_3/security.py b/ix-dev/stable/storj/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/stable/storj/templates/library/base_v1_1_3/security.py rename to ix-dev/stable/storj/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/stable/storj/templates/library/base_v1_1_3/storage.py b/ix-dev/stable/storj/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/stable/storj/templates/library/base_v1_1_3/storage.py rename to ix-dev/stable/storj/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/stable/storj/templates/library/base_v1_1_3/utils.py b/ix-dev/stable/storj/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/stable/storj/templates/library/base_v1_1_3/utils.py rename to ix-dev/stable/storj/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/stable/syncthing/app.yaml b/ix-dev/stable/syncthing/app.yaml index 7b7d1e7481..f1609e4af0 100644 --- a/ix-dev/stable/syncthing/app.yaml +++ b/ix-dev/stable/syncthing/app.yaml @@ -26,8 +26,8 @@ keywords: - sync - file-sharing - backup -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -50,4 +50,4 @@ sources: - https://hub.docker.com/r/syncthing/syncthing title: Syncthing train: stable -version: 1.0.26 +version: 1.0.27 diff --git a/ix-dev/stable/syncthing/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/stable/syncthing/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/stable/syncthing/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/stable/syncthing/templates/library/base_v1_1_3/permissions.py b/ix-dev/stable/syncthing/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/stable/syncthing/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/stable/syncthing/templates/library/base_v1_1_3/__init__.py b/ix-dev/stable/syncthing/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/stable/syncthing/templates/library/base_v1_1_3/__init__.py rename to ix-dev/stable/syncthing/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/stable/syncthing/templates/library/base_v1_1_3/environment.py b/ix-dev/stable/syncthing/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/stable/syncthing/templates/library/base_v1_1_3/environment.py rename to ix-dev/stable/syncthing/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/stable/syncthing/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/stable/syncthing/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/stable/syncthing/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/stable/syncthing/templates/library/base_v1_1_3/mariadb.py b/ix-dev/stable/syncthing/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/stable/syncthing/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/stable/syncthing/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/stable/syncthing/templates/library/base_v1_1_3/metadata.py b/ix-dev/stable/syncthing/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/stable/syncthing/templates/library/base_v1_1_3/metadata.py rename to ix-dev/stable/syncthing/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/stable/syncthing/templates/library/base_v1_1_3/network.py b/ix-dev/stable/syncthing/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/stable/syncthing/templates/library/base_v1_1_3/network.py rename to ix-dev/stable/syncthing/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/stable/syncthing/templates/library/base_v1_1_4/permissions.py b/ix-dev/stable/syncthing/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/stable/syncthing/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/stable/syncthing/templates/library/base_v1_1_3/ports.py b/ix-dev/stable/syncthing/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/stable/syncthing/templates/library/base_v1_1_3/ports.py rename to ix-dev/stable/syncthing/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/stable/syncthing/templates/library/base_v1_1_3/postgres.py b/ix-dev/stable/syncthing/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/stable/syncthing/templates/library/base_v1_1_3/postgres.py rename to ix-dev/stable/syncthing/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/stable/syncthing/templates/library/base_v1_1_3/redis.py b/ix-dev/stable/syncthing/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/stable/syncthing/templates/library/base_v1_1_3/redis.py rename to ix-dev/stable/syncthing/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/stable/syncthing/templates/library/base_v1_1_3/resources.py b/ix-dev/stable/syncthing/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/stable/syncthing/templates/library/base_v1_1_3/resources.py rename to ix-dev/stable/syncthing/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/stable/syncthing/templates/library/base_v1_1_3/security.py b/ix-dev/stable/syncthing/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/stable/syncthing/templates/library/base_v1_1_3/security.py rename to ix-dev/stable/syncthing/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/stable/syncthing/templates/library/base_v1_1_3/storage.py b/ix-dev/stable/syncthing/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/stable/syncthing/templates/library/base_v1_1_3/storage.py rename to ix-dev/stable/syncthing/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/stable/syncthing/templates/library/base_v1_1_3/utils.py b/ix-dev/stable/syncthing/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/stable/syncthing/templates/library/base_v1_1_3/utils.py rename to ix-dev/stable/syncthing/templates/library/base_v1_1_4/utils.py diff --git a/ix-dev/stable/wg-easy/app.yaml b/ix-dev/stable/wg-easy/app.yaml index ebd9d96869..2080af7c54 100644 --- a/ix-dev/stable/wg-easy/app.yaml +++ b/ix-dev/stable/wg-easy/app.yaml @@ -16,8 +16,8 @@ keywords: - wireguard - network - vpn -lib_version: 1.1.3 -lib_version_hash: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +lib_version: 1.1.4 +lib_version_hash: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113 maintainers: - email: dev@ixsystems.com name: truenas @@ -35,4 +35,4 @@ sources: - https://github.com/wg-easy/wg-easy title: WG Easy train: stable -version: 1.0.19 +version: 1.0.20 diff --git a/ix-dev/stable/wg-easy/templates/library/base_v1_1_3/healthchecks.py b/ix-dev/stable/wg-easy/templates/library/base_v1_1_3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/ix-dev/stable/wg-easy/templates/library/base_v1_1_3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/stable/wg-easy/templates/library/base_v1_1_3/permissions.py b/ix-dev/stable/wg-easy/templates/library/base_v1_1_3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/ix-dev/stable/wg-easy/templates/library/base_v1_1_3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/ix-dev/stable/wg-easy/templates/library/base_v1_1_3/__init__.py b/ix-dev/stable/wg-easy/templates/library/base_v1_1_4/__init__.py similarity index 100% rename from ix-dev/stable/wg-easy/templates/library/base_v1_1_3/__init__.py rename to ix-dev/stable/wg-easy/templates/library/base_v1_1_4/__init__.py diff --git a/ix-dev/stable/wg-easy/templates/library/base_v1_1_3/environment.py b/ix-dev/stable/wg-easy/templates/library/base_v1_1_4/environment.py similarity index 100% rename from ix-dev/stable/wg-easy/templates/library/base_v1_1_3/environment.py rename to ix-dev/stable/wg-easy/templates/library/base_v1_1_4/environment.py diff --git a/ix-dev/stable/wg-easy/templates/library/base_v1_1_4/healthchecks.py b/ix-dev/stable/wg-easy/templates/library/base_v1_1_4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/ix-dev/stable/wg-easy/templates/library/base_v1_1_4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/ix-dev/stable/wg-easy/templates/library/base_v1_1_3/mariadb.py b/ix-dev/stable/wg-easy/templates/library/base_v1_1_4/mariadb.py similarity index 100% rename from ix-dev/stable/wg-easy/templates/library/base_v1_1_3/mariadb.py rename to ix-dev/stable/wg-easy/templates/library/base_v1_1_4/mariadb.py diff --git a/ix-dev/stable/wg-easy/templates/library/base_v1_1_3/metadata.py b/ix-dev/stable/wg-easy/templates/library/base_v1_1_4/metadata.py similarity index 100% rename from ix-dev/stable/wg-easy/templates/library/base_v1_1_3/metadata.py rename to ix-dev/stable/wg-easy/templates/library/base_v1_1_4/metadata.py diff --git a/ix-dev/stable/wg-easy/templates/library/base_v1_1_3/network.py b/ix-dev/stable/wg-easy/templates/library/base_v1_1_4/network.py similarity index 100% rename from ix-dev/stable/wg-easy/templates/library/base_v1_1_3/network.py rename to ix-dev/stable/wg-easy/templates/library/base_v1_1_4/network.py diff --git a/ix-dev/stable/wg-easy/templates/library/base_v1_1_4/permissions.py b/ix-dev/stable/wg-easy/templates/library/base_v1_1_4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/ix-dev/stable/wg-easy/templates/library/base_v1_1_4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/ix-dev/stable/wg-easy/templates/library/base_v1_1_3/ports.py b/ix-dev/stable/wg-easy/templates/library/base_v1_1_4/ports.py similarity index 100% rename from ix-dev/stable/wg-easy/templates/library/base_v1_1_3/ports.py rename to ix-dev/stable/wg-easy/templates/library/base_v1_1_4/ports.py diff --git a/ix-dev/stable/wg-easy/templates/library/base_v1_1_3/postgres.py b/ix-dev/stable/wg-easy/templates/library/base_v1_1_4/postgres.py similarity index 100% rename from ix-dev/stable/wg-easy/templates/library/base_v1_1_3/postgres.py rename to ix-dev/stable/wg-easy/templates/library/base_v1_1_4/postgres.py diff --git a/ix-dev/stable/wg-easy/templates/library/base_v1_1_3/redis.py b/ix-dev/stable/wg-easy/templates/library/base_v1_1_4/redis.py similarity index 100% rename from ix-dev/stable/wg-easy/templates/library/base_v1_1_3/redis.py rename to ix-dev/stable/wg-easy/templates/library/base_v1_1_4/redis.py diff --git a/ix-dev/stable/wg-easy/templates/library/base_v1_1_3/resources.py b/ix-dev/stable/wg-easy/templates/library/base_v1_1_4/resources.py similarity index 100% rename from ix-dev/stable/wg-easy/templates/library/base_v1_1_3/resources.py rename to ix-dev/stable/wg-easy/templates/library/base_v1_1_4/resources.py diff --git a/ix-dev/stable/wg-easy/templates/library/base_v1_1_3/security.py b/ix-dev/stable/wg-easy/templates/library/base_v1_1_4/security.py similarity index 100% rename from ix-dev/stable/wg-easy/templates/library/base_v1_1_3/security.py rename to ix-dev/stable/wg-easy/templates/library/base_v1_1_4/security.py diff --git a/ix-dev/stable/wg-easy/templates/library/base_v1_1_3/storage.py b/ix-dev/stable/wg-easy/templates/library/base_v1_1_4/storage.py similarity index 100% rename from ix-dev/stable/wg-easy/templates/library/base_v1_1_3/storage.py rename to ix-dev/stable/wg-easy/templates/library/base_v1_1_4/storage.py diff --git a/ix-dev/stable/wg-easy/templates/library/base_v1_1_3/utils.py b/ix-dev/stable/wg-easy/templates/library/base_v1_1_4/utils.py similarity index 100% rename from ix-dev/stable/wg-easy/templates/library/base_v1_1_3/utils.py rename to ix-dev/stable/wg-easy/templates/library/base_v1_1_4/utils.py diff --git a/library/1.1.3/healthchecks.py b/library/1.1.3/healthchecks.py deleted file mode 100644 index 09f8ac53fd..0000000000 --- a/library/1.1.3/healthchecks.py +++ /dev/null @@ -1,121 +0,0 @@ -from . import utils - - -def check_health(test, interval=10, timeout=5, retries=30, start_period=10): - if not test: - utils.throw_error("Expected [test] to be set") - - return { - "test": test, - "interval": f"{interval}s", - "timeout": f"{timeout}s", - "retries": retries, - "start_period": f"{start_period}s", - } - - -def mariadb_test(db, config=None): - config = config or {} - if not db: - utils.throw_error("MariaDB container: [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 3306) - - return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" - - -def pg_test(user, db, config=None): - config = config or {} - if not user or not db: - utils.throw_error("Postgres container: [user] and [db] must be set") - - host = config.get("host", "127.0.0.1") - port = config.get("port", 5432) - - return f"pg_isready -h {host} -p {port} -d {db} -U {user}" - - -def redis_test(config=None): - config = config or {} - - host = config.get("host", "127.0.0.1") - port = config.get("port", 6379) - password = "$$REDIS_PASSWORD" - - return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" - - -def curl_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--insecure") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def wget_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - scheme = config.get("scheme", "http") - host = config.get("host", "127.0.0.1") - headers = config.get("headers", []) - - opts = [] - if scheme == "https": - opts.append("--no-check-certificate") - - for header in headers: - if not header[0] or not header[1]: - utils.throw_error("Expected [header] to be a list of two items") - opts.append(f'--header "{header[0]}: {header[1]}"') - - return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" - - -def http_test(port, path, config=None): - config = config or {} - if not port or not path: - utils.throw_error("Expected [port] and [path] to be set") - - host = config.get("host", "127.0.0.1") - - return ( - f"/bin/bash -c 'exec {{health_check_fd}}<>/dev/tcp/{host}/{port} && echo -e \"GET {path} HTTP/1.1\\r\\nHost: " - + f"{host}\\r\\nConnection: close\\r\\n\\r\\n\" >&$${{health_check_fd}} && cat <&$${{health_check_fd}}'" - ) - - -def netcat_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"nc -z -w 1 {host} {port}" - - -def tcp_test(port, config=None): - config = config or {} - if not port: - utils.throw_error("Expected [port] to be set") - - host = config.get("host", "127.0.0.1") - - return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/library/1.1.3/permissions.py b/library/1.1.3/permissions.py deleted file mode 100644 index 7d98983af6..0000000000 --- a/library/1.1.3/permissions.py +++ /dev/null @@ -1,139 +0,0 @@ -import jsonschema - -from . import utils - -ITEM_SCHEMA = { - "type": "object", - "properties": { - "dir": {"type": "string"}, - "mode": {"type": "string", "enum": ["always", "check"]}, - "uid": {"type": "integer"}, - "gid": {"type": "integer"}, - "chmod": {"type": "string"}, - "is_temporary": {"type": "boolean"}, - }, - "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], -} - - -def perms_container(items=[], volumes=[]): - if not items: - raise ValueError("Expected [items] to be set for perms_container") - if not volumes: - raise ValueError("Expected [volumes] to be set for perms_container") - - command = [process_dir_shell_func()] - for item in items: - try: - jsonschema.validate(item, ITEM_SCHEMA) - except jsonschema.ValidationError as e: - utils.throw_error(f"Item [{item}] is not valid: {e}") - cmd = [ - "process_dir", - item["dir"], - item["mode"], - str(item["uid"]), - str(item["gid"]), - item["chmod"], - str(item["is_temporary"]).lower(), - ] - command.append(" ".join(cmd)) - - return { - "image": "bash", - "user": "root", - "deploy": { - "resources": { - "limits": {"cpus": "1.0", "memory": "512m"}, - } - }, - "entrypoint": ["bash", "-c"], - "command": ["\n".join(command)], - "volumes": volumes, - } - - -# Don't forget to use double $ for shell variables, -# otherwise docker-compose will try to expand them -def process_dir_shell_func(): - return """ -function process_dir() { - local dir=$$1 - local mode=$$2 - local uid=$$3 - local gid=$$4 - local chmod=$$5 - local is_temporary=$$6 - - local fix_owner="false" - local fix_perms="false" - - if [ -z "$$dir" ]; then - echo "Path is empty, skipping..." - exit 0 - fi - - if [ ! -d "$$dir" ]; then - echo "Path [$$dir] does is not a directory, skipping..." - exit 0 - fi - - if [ "$$is_temporary" = "true" ]; then - echo "Path [$$dir] is a temporary directory, ensuring it is empty..." - # Exclude the safe directory, where we can use to mount files temporarily - find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + - fi - - if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then - echo "Path [$$dir] is not empty, skipping..." - exit 0 - fi - - echo "Current Ownership and Permissions on [$$dir]:" - echo "chown: $$(stat -c "%u %g" "$$dir")" - echo "chmod: $$(stat -c "%a" "$$dir")" - - if [ "$$mode" = "always" ]; then - fix_owner="true" - fix_perms="true" - fi - - if [ "$$mode" = "check" ]; then - if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then - echo "Ownership is correct. Skipping..." - fix_owner="false" - else - echo "Ownership is incorrect. Fixing..." - fix_owner="true" - fi - - if [ "$$chmod" = "false" ]; then - echo "Skipping permissions check, chmod is false" - elif [ -n "$$chmod" ]; then - if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" - else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" - fi - fi - fi - - if [ "$$fix_owner" = "true" ]; then - echo "Changing ownership to $$uid:$$gid on: [$$dir]" - chown -R "$$uid:$$gid" "$$dir" - echo "Finished changing ownership" - echo "Ownership after changes:" - stat -c "%u %g" "$$dir" - fi - - if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then - echo "Changing permissions to $$chmod on: [$$dir]" - chmod -R "$$chmod" "$$dir" - echo "Finished changing permissions" - echo "Permissions after changes:" - stat -c "%a" "$$dir" - fi -} -""" diff --git a/library/1.1.3/__init__.py b/library/1.1.4/__init__.py similarity index 100% rename from library/1.1.3/__init__.py rename to library/1.1.4/__init__.py diff --git a/library/1.1.3/environment.py b/library/1.1.4/environment.py similarity index 100% rename from library/1.1.3/environment.py rename to library/1.1.4/environment.py diff --git a/library/1.1.4/healthchecks.py b/library/1.1.4/healthchecks.py new file mode 100644 index 0000000000..cc98270d1d --- /dev/null +++ b/library/1.1.4/healthchecks.py @@ -0,0 +1,120 @@ +from . import utils + + +def check_health(test, interval=10, timeout=5, retries=30, start_period=10): + if not test: + utils.throw_error("Expected [test] to be set") + + return { + "test": test, + "interval": f"{interval}s", + "timeout": f"{timeout}s", + "retries": retries, + "start_period": f"{start_period}s", + } + + +def mariadb_test(db, config=None): + config = config or {} + if not db: + utils.throw_error("MariaDB container: [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 3306) + + return f"mariadb-admin --user=root --host={host} --port={port} --password=$$MARIADB_ROOT_PASSWORD ping" + + +def pg_test(user, db, config=None): + config = config or {} + if not user or not db: + utils.throw_error("Postgres container: [user] and [db] must be set") + + host = config.get("host", "127.0.0.1") + port = config.get("port", 5432) + + return f"pg_isready -h {host} -p {port} -d {db} -U {user}" + + +def redis_test(config=None): + config = config or {} + + host = config.get("host", "127.0.0.1") + port = config.get("port", 6379) + password = "$$REDIS_PASSWORD" + + return f"redis-cli -h {host} -p {port} -a {password} ping | grep -q PONG" + + +def curl_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--insecure") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"curl --silent --output /dev/null --show-error --fail {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def wget_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + scheme = config.get("scheme", "http") + host = config.get("host", "127.0.0.1") + headers = config.get("headers", []) + + opts = [] + if scheme == "https": + opts.append("--no-check-certificate") + + for header in headers: + if not header[0] or not header[1]: + utils.throw_error("Expected [header] to be a list of two items") + opts.append(f'--header "{header[0]}: {header[1]}"') + + return f"wget --spider --quiet {' '.join(opts)} {scheme}://{host}:{port}{path}" + + +def http_test(port, path, config=None): + config = config or {} + if not port or not path: + utils.throw_error("Expected [port] and [path] to be set") + + host = config.get("host", "127.0.0.1") + + return f""" + /bin/bash -c 'exec {{hc_fd}}<>/dev/tcp/{host}/{port} && echo -e "GET {path} HTTP/1.1\\r\\nHost: {host}\\r\\nConnection: close\\r\\n\\r\\n" >&$${{hc_fd}} && cat <&$${{hc_fd}} | grep "HTTP/1.1 200"' + """ # noqa + + +def netcat_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"nc -z -w 1 {host} {port}" + + +def tcp_test(port, config=None): + config = config or {} + if not port: + utils.throw_error("Expected [port] to be set") + + host = config.get("host", "127.0.0.1") + + return f"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/{host}/{port}'" diff --git a/library/1.1.3/mariadb.py b/library/1.1.4/mariadb.py similarity index 100% rename from library/1.1.3/mariadb.py rename to library/1.1.4/mariadb.py diff --git a/library/1.1.3/metadata.py b/library/1.1.4/metadata.py similarity index 100% rename from library/1.1.3/metadata.py rename to library/1.1.4/metadata.py diff --git a/library/1.1.3/network.py b/library/1.1.4/network.py similarity index 100% rename from library/1.1.3/network.py rename to library/1.1.4/network.py diff --git a/library/1.1.4/permissions.py b/library/1.1.4/permissions.py new file mode 100644 index 0000000000..1ce6e60ca1 --- /dev/null +++ b/library/1.1.4/permissions.py @@ -0,0 +1,139 @@ +import jsonschema + +from . import utils + +ITEM_SCHEMA = { + "type": "object", + "properties": { + "dir": {"type": "string"}, + "mode": {"type": "string", "enum": ["always", "check"]}, + "uid": {"type": "integer"}, + "gid": {"type": "integer"}, + "chmod": {"type": "string"}, + "is_temporary": {"type": "boolean"}, + }, + "required": ["dir", "mode", "uid", "gid", "chmod", "is_temporary"], +} + + +def perms_container(items=[], volumes=[]): + if not items: + raise ValueError("Expected [items] to be set for perms_container") + if not volumes: + raise ValueError("Expected [volumes] to be set for perms_container") + + command = [process_dir_shell_func()] + for item in items: + try: + jsonschema.validate(item, ITEM_SCHEMA) + except jsonschema.ValidationError as e: + utils.throw_error(f"Item [{item}] is not valid: {e}") + cmd = [ + "process_dir", + item["dir"], + item["mode"], + str(item["uid"]), + str(item["gid"]), + item["chmod"], + str(item["is_temporary"]).lower(), + ] + command.append(" ".join(cmd)) + + return { + "image": "bash", + "user": "root", + "deploy": { + "resources": { + "limits": {"cpus": "1.0", "memory": "512m"}, + } + }, + "entrypoint": ["bash", "-c"], + "command": ["\n".join(command)], + "volumes": volumes, + } + + +# Don't forget to use double $ for shell variables, +# otherwise docker-compose will try to expand them +def process_dir_shell_func(): + return """ +function process_dir() { + local dir=$$1 + local mode=$$2 + local uid=$$3 + local gid=$$4 + local chmod=$$5 + local is_temporary=$$6 + + local fix_owner="false" + local fix_perms="false" + + if [ -z "$$dir" ]; then + echo "Path is empty, skipping..." + return 0 + fi + + if [ ! -d "$$dir" ]; then + echo "Path [$$dir] does is not a directory, skipping..." + return 0 + fi + + if [ "$$is_temporary" = "true" ]; then + echo "Path [$$dir] is a temporary directory, ensuring it is empty..." + # Exclude the safe directory, where we can use to mount files temporarily + find "$$dir" -mindepth 1 -maxdepth 1 ! -name "ix-safe" -exec rm -rf {} + + fi + + if [ "$$is_temporary" = "false" ] && [ -n "$$(ls -A $$dir)" ]; then + echo "Path [$$dir] is not empty, skipping..." + return 0 + fi + + echo "Current Ownership and Permissions on [$$dir]:" + echo "chown: $$(stat -c "%u %g" "$$dir")" + echo "chmod: $$(stat -c "%a" "$$dir")" + + if [ "$$mode" = "always" ]; then + fix_owner="true" + fix_perms="true" + fi + + if [ "$$mode" = "check" ]; then + if [ $$(stat -c %u "$$dir") -eq $$uid ] && [ $$(stat -c %g "$$dir") -eq $$gid ]; then + echo "Ownership is correct. Skipping..." + fix_owner="false" + else + echo "Ownership is incorrect. Fixing..." + fix_owner="true" + fi + + if [ "$$chmod" = "false" ]; then + echo "Skipping permissions check, chmod is false" + elif [ -n "$$chmod" ]; then + if [ $$(stat -c %a "$$dir") -eq $$chmod ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + fi + fi + + if [ "$$fix_owner" = "true" ]; then + echo "Changing ownership to $$uid:$$gid on: [$$dir]" + chown -R "$$uid:$$gid" "$$dir" + echo "Finished changing ownership" + echo "Ownership after changes:" + stat -c "%u %g" "$$dir" + fi + + if [ -n "$$chmod" ] && [ "$$fix_perms" = "true" ]; then + echo "Changing permissions to $$chmod on: [$$dir]" + chmod -R "$$chmod" "$$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$$dir" + fi +} +""" diff --git a/library/1.1.3/ports.py b/library/1.1.4/ports.py similarity index 100% rename from library/1.1.3/ports.py rename to library/1.1.4/ports.py diff --git a/library/1.1.3/postgres.py b/library/1.1.4/postgres.py similarity index 100% rename from library/1.1.3/postgres.py rename to library/1.1.4/postgres.py diff --git a/library/1.1.3/redis.py b/library/1.1.4/redis.py similarity index 100% rename from library/1.1.3/redis.py rename to library/1.1.4/redis.py diff --git a/library/1.1.3/resources.py b/library/1.1.4/resources.py similarity index 100% rename from library/1.1.3/resources.py rename to library/1.1.4/resources.py diff --git a/library/1.1.3/security.py b/library/1.1.4/security.py similarity index 100% rename from library/1.1.3/security.py rename to library/1.1.4/security.py diff --git a/library/1.1.3/storage.py b/library/1.1.4/storage.py similarity index 100% rename from library/1.1.3/storage.py rename to library/1.1.4/storage.py diff --git a/library/1.1.3/utils.py b/library/1.1.4/utils.py similarity index 100% rename from library/1.1.3/utils.py rename to library/1.1.4/utils.py diff --git a/library/hashes.yaml b/library/hashes.yaml index b9d6481cbf..6067c8ffd9 100644 --- a/library/hashes.yaml +++ b/library/hashes.yaml @@ -1,2 +1,2 @@ 0.0.1: f074617a82a86d2a6cc78a4c8a4296fc9d168e456f12713e50c696557b302133 -1.1.3: 2aa61e120fd30dd72800bea5d56ad12793d4a6b74cf69140780d51add22c7768 +1.1.4: 6e32ff5969906d9c3a10fea2b17fdd3197afb052d3432344da03188d8a907113