diff --git a/.github/renovate-config.js b/.github/renovate-config.js index b2e8b4d73c..87f798dd95 100644 --- a/.github/renovate-config.js +++ b/.github/renovate-config.js @@ -258,9 +258,14 @@ module.exports = { ), customVersioning( // 17-3.5 - "^17-(?\\d+)\\.(?\\d+)$", + "^(17|18)-(?\\d+)\\.(?\\d+)$", ["postgis/postgis"] ), + customVersioning( + // 0.8.1-pg18-trixie + "^(?\\d+)\\.(?\\d+)\\.(?\\d+)-pg(17|18)(-\\w+)?$", + ["pgvector/pgvector"] + ), customVersioning( // 2.4-dev "^(?\\d+)\\.(?\\d+)-dev$", diff --git a/ix-dev/community/adventurelog/app.yaml b/ix-dev/community/adventurelog/app.yaml index a10e8935a6..3dc7887bc1 100644 --- a/ix-dev/community/adventurelog/app.yaml +++ b/ix-dev/community/adventurelog/app.yaml @@ -23,8 +23,8 @@ keywords: - location - tracker - planner -lib_version: 2.1.65 -lib_version_hash: f92a9ee78c78fc77f86e7d8b545bd4c605c31c599e2c5da59f1615aa516cb8b5 +lib_version: 2.1.66 +lib_version_hash: 986abcd60fd0cc6277c80d55d2798356ddda1bd6348580ca7198b003571707fa maintainers: - email: dev@truenas.com name: truenas @@ -51,4 +51,4 @@ sources: - https://github.com/seanmorley15/AdventureLog title: AdventureLog train: community -version: 1.0.8 +version: 1.1.0 diff --git a/ix-dev/community/adventurelog/app_migrations.yaml b/ix-dev/community/adventurelog/app_migrations.yaml new file mode 100644 index 0000000000..ea2bfc957b --- /dev/null +++ b/ix-dev/community/adventurelog/app_migrations.yaml @@ -0,0 +1,6 @@ +migrations: +- file: set_default_postgis_image + from: + max_version: 1.0.8 + target: + min_version: 1.1.0 diff --git a/ix-dev/community/adventurelog/ix_values.yaml b/ix-dev/community/adventurelog/ix_values.yaml index 651049b641..8b654997e9 100644 --- a/ix-dev/community/adventurelog/ix_values.yaml +++ b/ix-dev/community/adventurelog/ix_values.yaml @@ -8,9 +8,15 @@ images: frontend_image: repository: ghcr.io/seanmorley15/adventurelog-frontend tag: v0.11.0 - postgis_image: + postgis_17_image: repository: postgis/postgis tag: "17-3.5" + postgis_18_image: + repository: postgis/postgis + tag: "18-3.6" + postgres_upgrade_image: + repository: ixsystems/postgres-upgrade + tag: 1.1.3 consts: backend_container_name: backend diff --git a/ix-dev/community/adventurelog/migrations/set_default_postgis_image b/ix-dev/community/adventurelog/migrations/set_default_postgis_image new file mode 100755 index 0000000000..95d4265798 --- /dev/null +++ b/ix-dev/community/adventurelog/migrations/set_default_postgis_image @@ -0,0 +1,20 @@ +#!/usr/bin/python3 + +import os +import sys +import yaml + + +def migrate(values): + if not values["adventurelog"].get("postgres_image_selector"): + values["adventurelog"]["postgres_image_selector"] = "postgis_17_image" + return values + + +if __name__ == "__main__": + if len(sys.argv) != 2: + exit(1) + + if os.path.exists(sys.argv[1]): + with open(sys.argv[1], "r") as f: + print(yaml.dump(migrate(yaml.safe_load(f.read())))) diff --git a/ix-dev/community/adventurelog/questions.yaml b/ix-dev/community/adventurelog/questions.yaml index 713e49d72d..3b98f32bcd 100644 --- a/ix-dev/community/adventurelog/questions.yaml +++ b/ix-dev/community/adventurelog/questions.yaml @@ -26,6 +26,24 @@ questions: schema: type: dict attrs: + - variable: postgres_image_selector + label: Postgres Image (CAUTION) + description: | + If you are changing this after the postgres directory has been initialized,
+ STOP! and make sure you have a backup of your data.
+ Changing this will trigger an one way database upgrade.
+ You can only select newer versions of postgres.
+ Selecting an older version will refuse to start.
+ If something goes wrong, you will have to restore from backup. + schema: + type: string + default: postgis_18_image + required: true + enum: + - value: postgis_17_image + description: Postgres 17 + - value: postgis_18_image + description: Postgres 18 - variable: db_password label: Database Password description: The password for AdventureLog. diff --git a/ix-dev/community/adventurelog/templates/docker-compose.yaml b/ix-dev/community/adventurelog/templates/docker-compose.yaml index c879a88481..5038257ee0 100644 --- a/ix-dev/community/adventurelog/templates/docker-compose.yaml +++ b/ix-dev/community/adventurelog/templates/docker-compose.yaml @@ -7,7 +7,7 @@ {# Postgis #} {% set pg_config = {"user": values.consts.db_user, "password": values.adventurelog.db_password, "database": values.consts.db_name, "volume": values.storage.postgres_data} %} -{% set postgis = tpl.deps.postgres(values.consts.postgis_container_name, "postgis_image", pg_config, perm_container) %} +{% set postgis = tpl.deps.postgres(values.consts.postgis_container_name, values.adventurelog.postgres_image_selector, pg_config, perm_container) %} {# Frontend #} {% do frontend.set_user(1000, 1000) %} diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/__init__.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/__init__.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/__init__.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/__init__.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/client.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/client.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/client.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/client.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/configs.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/configs.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/configs.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/configs.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/container.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/container.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/container.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/container.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/depends.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/depends.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/depends.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/depends.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/deploy.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/deploy.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/deploy.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/deploy.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/deps.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/deps.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/deps.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/deps.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/deps_elastic.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/deps_elastic.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/deps_elastic.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/deps_elastic.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/deps_mariadb.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/deps_mariadb.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/deps_mariadb.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/deps_mariadb.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/deps_meilisearch.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/deps_meilisearch.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/deps_meilisearch.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/deps_meilisearch.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/deps_mongodb.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/deps_mongodb.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/deps_mongodb.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/deps_mongodb.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/deps_perms.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/deps_perms.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/deps_perms.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/deps_perms.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/deps_postgres.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/deps_postgres.py similarity index 94% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/deps_postgres.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/deps_postgres.py index 8269990377..1e6f7471c8 100644 --- a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/deps_postgres.py +++ b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/deps_postgres.py @@ -34,6 +34,11 @@ SUPPORTED_REPOS = [ "pgvector/pgvector", "ghcr.io/immich-app/postgres", ] +SUPPORTED_UPGRADE_REPOS = [ + "postgres", + "postgis/postgis", + "pgvector/pgvector", +] def get_major_version(variant: str, tag: str): @@ -52,15 +57,16 @@ def get_major_version(variant: str, tag: str): return x.split("-")[0] elif variant == "pgvector/pgvector": - # 0.8.1-pg17 - regex = re.compile(r"^\d+\.\d+\.\d+\-pg\d+") + # 0.8.1-pg17-trixie + regex = re.compile(r"^\d+\.\d+\.\d+\-pg\d+(\-\w+)?") def oper(x): - return x.split("-")[1].lstrip("pg") + parts = x.split("-") + return parts[1].lstrip("pg") elif variant == "ghcr.io/immich-app/postgres": - # 15-vectorchord0.4.3-pgvectors0.2.0 - regex = re.compile(r"^\d+\-vectorchord\d+\.\d+\.\d+(\-pgvectors?\d+\.\d+\.\d+)?") + # 15-vectorchord0.4.3 + regex = re.compile(r"^\d+\-vectorchord\d+\.\d+\.\d+") def oper(x): return x.split("-")[0] @@ -113,7 +119,7 @@ class PostgresContainer: # eg we don't want to handle upgrades of pg_vector or immich at the moment repo = self._get_repo(image) - if repo == "postgres": + if repo in SUPPORTED_UPGRADE_REPOS: self._data_dir = "/var/lib/postgresql" target_major_version = self._get_target_version(image) # This is the new format upstream Postgres uses/suggests. diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/deps_redis.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/deps_redis.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/deps_redis.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/deps_redis.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/deps_solr.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/deps_solr.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/deps_solr.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/deps_solr.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/deps_tika.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/deps_tika.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/deps_tika.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/deps_tika.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/device.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/device.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/device.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/device.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/device_cgroup_rules.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/device_cgroup_rules.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/device_cgroup_rules.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/device_cgroup_rules.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/devices.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/devices.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/devices.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/devices.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/dns.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/dns.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/dns.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/dns.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/environment.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/environment.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/environment.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/environment.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/error.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/error.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/error.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/error.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/expose.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/expose.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/expose.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/expose.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/extra_hosts.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/extra_hosts.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/extra_hosts.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/extra_hosts.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/formatter.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/formatter.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/formatter.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/formatter.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/functions.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/functions.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/functions.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/functions.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/healthcheck.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/healthcheck.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/healthcheck.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/healthcheck.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/labels.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/labels.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/labels.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/labels.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/notes.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/notes.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/notes.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/notes.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/portals.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/portals.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/portals.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/portals.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/ports.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/ports.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/ports.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/ports.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/render.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/render.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/render.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/render.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/resources.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/resources.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/resources.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/resources.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/restart.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/restart.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/restart.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/restart.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/security_opts.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/security_opts.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/security_opts.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/security_opts.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/storage.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/storage.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/storage.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/storage.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/sysctls.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/sysctls.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/sysctls.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/sysctls.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/__init__.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/__init__.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/__init__.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/__init__.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_build_image.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_build_image.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_build_image.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_build_image.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_configs.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_configs.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_configs.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_configs.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_container.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_container.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_container.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_container.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_depends.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_depends.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_depends.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_depends.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_deps.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_deps.py similarity index 99% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_deps.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_deps.py index 2792798b03..197486537a 100644 --- a/ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_deps.py +++ b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_deps.py @@ -537,7 +537,10 @@ def test_add_postgres_with_invalid_tag(mock_values): def test_no_upgrade_container_with_non_postgres_image(mock_values): - mock_values["images"]["postgres_image"] = {"repository": "pgvector/pgvector", "tag": "0.8.1-pg17"} + mock_values["images"]["postgres_image"] = { + "repository": "ghcr.io/immich-app/postgres", + "tag": "15-vectorchord0.4.3-pgvectors0.2.0", + } render = Render(mock_values) c1 = render.add_container("test_container", "test_image") c1.healthcheck.disable() @@ -605,7 +608,7 @@ def test_postgres_with_upgrade_container(mock_values): def test_add_mongodb(mock_values): - mock_values["images"]["mongodb_image"] = {"repository": "mongodb", "tag": "latest"} + mock_values["images"]["mongodb_image"] = {"repository": "mongo", "tag": "latest"} render = Render(mock_values) c1 = render.add_container("test_container", "test_image") c1.healthcheck.disable() @@ -627,7 +630,7 @@ def test_add_mongodb(mock_values): output = render.render() assert "devices" not in output["services"]["mongodb_container"] assert "reservations" not in output["services"]["mongodb_container"]["deploy"]["resources"] - assert output["services"]["mongodb_container"]["image"] == "mongodb:latest" + assert output["services"]["mongodb_container"]["image"] == "mongo:latest" assert output["services"]["mongodb_container"]["user"] == "568:568" assert output["services"]["mongodb_container"]["deploy"]["resources"]["limits"]["cpus"] == "2.0" assert output["services"]["mongodb_container"]["deploy"]["resources"]["limits"]["memory"] == "4096M" @@ -781,7 +784,7 @@ def test_add_meilisearch_unsupported_repo(mock_values): def test_add_elasticsearch(mock_values): mock_values["images"]["elastic_image"] = { - "repository": "docker.elastic.co/elasticsearch/elasticsearch", + "repository": "elasticsearch", "tag": "9.1.2", } render = Render(mock_values) @@ -804,7 +807,7 @@ def test_add_elasticsearch(mock_values): output = render.render() assert "devices" not in output["services"]["elastic_container"] assert "reservations" not in output["services"]["elastic_container"]["deploy"]["resources"] - assert output["services"]["elastic_container"]["image"] == "docker.elastic.co/elasticsearch/elasticsearch:9.1.2" + assert output["services"]["elastic_container"]["image"] == "elasticsearch:9.1.2" assert output["services"]["elastic_container"]["user"] == "1000:1000" assert output["services"]["elastic_container"]["deploy"]["resources"]["limits"]["cpus"] == "2.0" assert output["services"]["elastic_container"]["deploy"]["resources"]["limits"]["memory"] == "4096M" diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_device.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_device.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_device.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_device.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_device_cgroup_rules.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_device_cgroup_rules.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_device_cgroup_rules.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_device_cgroup_rules.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_dns.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_dns.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_dns.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_dns.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_environment.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_environment.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_environment.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_environment.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_expose.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_expose.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_expose.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_expose.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_extra_hosts.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_extra_hosts.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_extra_hosts.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_extra_hosts.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_formatter.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_formatter.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_formatter.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_formatter.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_functions.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_functions.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_functions.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_functions.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_healthcheck.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_healthcheck.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_healthcheck.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_healthcheck.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_labels.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_labels.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_labels.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_labels.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_notes.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_notes.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_notes.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_notes.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_portal.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_portal.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_portal.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_portal.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_ports.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_ports.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_ports.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_ports.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_render.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_render.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_render.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_render.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_resources.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_resources.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_resources.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_resources.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_restart.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_restart.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_restart.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_restart.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_security_opts.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_security_opts.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_security_opts.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_security_opts.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_sysctls.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_sysctls.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_sysctls.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_sysctls.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_validations.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_validations.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_validations.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_validations.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_volumes.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_volumes.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_volumes.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/tests/test_volumes.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/tmpfs.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/tmpfs.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/tmpfs.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/tmpfs.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/validations.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/validations.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/validations.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/validations.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/volume_mount.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/volume_mount.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/volume_mount.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/volume_mount.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/volume_mount_types.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/volume_mount_types.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/volume_mount_types.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/volume_mount_types.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/volume_sources.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/volume_sources.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/volume_sources.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/volume_sources.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/volume_types.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/volume_types.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/volume_types.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/volume_types.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/volumes.py b/ix-dev/community/adventurelog/templates/library/base_v2_1_66/volumes.py similarity index 100% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/volumes.py rename to ix-dev/community/adventurelog/templates/library/base_v2_1_66/volumes.py diff --git a/ix-dev/community/adventurelog/templates/test_values/basic-values.yaml b/ix-dev/community/adventurelog/templates/test_values/basic-values.yaml index c03379ed4a..a0de9eef95 100644 --- a/ix-dev/community/adventurelog/templates/test_values/basic-values.yaml +++ b/ix-dev/community/adventurelog/templates/test_values/basic-values.yaml @@ -6,6 +6,7 @@ resources: TZ: Etc/UTC adventurelog: + postgres_image_selector: postgis_18_image db_password: secret backend_url: http://localhost:8080 frontend_url: http://localhost:8081 diff --git a/ix-dev/community/chatwoot/app.yaml b/ix-dev/community/chatwoot/app.yaml index f68dc8ed44..f0a1b28f65 100644 --- a/ix-dev/community/chatwoot/app.yaml +++ b/ix-dev/community/chatwoot/app.yaml @@ -12,8 +12,8 @@ icon: https://media.sys.truenas.net/apps/chatwoot/icons/icon.svg keywords: - support - live chat -lib_version: 2.1.65 -lib_version_hash: f92a9ee78c78fc77f86e7d8b545bd4c605c31c599e2c5da59f1615aa516cb8b5 +lib_version: 2.1.66 +lib_version_hash: 986abcd60fd0cc6277c80d55d2798356ddda1bd6348580ca7198b003571707fa maintainers: - email: dev@truenas.com name: truenas @@ -41,4 +41,4 @@ sources: - https://hub.docker.com/r/chatwoot/chatwoot title: Chatwoot train: community -version: 1.0.29 +version: 1.0.30 diff --git a/ix-dev/community/chatwoot/ix_values.yaml b/ix-dev/community/chatwoot/ix_values.yaml index bdd83f78dd..a885a23fa0 100644 --- a/ix-dev/community/chatwoot/ix_values.yaml +++ b/ix-dev/community/chatwoot/ix_values.yaml @@ -14,9 +14,12 @@ images: postgres_17_image: repository: pgvector/pgvector tag: 0.8.1-pg17 + postgres_18_image: + repository: pgvector/pgvector + tag: 0.8.1-pg18-trixie postgres_upgrade_image: repository: ixsystems/postgres-upgrade - tag: 1.1.2 + tag: 1.1.3 consts: chatwoot_container_name: chatwoot diff --git a/ix-dev/community/chatwoot/questions.yaml b/ix-dev/community/chatwoot/questions.yaml index f8d9a0760c..406d7747f5 100644 --- a/ix-dev/community/chatwoot/questions.yaml +++ b/ix-dev/community/chatwoot/questions.yaml @@ -50,11 +50,13 @@ questions: If something goes wrong, you will have to restore from backup. schema: type: string - default: postgres_17_image + default: postgres_18_image required: true enum: - value: postgres_17_image description: Postgres 17 + - value: postgres_18_image + description: Postgres 18 - variable: db_password label: Database Password description: The password for Chatwoot. diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/__init__.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/__init__.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/__init__.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/__init__.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/client.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/client.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/client.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/client.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/configs.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/configs.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/configs.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/configs.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/container.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/container.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/container.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/container.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/depends.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/depends.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/depends.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/depends.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/deploy.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/deploy.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/deploy.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/deploy.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/deps.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/deps.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/deps.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/deps.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/deps_elastic.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/deps_elastic.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/deps_elastic.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/deps_elastic.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/deps_mariadb.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/deps_mariadb.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/deps_mariadb.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/deps_mariadb.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/deps_meilisearch.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/deps_meilisearch.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/deps_meilisearch.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/deps_meilisearch.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/deps_mongodb.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/deps_mongodb.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/deps_mongodb.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/deps_mongodb.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/deps_perms.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/deps_perms.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/deps_perms.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/deps_perms.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/deps_postgres.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/deps_postgres.py similarity index 94% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/deps_postgres.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/deps_postgres.py index 8269990377..1e6f7471c8 100644 --- a/ix-dev/community/dawarich/templates/library/base_v2_1_65/deps_postgres.py +++ b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/deps_postgres.py @@ -34,6 +34,11 @@ SUPPORTED_REPOS = [ "pgvector/pgvector", "ghcr.io/immich-app/postgres", ] +SUPPORTED_UPGRADE_REPOS = [ + "postgres", + "postgis/postgis", + "pgvector/pgvector", +] def get_major_version(variant: str, tag: str): @@ -52,15 +57,16 @@ def get_major_version(variant: str, tag: str): return x.split("-")[0] elif variant == "pgvector/pgvector": - # 0.8.1-pg17 - regex = re.compile(r"^\d+\.\d+\.\d+\-pg\d+") + # 0.8.1-pg17-trixie + regex = re.compile(r"^\d+\.\d+\.\d+\-pg\d+(\-\w+)?") def oper(x): - return x.split("-")[1].lstrip("pg") + parts = x.split("-") + return parts[1].lstrip("pg") elif variant == "ghcr.io/immich-app/postgres": - # 15-vectorchord0.4.3-pgvectors0.2.0 - regex = re.compile(r"^\d+\-vectorchord\d+\.\d+\.\d+(\-pgvectors?\d+\.\d+\.\d+)?") + # 15-vectorchord0.4.3 + regex = re.compile(r"^\d+\-vectorchord\d+\.\d+\.\d+") def oper(x): return x.split("-")[0] @@ -113,7 +119,7 @@ class PostgresContainer: # eg we don't want to handle upgrades of pg_vector or immich at the moment repo = self._get_repo(image) - if repo == "postgres": + if repo in SUPPORTED_UPGRADE_REPOS: self._data_dir = "/var/lib/postgresql" target_major_version = self._get_target_version(image) # This is the new format upstream Postgres uses/suggests. diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/deps_redis.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/deps_redis.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/deps_redis.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/deps_redis.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/deps_solr.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/deps_solr.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/deps_solr.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/deps_solr.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/deps_tika.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/deps_tika.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/deps_tika.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/deps_tika.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/device.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/device.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/device.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/device.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/device_cgroup_rules.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/device_cgroup_rules.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/device_cgroup_rules.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/device_cgroup_rules.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/devices.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/devices.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/devices.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/devices.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/dns.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/dns.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/dns.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/dns.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/environment.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/environment.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/environment.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/environment.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/error.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/error.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/error.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/error.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/expose.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/expose.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/expose.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/expose.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/extra_hosts.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/extra_hosts.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/extra_hosts.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/extra_hosts.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/formatter.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/formatter.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/formatter.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/formatter.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/functions.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/functions.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/functions.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/functions.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/healthcheck.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/healthcheck.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/healthcheck.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/healthcheck.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/labels.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/labels.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/labels.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/labels.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/notes.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/notes.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/notes.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/notes.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/portals.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/portals.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/portals.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/portals.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/ports.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/ports.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/ports.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/ports.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/render.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/render.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/render.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/render.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/resources.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/resources.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/resources.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/resources.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/restart.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/restart.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/restart.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/restart.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/security_opts.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/security_opts.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/security_opts.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/security_opts.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/storage.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/storage.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/storage.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/storage.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/sysctls.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/sysctls.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/sysctls.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/sysctls.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/__init__.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/__init__.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/__init__.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/__init__.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_build_image.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_build_image.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_build_image.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_build_image.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_configs.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_configs.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_configs.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_configs.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_container.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_container.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_container.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_container.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_depends.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_depends.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_depends.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_depends.py diff --git a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_deps.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_deps.py similarity index 99% rename from ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_deps.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_deps.py index 2792798b03..197486537a 100644 --- a/ix-dev/community/adventurelog/templates/library/base_v2_1_65/tests/test_deps.py +++ b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_deps.py @@ -537,7 +537,10 @@ def test_add_postgres_with_invalid_tag(mock_values): def test_no_upgrade_container_with_non_postgres_image(mock_values): - mock_values["images"]["postgres_image"] = {"repository": "pgvector/pgvector", "tag": "0.8.1-pg17"} + mock_values["images"]["postgres_image"] = { + "repository": "ghcr.io/immich-app/postgres", + "tag": "15-vectorchord0.4.3-pgvectors0.2.0", + } render = Render(mock_values) c1 = render.add_container("test_container", "test_image") c1.healthcheck.disable() @@ -605,7 +608,7 @@ def test_postgres_with_upgrade_container(mock_values): def test_add_mongodb(mock_values): - mock_values["images"]["mongodb_image"] = {"repository": "mongodb", "tag": "latest"} + mock_values["images"]["mongodb_image"] = {"repository": "mongo", "tag": "latest"} render = Render(mock_values) c1 = render.add_container("test_container", "test_image") c1.healthcheck.disable() @@ -627,7 +630,7 @@ def test_add_mongodb(mock_values): output = render.render() assert "devices" not in output["services"]["mongodb_container"] assert "reservations" not in output["services"]["mongodb_container"]["deploy"]["resources"] - assert output["services"]["mongodb_container"]["image"] == "mongodb:latest" + assert output["services"]["mongodb_container"]["image"] == "mongo:latest" assert output["services"]["mongodb_container"]["user"] == "568:568" assert output["services"]["mongodb_container"]["deploy"]["resources"]["limits"]["cpus"] == "2.0" assert output["services"]["mongodb_container"]["deploy"]["resources"]["limits"]["memory"] == "4096M" @@ -781,7 +784,7 @@ def test_add_meilisearch_unsupported_repo(mock_values): def test_add_elasticsearch(mock_values): mock_values["images"]["elastic_image"] = { - "repository": "docker.elastic.co/elasticsearch/elasticsearch", + "repository": "elasticsearch", "tag": "9.1.2", } render = Render(mock_values) @@ -804,7 +807,7 @@ def test_add_elasticsearch(mock_values): output = render.render() assert "devices" not in output["services"]["elastic_container"] assert "reservations" not in output["services"]["elastic_container"]["deploy"]["resources"] - assert output["services"]["elastic_container"]["image"] == "docker.elastic.co/elasticsearch/elasticsearch:9.1.2" + assert output["services"]["elastic_container"]["image"] == "elasticsearch:9.1.2" assert output["services"]["elastic_container"]["user"] == "1000:1000" assert output["services"]["elastic_container"]["deploy"]["resources"]["limits"]["cpus"] == "2.0" assert output["services"]["elastic_container"]["deploy"]["resources"]["limits"]["memory"] == "4096M" diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_device.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_device.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_device.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_device.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_device_cgroup_rules.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_device_cgroup_rules.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_device_cgroup_rules.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_device_cgroup_rules.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_dns.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_dns.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_dns.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_dns.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_environment.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_environment.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_environment.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_environment.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_expose.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_expose.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_expose.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_expose.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_extra_hosts.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_extra_hosts.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_extra_hosts.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_extra_hosts.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_formatter.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_formatter.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_formatter.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_formatter.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_functions.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_functions.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_functions.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_functions.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_healthcheck.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_healthcheck.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_healthcheck.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_healthcheck.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_labels.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_labels.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_labels.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_labels.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_notes.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_notes.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_notes.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_notes.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_portal.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_portal.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_portal.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_portal.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_ports.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_ports.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_ports.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_ports.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_render.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_render.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_render.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_render.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_resources.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_resources.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_resources.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_resources.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_restart.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_restart.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_restart.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_restart.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_security_opts.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_security_opts.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_security_opts.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_security_opts.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_sysctls.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_sysctls.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_sysctls.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_sysctls.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_validations.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_validations.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_validations.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_validations.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_volumes.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_volumes.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_volumes.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/tests/test_volumes.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/tmpfs.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/tmpfs.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/tmpfs.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/tmpfs.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/validations.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/validations.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/validations.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/validations.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/volume_mount.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/volume_mount.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/volume_mount.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/volume_mount.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/volume_mount_types.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/volume_mount_types.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/volume_mount_types.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/volume_mount_types.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/volume_sources.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/volume_sources.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/volume_sources.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/volume_sources.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/volume_types.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/volume_types.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/volume_types.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/volume_types.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/volumes.py b/ix-dev/community/chatwoot/templates/library/base_v2_1_66/volumes.py similarity index 100% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/volumes.py rename to ix-dev/community/chatwoot/templates/library/base_v2_1_66/volumes.py diff --git a/ix-dev/community/chatwoot/templates/test_values/basic-values.yaml b/ix-dev/community/chatwoot/templates/test_values/basic-values.yaml index 1783ff14fd..a59e25c1e4 100644 --- a/ix-dev/community/chatwoot/templates/test_values/basic-values.yaml +++ b/ix-dev/community/chatwoot/templates/test_values/basic-values.yaml @@ -5,7 +5,7 @@ resources: chatwoot: image_selector: image - postgres_image_selector: postgres_17_image + postgres_image_selector: postgres_18_image db_password: secret redis_password: secret secret_key_base: secret diff --git a/ix-dev/community/chatwoot/templates/test_values/ce-values.yaml b/ix-dev/community/chatwoot/templates/test_values/ce-values.yaml index ad9a9b3088..91c4d6366c 100644 --- a/ix-dev/community/chatwoot/templates/test_values/ce-values.yaml +++ b/ix-dev/community/chatwoot/templates/test_values/ce-values.yaml @@ -5,7 +5,7 @@ resources: chatwoot: image_selector: ce_image - postgres_image_selector: postgres_17_image + postgres_image_selector: postgres_18_image db_password: secret redis_password: secret secret_key_base: secret diff --git a/ix-dev/community/dawarich/app.yaml b/ix-dev/community/dawarich/app.yaml index 2bf6010c5f..6c6350f2f2 100644 --- a/ix-dev/community/dawarich/app.yaml +++ b/ix-dev/community/dawarich/app.yaml @@ -14,8 +14,8 @@ icon: https://media.sys.truenas.net/apps/dawarich/icons/icon.svg keywords: - location - history -lib_version: 2.1.65 -lib_version_hash: f92a9ee78c78fc77f86e7d8b545bd4c605c31c599e2c5da59f1615aa516cb8b5 +lib_version: 2.1.66 +lib_version_hash: 986abcd60fd0cc6277c80d55d2798356ddda1bd6348580ca7198b003571707fa maintainers: - email: dev@truenas.com name: truenas @@ -45,4 +45,4 @@ sources: - https://github.com/Freika/dawarich title: Dawarich train: community -version: 1.1.43 +version: 1.2.0 diff --git a/ix-dev/community/dawarich/app_migrations.yaml b/ix-dev/community/dawarich/app_migrations.yaml index af4e844a39..e0b2b0b4fd 100644 --- a/ix-dev/community/dawarich/app_migrations.yaml +++ b/ix-dev/community/dawarich/app_migrations.yaml @@ -14,3 +14,8 @@ migrations: max_version: 1.1.5 target: min_version: 1.1.9 +- file: set_default_postgis_image + from: + max_version: 1.1.43 + target: + min_version: 1.2.0 diff --git a/ix-dev/community/dawarich/ix_values.yaml b/ix-dev/community/dawarich/ix_values.yaml index dce5ef1455..e17794d7a1 100644 --- a/ix-dev/community/dawarich/ix_values.yaml +++ b/ix-dev/community/dawarich/ix_values.yaml @@ -5,9 +5,15 @@ images: container_utils_image: repository: ixsystems/container-utils tag: 1.0.2 - postgis_image: + postgis_17_image: repository: postgis/postgis tag: "17-3.5" + postgis_18_image: + repository: postgis/postgis + tag: "18-3.6" + postgres_upgrade_image: + repository: ixsystems/postgres-upgrade + tag: 1.1.3 redis_image: repository: valkey/valkey tag: 9.0.0 diff --git a/ix-dev/community/dawarich/migrations/set_default_postgis_image b/ix-dev/community/dawarich/migrations/set_default_postgis_image new file mode 100755 index 0000000000..f022e697ce --- /dev/null +++ b/ix-dev/community/dawarich/migrations/set_default_postgis_image @@ -0,0 +1,20 @@ +#!/usr/bin/python3 + +import os +import sys +import yaml + + +def migrate(values): + if not values["dawarich"].get("postgres_image_selector"): + values["dawarich"]["postgres_image_selector"] = "postgis_17_image" + return values + + +if __name__ == "__main__": + if len(sys.argv) != 2: + exit(1) + + if os.path.exists(sys.argv[1]): + with open(sys.argv[1], "r") as f: + print(yaml.dump(migrate(yaml.safe_load(f.read())))) diff --git a/ix-dev/community/dawarich/questions.yaml b/ix-dev/community/dawarich/questions.yaml index d429094993..bc2c4e5d3d 100644 --- a/ix-dev/community/dawarich/questions.yaml +++ b/ix-dev/community/dawarich/questions.yaml @@ -26,6 +26,24 @@ questions: schema: type: dict attrs: + - variable: postgres_image_selector + label: Postgres Image (CAUTION) + description: | + If you are changing this after the postgres directory has been initialized,
+ STOP! and make sure you have a backup of your data.
+ Changing this will trigger an one way database upgrade.
+ You can only select newer versions of postgres.
+ Selecting an older version will refuse to start.
+ If something goes wrong, you will have to restore from backup. + schema: + type: string + default: postgis_18_image + required: true + enum: + - value: postgis_17_image + description: Postgres 17 + - value: postgis_18_image + description: Postgres 18 - variable: db_password label: Database Password description: The password for Dawarich. diff --git a/ix-dev/community/dawarich/templates/docker-compose.yaml b/ix-dev/community/dawarich/templates/docker-compose.yaml index 375b5e44f2..6aae9a8615 100644 --- a/ix-dev/community/dawarich/templates/docker-compose.yaml +++ b/ix-dev/community/dawarich/templates/docker-compose.yaml @@ -12,7 +12,7 @@ "database": values.consts.db_name, "volume": values.storage.postgres_data, } %} -{% set postgis = tpl.deps.postgres(values.consts.postgis_container_name, "postgis_image", pg_config, perm_container) %} +{% set postgis = tpl.deps.postgres(values.consts.postgis_container_name, values.dawarich.postgres_image_selector, pg_config, perm_container) %} {# Redis #} {% set redis_config = { diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/__init__.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/__init__.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/__init__.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/__init__.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/client.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/client.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/client.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/client.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/configs.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/configs.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/configs.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/configs.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/container.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/container.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/container.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/container.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/depends.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/depends.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/depends.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/depends.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/deploy.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/deploy.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/deploy.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/deploy.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/deps.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/deps.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/deps.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/deps.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/deps_elastic.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/deps_elastic.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/deps_elastic.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/deps_elastic.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/deps_mariadb.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/deps_mariadb.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/deps_mariadb.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/deps_mariadb.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/deps_meilisearch.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/deps_meilisearch.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/deps_meilisearch.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/deps_meilisearch.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/deps_mongodb.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/deps_mongodb.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/deps_mongodb.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/deps_mongodb.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/deps_perms.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/deps_perms.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/deps_perms.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/deps_perms.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/deps_postgres.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/deps_postgres.py similarity index 94% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/deps_postgres.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/deps_postgres.py index 8269990377..1e6f7471c8 100644 --- a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/deps_postgres.py +++ b/ix-dev/community/dawarich/templates/library/base_v2_1_66/deps_postgres.py @@ -34,6 +34,11 @@ SUPPORTED_REPOS = [ "pgvector/pgvector", "ghcr.io/immich-app/postgres", ] +SUPPORTED_UPGRADE_REPOS = [ + "postgres", + "postgis/postgis", + "pgvector/pgvector", +] def get_major_version(variant: str, tag: str): @@ -52,15 +57,16 @@ def get_major_version(variant: str, tag: str): return x.split("-")[0] elif variant == "pgvector/pgvector": - # 0.8.1-pg17 - regex = re.compile(r"^\d+\.\d+\.\d+\-pg\d+") + # 0.8.1-pg17-trixie + regex = re.compile(r"^\d+\.\d+\.\d+\-pg\d+(\-\w+)?") def oper(x): - return x.split("-")[1].lstrip("pg") + parts = x.split("-") + return parts[1].lstrip("pg") elif variant == "ghcr.io/immich-app/postgres": - # 15-vectorchord0.4.3-pgvectors0.2.0 - regex = re.compile(r"^\d+\-vectorchord\d+\.\d+\.\d+(\-pgvectors?\d+\.\d+\.\d+)?") + # 15-vectorchord0.4.3 + regex = re.compile(r"^\d+\-vectorchord\d+\.\d+\.\d+") def oper(x): return x.split("-")[0] @@ -113,7 +119,7 @@ class PostgresContainer: # eg we don't want to handle upgrades of pg_vector or immich at the moment repo = self._get_repo(image) - if repo == "postgres": + if repo in SUPPORTED_UPGRADE_REPOS: self._data_dir = "/var/lib/postgresql" target_major_version = self._get_target_version(image) # This is the new format upstream Postgres uses/suggests. diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/deps_redis.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/deps_redis.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/deps_redis.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/deps_redis.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/deps_solr.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/deps_solr.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/deps_solr.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/deps_solr.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/deps_tika.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/deps_tika.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/deps_tika.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/deps_tika.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/device.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/device.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/device.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/device.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/device_cgroup_rules.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/device_cgroup_rules.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/device_cgroup_rules.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/device_cgroup_rules.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/devices.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/devices.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/devices.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/devices.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/dns.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/dns.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/dns.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/dns.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/environment.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/environment.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/environment.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/environment.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/error.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/error.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/error.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/error.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/expose.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/expose.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/expose.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/expose.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/extra_hosts.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/extra_hosts.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/extra_hosts.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/extra_hosts.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/formatter.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/formatter.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/formatter.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/formatter.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/functions.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/functions.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/functions.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/functions.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/healthcheck.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/healthcheck.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/healthcheck.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/healthcheck.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/labels.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/labels.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/labels.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/labels.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/notes.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/notes.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/notes.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/notes.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/portals.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/portals.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/portals.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/portals.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/ports.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/ports.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/ports.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/ports.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/render.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/render.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/render.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/render.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/resources.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/resources.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/resources.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/resources.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/restart.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/restart.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/restart.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/restart.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/security_opts.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/security_opts.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/security_opts.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/security_opts.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/storage.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/storage.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/storage.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/storage.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/sysctls.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/sysctls.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/sysctls.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/sysctls.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/__init__.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/__init__.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/__init__.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/__init__.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_build_image.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_build_image.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_build_image.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_build_image.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_configs.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_configs.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_configs.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_configs.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_container.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_container.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_container.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_container.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_depends.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_depends.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_depends.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_depends.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_deps.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_deps.py similarity index 99% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_deps.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_deps.py index 2792798b03..197486537a 100644 --- a/ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_deps.py +++ b/ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_deps.py @@ -537,7 +537,10 @@ def test_add_postgres_with_invalid_tag(mock_values): def test_no_upgrade_container_with_non_postgres_image(mock_values): - mock_values["images"]["postgres_image"] = {"repository": "pgvector/pgvector", "tag": "0.8.1-pg17"} + mock_values["images"]["postgres_image"] = { + "repository": "ghcr.io/immich-app/postgres", + "tag": "15-vectorchord0.4.3-pgvectors0.2.0", + } render = Render(mock_values) c1 = render.add_container("test_container", "test_image") c1.healthcheck.disable() @@ -605,7 +608,7 @@ def test_postgres_with_upgrade_container(mock_values): def test_add_mongodb(mock_values): - mock_values["images"]["mongodb_image"] = {"repository": "mongodb", "tag": "latest"} + mock_values["images"]["mongodb_image"] = {"repository": "mongo", "tag": "latest"} render = Render(mock_values) c1 = render.add_container("test_container", "test_image") c1.healthcheck.disable() @@ -627,7 +630,7 @@ def test_add_mongodb(mock_values): output = render.render() assert "devices" not in output["services"]["mongodb_container"] assert "reservations" not in output["services"]["mongodb_container"]["deploy"]["resources"] - assert output["services"]["mongodb_container"]["image"] == "mongodb:latest" + assert output["services"]["mongodb_container"]["image"] == "mongo:latest" assert output["services"]["mongodb_container"]["user"] == "568:568" assert output["services"]["mongodb_container"]["deploy"]["resources"]["limits"]["cpus"] == "2.0" assert output["services"]["mongodb_container"]["deploy"]["resources"]["limits"]["memory"] == "4096M" @@ -781,7 +784,7 @@ def test_add_meilisearch_unsupported_repo(mock_values): def test_add_elasticsearch(mock_values): mock_values["images"]["elastic_image"] = { - "repository": "docker.elastic.co/elasticsearch/elasticsearch", + "repository": "elasticsearch", "tag": "9.1.2", } render = Render(mock_values) @@ -804,7 +807,7 @@ def test_add_elasticsearch(mock_values): output = render.render() assert "devices" not in output["services"]["elastic_container"] assert "reservations" not in output["services"]["elastic_container"]["deploy"]["resources"] - assert output["services"]["elastic_container"]["image"] == "docker.elastic.co/elasticsearch/elasticsearch:9.1.2" + assert output["services"]["elastic_container"]["image"] == "elasticsearch:9.1.2" assert output["services"]["elastic_container"]["user"] == "1000:1000" assert output["services"]["elastic_container"]["deploy"]["resources"]["limits"]["cpus"] == "2.0" assert output["services"]["elastic_container"]["deploy"]["resources"]["limits"]["memory"] == "4096M" diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_device.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_device.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_device.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_device.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_device_cgroup_rules.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_device_cgroup_rules.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_device_cgroup_rules.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_device_cgroup_rules.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_dns.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_dns.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_dns.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_dns.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_environment.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_environment.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_environment.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_environment.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_expose.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_expose.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_expose.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_expose.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_extra_hosts.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_extra_hosts.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_extra_hosts.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_extra_hosts.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_formatter.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_formatter.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_formatter.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_formatter.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_functions.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_functions.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_functions.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_functions.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_healthcheck.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_healthcheck.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_healthcheck.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_healthcheck.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_labels.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_labels.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_labels.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_labels.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_notes.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_notes.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_notes.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_notes.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_portal.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_portal.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_portal.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_portal.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_ports.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_ports.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_ports.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_ports.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_render.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_render.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_render.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_render.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_resources.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_resources.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_resources.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_resources.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_restart.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_restart.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_restart.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_restart.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_security_opts.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_security_opts.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_security_opts.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_security_opts.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_sysctls.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_sysctls.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_sysctls.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_sysctls.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_validations.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_validations.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_validations.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_validations.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_volumes.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_volumes.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/tests/test_volumes.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/tests/test_volumes.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/tmpfs.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/tmpfs.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/tmpfs.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/tmpfs.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/validations.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/validations.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/validations.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/validations.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/volume_mount.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/volume_mount.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/volume_mount.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/volume_mount.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/volume_mount_types.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/volume_mount_types.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/volume_mount_types.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/volume_mount_types.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/volume_sources.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/volume_sources.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/volume_sources.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/volume_sources.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/volume_types.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/volume_types.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/volume_types.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/volume_types.py diff --git a/ix-dev/community/dawarich/templates/library/base_v2_1_65/volumes.py b/ix-dev/community/dawarich/templates/library/base_v2_1_66/volumes.py similarity index 100% rename from ix-dev/community/dawarich/templates/library/base_v2_1_65/volumes.py rename to ix-dev/community/dawarich/templates/library/base_v2_1_66/volumes.py diff --git a/ix-dev/community/dawarich/templates/test_values/basic-values.yaml b/ix-dev/community/dawarich/templates/test_values/basic-values.yaml index 2f257ab664..ba8c6eecf1 100644 --- a/ix-dev/community/dawarich/templates/test_values/basic-values.yaml +++ b/ix-dev/community/dawarich/templates/test_values/basic-values.yaml @@ -6,6 +6,7 @@ resources: TZ: Etc/UTC dawarich: + postgres_image_selector: postgis_18_image db_password: secret redis_password: secret application_hosts: diff --git a/ix-dev/community/librechat/app.yaml b/ix-dev/community/librechat/app.yaml index 7bdcc4d89c..9924fa6815 100644 --- a/ix-dev/community/librechat/app.yaml +++ b/ix-dev/community/librechat/app.yaml @@ -15,8 +15,8 @@ keywords: - ai - librechat - open-source -lib_version: 2.1.65 -lib_version_hash: f92a9ee78c78fc77f86e7d8b545bd4c605c31c599e2c5da59f1615aa516cb8b5 +lib_version: 2.1.66 +lib_version_hash: 986abcd60fd0cc6277c80d55d2798356ddda1bd6348580ca7198b003571707fa maintainers: - email: dev@truenas.com name: truenas @@ -48,4 +48,4 @@ sources: - https://github.com/LibreChat/LibreChat title: LibreChat train: community -version: 1.0.15 +version: 1.0.16 diff --git a/ix-dev/community/librechat/ix_values.yaml b/ix-dev/community/librechat/ix_values.yaml index fc7aa66c42..09c3d3f093 100644 --- a/ix-dev/community/librechat/ix_values.yaml +++ b/ix-dev/community/librechat/ix_values.yaml @@ -17,9 +17,12 @@ images: postgres_17_image: repository: pgvector/pgvector tag: 0.8.1-pg17 + postgres_18_image: + repository: pgvector/pgvector + tag: 0.8.1-pg18-trixie postgres_upgrade_image: repository: ixsystems/postgres-upgrade - tag: 1.1.2 + tag: 1.1.3 consts: librechat_container_name: librechat diff --git a/ix-dev/community/librechat/questions.yaml b/ix-dev/community/librechat/questions.yaml index 1750a4899c..377b2dde28 100644 --- a/ix-dev/community/librechat/questions.yaml +++ b/ix-dev/community/librechat/questions.yaml @@ -39,11 +39,13 @@ questions: If something goes wrong, you will have to restore from backup. schema: type: string - default: postgres_17_image + default: postgres_18_image required: true enum: - value: postgres_17_image description: Postgres 17 + - value: postgres_18_image + description: Postgres 18 - variable: pg_db_password label: Postgres Database Password schema: diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/__init__.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/__init__.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/__init__.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/__init__.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/client.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/client.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/client.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/client.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/configs.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/configs.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/configs.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/configs.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/container.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/container.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/container.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/container.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/depends.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/depends.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/depends.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/depends.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/deploy.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/deploy.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/deploy.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/deploy.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/deps.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/deps.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/deps.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/deps.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/deps_elastic.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/deps_elastic.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/deps_elastic.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/deps_elastic.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/deps_mariadb.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/deps_mariadb.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/deps_mariadb.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/deps_mariadb.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/deps_meilisearch.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/deps_meilisearch.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/deps_meilisearch.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/deps_meilisearch.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/deps_mongodb.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/deps_mongodb.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/deps_mongodb.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/deps_mongodb.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/deps_perms.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/deps_perms.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/deps_perms.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/deps_perms.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/deps_postgres.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/deps_postgres.py similarity index 94% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/deps_postgres.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/deps_postgres.py index 8269990377..1e6f7471c8 100644 --- a/ix-dev/community/librechat/templates/library/base_v2_1_65/deps_postgres.py +++ b/ix-dev/community/librechat/templates/library/base_v2_1_66/deps_postgres.py @@ -34,6 +34,11 @@ SUPPORTED_REPOS = [ "pgvector/pgvector", "ghcr.io/immich-app/postgres", ] +SUPPORTED_UPGRADE_REPOS = [ + "postgres", + "postgis/postgis", + "pgvector/pgvector", +] def get_major_version(variant: str, tag: str): @@ -52,15 +57,16 @@ def get_major_version(variant: str, tag: str): return x.split("-")[0] elif variant == "pgvector/pgvector": - # 0.8.1-pg17 - regex = re.compile(r"^\d+\.\d+\.\d+\-pg\d+") + # 0.8.1-pg17-trixie + regex = re.compile(r"^\d+\.\d+\.\d+\-pg\d+(\-\w+)?") def oper(x): - return x.split("-")[1].lstrip("pg") + parts = x.split("-") + return parts[1].lstrip("pg") elif variant == "ghcr.io/immich-app/postgres": - # 15-vectorchord0.4.3-pgvectors0.2.0 - regex = re.compile(r"^\d+\-vectorchord\d+\.\d+\.\d+(\-pgvectors?\d+\.\d+\.\d+)?") + # 15-vectorchord0.4.3 + regex = re.compile(r"^\d+\-vectorchord\d+\.\d+\.\d+") def oper(x): return x.split("-")[0] @@ -113,7 +119,7 @@ class PostgresContainer: # eg we don't want to handle upgrades of pg_vector or immich at the moment repo = self._get_repo(image) - if repo == "postgres": + if repo in SUPPORTED_UPGRADE_REPOS: self._data_dir = "/var/lib/postgresql" target_major_version = self._get_target_version(image) # This is the new format upstream Postgres uses/suggests. diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/deps_redis.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/deps_redis.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/deps_redis.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/deps_redis.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/deps_solr.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/deps_solr.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/deps_solr.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/deps_solr.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/deps_tika.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/deps_tika.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/deps_tika.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/deps_tika.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/device.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/device.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/device.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/device.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/device_cgroup_rules.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/device_cgroup_rules.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/device_cgroup_rules.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/device_cgroup_rules.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/devices.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/devices.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/devices.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/devices.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/dns.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/dns.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/dns.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/dns.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/environment.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/environment.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/environment.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/environment.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/error.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/error.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/error.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/error.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/expose.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/expose.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/expose.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/expose.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/extra_hosts.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/extra_hosts.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/extra_hosts.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/extra_hosts.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/formatter.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/formatter.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/formatter.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/formatter.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/functions.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/functions.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/functions.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/functions.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/healthcheck.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/healthcheck.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/healthcheck.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/healthcheck.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/labels.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/labels.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/labels.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/labels.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/notes.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/notes.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/notes.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/notes.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/portals.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/portals.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/portals.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/portals.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/ports.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/ports.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/ports.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/ports.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/render.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/render.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/render.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/render.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/resources.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/resources.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/resources.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/resources.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/restart.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/restart.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/restart.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/restart.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/security_opts.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/security_opts.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/security_opts.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/security_opts.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/storage.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/storage.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/storage.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/storage.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/sysctls.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/sysctls.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/sysctls.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/sysctls.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/tests/__init__.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/tests/__init__.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/tests/__init__.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/tests/__init__.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_build_image.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_build_image.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_build_image.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_build_image.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_configs.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_configs.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_configs.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_configs.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_container.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_container.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_container.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_container.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_depends.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_depends.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_depends.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_depends.py diff --git a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_deps.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_deps.py similarity index 99% rename from ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_deps.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_deps.py index 2792798b03..197486537a 100644 --- a/ix-dev/community/chatwoot/templates/library/base_v2_1_65/tests/test_deps.py +++ b/ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_deps.py @@ -537,7 +537,10 @@ def test_add_postgres_with_invalid_tag(mock_values): def test_no_upgrade_container_with_non_postgres_image(mock_values): - mock_values["images"]["postgres_image"] = {"repository": "pgvector/pgvector", "tag": "0.8.1-pg17"} + mock_values["images"]["postgres_image"] = { + "repository": "ghcr.io/immich-app/postgres", + "tag": "15-vectorchord0.4.3-pgvectors0.2.0", + } render = Render(mock_values) c1 = render.add_container("test_container", "test_image") c1.healthcheck.disable() @@ -605,7 +608,7 @@ def test_postgres_with_upgrade_container(mock_values): def test_add_mongodb(mock_values): - mock_values["images"]["mongodb_image"] = {"repository": "mongodb", "tag": "latest"} + mock_values["images"]["mongodb_image"] = {"repository": "mongo", "tag": "latest"} render = Render(mock_values) c1 = render.add_container("test_container", "test_image") c1.healthcheck.disable() @@ -627,7 +630,7 @@ def test_add_mongodb(mock_values): output = render.render() assert "devices" not in output["services"]["mongodb_container"] assert "reservations" not in output["services"]["mongodb_container"]["deploy"]["resources"] - assert output["services"]["mongodb_container"]["image"] == "mongodb:latest" + assert output["services"]["mongodb_container"]["image"] == "mongo:latest" assert output["services"]["mongodb_container"]["user"] == "568:568" assert output["services"]["mongodb_container"]["deploy"]["resources"]["limits"]["cpus"] == "2.0" assert output["services"]["mongodb_container"]["deploy"]["resources"]["limits"]["memory"] == "4096M" @@ -781,7 +784,7 @@ def test_add_meilisearch_unsupported_repo(mock_values): def test_add_elasticsearch(mock_values): mock_values["images"]["elastic_image"] = { - "repository": "docker.elastic.co/elasticsearch/elasticsearch", + "repository": "elasticsearch", "tag": "9.1.2", } render = Render(mock_values) @@ -804,7 +807,7 @@ def test_add_elasticsearch(mock_values): output = render.render() assert "devices" not in output["services"]["elastic_container"] assert "reservations" not in output["services"]["elastic_container"]["deploy"]["resources"] - assert output["services"]["elastic_container"]["image"] == "docker.elastic.co/elasticsearch/elasticsearch:9.1.2" + assert output["services"]["elastic_container"]["image"] == "elasticsearch:9.1.2" assert output["services"]["elastic_container"]["user"] == "1000:1000" assert output["services"]["elastic_container"]["deploy"]["resources"]["limits"]["cpus"] == "2.0" assert output["services"]["elastic_container"]["deploy"]["resources"]["limits"]["memory"] == "4096M" diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_device.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_device.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_device.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_device.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_device_cgroup_rules.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_device_cgroup_rules.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_device_cgroup_rules.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_device_cgroup_rules.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_dns.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_dns.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_dns.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_dns.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_environment.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_environment.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_environment.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_environment.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_expose.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_expose.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_expose.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_expose.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_extra_hosts.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_extra_hosts.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_extra_hosts.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_extra_hosts.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_formatter.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_formatter.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_formatter.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_formatter.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_functions.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_functions.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_functions.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_functions.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_healthcheck.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_healthcheck.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_healthcheck.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_healthcheck.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_labels.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_labels.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_labels.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_labels.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_notes.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_notes.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_notes.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_notes.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_portal.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_portal.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_portal.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_portal.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_ports.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_ports.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_ports.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_ports.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_render.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_render.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_render.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_render.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_resources.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_resources.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_resources.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_resources.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_restart.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_restart.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_restart.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_restart.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_security_opts.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_security_opts.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_security_opts.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_security_opts.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_sysctls.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_sysctls.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_sysctls.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_sysctls.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_validations.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_validations.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_validations.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_validations.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_volumes.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_volumes.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/tests/test_volumes.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/tests/test_volumes.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/tmpfs.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/tmpfs.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/tmpfs.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/tmpfs.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/validations.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/validations.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/validations.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/validations.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/volume_mount.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/volume_mount.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/volume_mount.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/volume_mount.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/volume_mount_types.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/volume_mount_types.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/volume_mount_types.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/volume_mount_types.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/volume_sources.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/volume_sources.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/volume_sources.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/volume_sources.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/volume_types.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/volume_types.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/volume_types.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/volume_types.py diff --git a/ix-dev/community/librechat/templates/library/base_v2_1_65/volumes.py b/ix-dev/community/librechat/templates/library/base_v2_1_66/volumes.py similarity index 100% rename from ix-dev/community/librechat/templates/library/base_v2_1_65/volumes.py rename to ix-dev/community/librechat/templates/library/base_v2_1_66/volumes.py diff --git a/ix-dev/community/librechat/templates/test_values/basic-values.yaml b/ix-dev/community/librechat/templates/test_values/basic-values.yaml index 2cd577448a..e72cc986ef 100644 --- a/ix-dev/community/librechat/templates/test_values/basic-values.yaml +++ b/ix-dev/community/librechat/templates/test_values/basic-values.yaml @@ -4,7 +4,7 @@ resources: memory: 4096 librechat: - postgres_image_selector: postgres_17_image + postgres_image_selector: postgres_18_image pg_db_password: secret mongo_db_password: secret meilisearch_master_key: secret diff --git a/library/2.1.65/deps_postgres.py b/library/2.1.65/deps_postgres.py deleted file mode 100644 index 8269990377..0000000000 --- a/library/2.1.65/deps_postgres.py +++ /dev/null @@ -1,214 +0,0 @@ -import re -import urllib.parse -from typing import TYPE_CHECKING, TypedDict, NotRequired - - -if TYPE_CHECKING: - from render import Render - from storage import IxStorage - - -try: - from .error import RenderError - from .deps_perms import PermsContainer - from .validations import valid_port_or_raise -except ImportError: - from error import RenderError - from deps_perms import PermsContainer - from validations import valid_port_or_raise - - -class PostgresConfig(TypedDict): - user: str - password: str - database: str - port: NotRequired[int] - volume: "IxStorage" - additional_options: NotRequired[dict[str, str]] - - -MAX_POSTGRES_VERSION = 18 -SUPPORTED_REPOS = [ - "postgres", - "postgis/postgis", - "pgvector/pgvector", - "ghcr.io/immich-app/postgres", -] - - -def get_major_version(variant: str, tag: str): - if variant == "postgres": - # 17.7-bookworm - regex = re.compile(r"^\d+\.\d+-\w+") - - def oper(x): - return x.split(".")[0] - - elif variant == "postgis/postgis": - # 17-3.5 - regex = re.compile(r"^\d+\-\d+\.\d+") - - def oper(x): - return x.split("-")[0] - - elif variant == "pgvector/pgvector": - # 0.8.1-pg17 - regex = re.compile(r"^\d+\.\d+\.\d+\-pg\d+") - - def oper(x): - return x.split("-")[1].lstrip("pg") - - elif variant == "ghcr.io/immich-app/postgres": - # 15-vectorchord0.4.3-pgvectors0.2.0 - regex = re.compile(r"^\d+\-vectorchord\d+\.\d+\.\d+(\-pgvectors?\d+\.\d+\.\d+)?") - - def oper(x): - return x.split("-")[0] - - if not regex.match(tag): - raise RenderError(f"Could not determine major version from tag [{tag}] for variant [{variant}]") - - return oper(tag) - - -class PostgresContainer: - def __init__( - self, render_instance: "Render", name: str, image: str, config: PostgresConfig, perms_instance: PermsContainer - ): - self._render_instance = render_instance - self._name = name - self._config = config - self._data_dir = None - self._upgrade_name = f"{self._name}_upgrade" - self._upgrade_container = None - - for key in ("user", "password", "database", "volume"): - if key not in config: - raise RenderError(f"Expected [{key}] to be set for postgres") - - port = valid_port_or_raise(self.get_port()) - - # TODO: Set some defaults for ZFS Optimizations (Need to check if applies on updates) - # https://vadosware.io/post/everything-ive-seen-on-optimizing-postgres-on-zfs-on-linux/ - - opts = [] - for k, v in config.get("additional_options", {}).items(): - opts.extend(["-c", f"{k}={v}"]) - - common_variables = { - "POSTGRES_USER": config["user"], - "POSTGRES_PASSWORD": config["password"], - "POSTGRES_DB": config["database"], - "PGPORT": port, - } - - c = self._render_instance.add_container(name, image) - c.healthcheck.set_test("postgres", {"user": config["user"], "db": config["database"]}) - c.set_shm_size_mb(256) - - if opts: - c.set_command(opts) - - containers = [c] - - # eg we don't want to handle upgrades of pg_vector or immich at the moment - repo = self._get_repo(image) - if repo == "postgres": - self._data_dir = "/var/lib/postgresql" - target_major_version = self._get_target_version(image) - # This is the new format upstream Postgres uses/suggests. - # E.g., for Postgres 17, the data dir is /var/lib/postgresql/17/docker - common_variables.update({"PGDATA": f"{self._data_dir}/{target_major_version}/docker"}) - - upg = self._render_instance.add_container(self._upgrade_name, "postgres_upgrade_image") - - self._upgrade_container = upg - containers.append(upg) - - upg.set_entrypoint(["/bin/bash", "-c", "/upgrade.sh"]) - upg.restart.set_policy("on-failure", 1) - upg.healthcheck.disable() - upg.setup_as_helper(profile="medium") - upg.environment.add_env("TARGET_VERSION", target_major_version) - - c.depends.add_dependency(self._upgrade_name, "service_completed_successfully") - else: - self._data_dir = "/var/lib/postgresql/data" - - for container in containers: - # TODO: We can now use 568:568 (or any user/group). - # Need to first plan a migration path for the existing users. - container.set_user(999, 999) - container.remove_devices() - container.add_storage(self._data_dir, config["volume"]) - for k, v in common_variables.items(): - container.environment.add_env(k, v) - - perms_instance.add_or_skip_action( - f"{self._name}_postgres_data", config["volume"], {"uid": 999, "gid": 999, "mode": "check"} - ) - - # Store container for further configuration - # For example: c.depends.add_dependency("other_container", "service_started") - self._container = c - - @property - def container(self): - return self._container - - def add_dependency(self, container_name: str, condition: str): - self._container.depends.add_dependency(container_name, condition) - if self._upgrade_container: - self._upgrade_container.depends.add_dependency(container_name, condition) - - def _get_repo(self, image): - images = self._render_instance.values["images"] - if image not in images: - raise RenderError(f"Image [{image}] not found in values. Available images: [{', '.join(images.keys())}]") - repo = images[image].get("repository") - if not repo: - raise RenderError("Could not determine repo") - if repo not in SUPPORTED_REPOS: - raise RenderError(f"Unsupported repo [{repo}] for postgres. Supported repos: {', '.join(SUPPORTED_REPOS)}") - return repo - - def _get_target_version(self, image): - repo = self._get_repo(image) - images = self._render_instance.values["images"] - if image not in images: - raise RenderError(f"Image [{image}] not found in values. Available images: [{', '.join(images.keys())}]") - tag = str(images[image].get("tag", "")) - target_major_version = get_major_version(repo, tag) - - try: - # Make sure we end up with an integer - target_major_version = int(target_major_version) - except ValueError: - raise RenderError(f"Could not determine target major version from tag [{tag}]") - - if target_major_version > MAX_POSTGRES_VERSION: - raise RenderError(f"Postgres version [{target_major_version}] is not supported") - - return target_major_version - - def get_port(self): - return self._config.get("port") or 5432 - - def get_url(self, variant: str): - user = urllib.parse.quote_plus(self._config["user"]) - password = urllib.parse.quote_plus(self._config["password"]) - creds = f"{user}:{password}" - addr = f"{self._name}:{self.get_port()}" - db = self._config["database"] - - urls = { - "postgres": f"postgres://{creds}@{addr}/{db}?sslmode=disable", - "postgresql": f"postgresql://{creds}@{addr}/{db}?sslmode=disable", - "postgresql_no_creds": f"postgresql://{addr}/{db}?sslmode=disable", - "jdbc": f"jdbc:postgresql://{addr}/{db}", - "host_port": addr, - } - - if variant not in urls: - raise RenderError(f"Expected [variant] to be one of [{', '.join(urls.keys())}], got [{variant}]") - return urls[variant] diff --git a/library/2.1.65/tests/test_deps.py b/library/2.1.65/tests/test_deps.py deleted file mode 100644 index 2792798b03..0000000000 --- a/library/2.1.65/tests/test_deps.py +++ /dev/null @@ -1,1018 +0,0 @@ -import json -import pytest - -from render import Render - - -@pytest.fixture -def mock_values(): - return { - "images": { - "test_image": { - "repository": "nginx", - "tag": "latest", - }, - "container_utils_image": { - "repository": "ixsystems/container-utils", - "tag": "1.0.0", - }, - "postgres_upgrade_image": { - "repository": "ixsystems/postgres-upgrade", - "tag": "1.0.0", - }, - }, - } - - -def test_add_postgres_missing_config(mock_values): - render = Render(mock_values) - c1 = render.add_container("test_container", "test_image") - c1.healthcheck.disable() - with pytest.raises(Exception): - render.deps.postgres( - "pg_container", - "test_image", - {"user": "test_user", "password": "test_password", "database": "test_database"}, # type: ignore - ) - - -def test_add_postgres_unsupported_repo(mock_values): - mock_values["images"]["pg_image"] = {"repository": "unsupported_repo", "tag": "16.6-bookworm"} - render = Render(mock_values) - c1 = render.add_container("test_container", "test_image") - c1.healthcheck.disable() - perms_container = render.deps.perms("perms_container") - with pytest.raises(Exception): - render.deps.postgres( - "pg_container", - "pg_image", - { - "user": "test_user", - "password": "test_@password", - "database": "test_database", - "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, - }, - perms_container, - ) - - -def test_add_postgres(mock_values): - mock_values["images"]["pg_image"] = {"repository": "postgres", "tag": "16.6-bookworm"} - render = Render(mock_values) - c1 = render.add_container("test_container", "test_image") - c1.healthcheck.disable() - perms_container = render.deps.perms("perms_container") - p = render.deps.postgres( - "pg_container", - "pg_image", - { - "user": "test_user", - "password": "test_@password", - "database": "test_database", - "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, - }, - perms_container, - ) - if perms_container.has_actions(): - perms_container.activate() - p.container.depends.add_dependency("perms_container", "service_completed_successfully") - output = render.render() - assert ( - p.get_url("postgres") == "postgres://test_user:test_%40password@pg_container:5432/test_database?sslmode=disable" - ) - assert "devices" not in output["services"]["pg_container"] - assert "reservations" not in output["services"]["pg_container"]["deploy"]["resources"] - assert output["services"]["pg_container"]["image"] == "postgres:16.6-bookworm" - assert output["services"]["pg_container"]["user"] == "999:999" - assert output["services"]["pg_container"]["deploy"]["resources"]["limits"]["cpus"] == "2.0" - assert output["services"]["pg_container"]["deploy"]["resources"]["limits"]["memory"] == "4096M" - assert output["services"]["pg_container"]["healthcheck"] == { - "test": [ - "CMD", - "pg_isready", - "-h", - "127.0.0.1", - "-p", - "5432", - "-U", - "test_user", - "-d", - "test_database", - ], - "interval": "30s", - "timeout": "5s", - "retries": 5, - "start_period": "15s", - "start_interval": "2s", - } - assert output["services"]["pg_container"]["volumes"] == [ - { - "type": "volume", - "source": "test_volume", - "target": "/var/lib/postgresql", - "read_only": False, - "volume": {"nocopy": False}, - } - ] - assert output["services"]["pg_container"]["environment"] == { - "TZ": "Etc/UTC", - "UMASK": "002", - "UMASK_SET": "002", - "NVIDIA_VISIBLE_DEVICES": "void", - "POSTGRES_USER": "test_user", - "POSTGRES_PASSWORD": "test_@password", - "POSTGRES_DB": "test_database", - "PGPORT": "5432", - "PGDATA": "/var/lib/postgresql/16/docker", - } - assert output["services"]["pg_container"]["depends_on"] == { - "perms_container": {"condition": "service_completed_successfully"}, - "pg_container_upgrade": {"condition": "service_completed_successfully"}, - } - assert output["services"]["perms_container"]["restart"] == "on-failure:1" - - -def test_add_postgres_options(mock_values): - mock_values["images"]["pg_image"] = {"repository": "postgres", "tag": "16.6-bookworm"} - render = Render(mock_values) - c1 = render.add_container("test_container", "test_image") - c1.healthcheck.disable() - perms_container = render.deps.perms("perms_container") - render.deps.postgres( - "pg_container", - "pg_image", - { - "user": "test_user", - "password": "test_@password", - "database": "test_database", - "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, - "additional_options": {"maintenance_work_mem": "1024MB", "max_connections": "100"}, - }, - perms_container, - ) - - output = render.render() - assert output["services"]["pg_container"]["command"] == [ - "-c", - "maintenance_work_mem=1024MB", - "-c", - "max_connections=100", - ] - - -def test_add_redis_missing_config(mock_values): - render = Render(mock_values) - c1 = render.add_container("test_container", "test_image") - c1.healthcheck.disable() - with pytest.raises(Exception): - render.deps.redis( - "redis_container", - "test_image", - {"password": "test_password", "volume": {}}, # type: ignore - ) - - -def test_add_redis_unsupported_repo(mock_values): - mock_values["images"]["redis_image"] = {"repository": "unsupported_repo", "tag": "latest"} - render = Render(mock_values) - c1 = render.add_container("test_container", "test_image") - c1.healthcheck.disable() - perms_container = render.deps.perms("perms_container") - with pytest.raises(Exception): - render.deps.redis( - "redis_container", - "redis_image", - { - "password": "test&password@", - "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, - }, - perms_container, - ) - - -def test_add_redis_with_password_with_spaces(mock_values): - mock_values["images"]["redis_image"] = {"repository": "redis", "tag": "latest"} - render = Render(mock_values) - c1 = render.add_container("test_container", "test_image") - c1.healthcheck.disable() - with pytest.raises(Exception): - render.deps.redis( - "redis_container", - "redis_image", - {"password": "test password", "volume": {}}, # type: ignore - ) - - -def test_add_redis(mock_values): - mock_values["images"]["redis_image"] = {"repository": "valkey/valkey", "tag": "latest"} - mock_values["run_as"] = {"user": 0, "group": 0} - render = Render(mock_values) - c1 = render.add_container("test_container", "test_image") - c1.healthcheck.disable() - perms_container = render.deps.perms("perms_container") - r = render.deps.redis( - "redis_container", - "redis_image", - { - "password": "test&password@", - "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, - }, - perms_container, - ) - c1.environment.add_env("REDIS_URL", r.get_url("redis")) - if perms_container.has_actions(): - perms_container.activate() - r.container.depends.add_dependency("perms_container", "service_completed_successfully") - output = render.render() - assert "devices" not in output["services"]["redis_container"] - assert "reservations" not in output["services"]["redis_container"]["deploy"]["resources"] - assert ( - output["services"]["test_container"]["environment"]["REDIS_URL"] - == "redis://default:test%26password%40@redis_container:6379" - ) - assert output["services"]["redis_container"]["image"] == "valkey/valkey:latest" - assert output["services"]["redis_container"]["user"] == "568:568" - assert output["services"]["redis_container"]["deploy"]["resources"]["limits"]["cpus"] == "2.0" - assert output["services"]["redis_container"]["deploy"]["resources"]["limits"]["memory"] == "4096M" - assert output["services"]["redis_container"]["healthcheck"] == { - "test": [ - "CMD", - "redis-cli", - "-h", - "127.0.0.1", - "-p", - "6379", - "-a", - "test&password@", - "ping", - ], - "interval": "30s", - "timeout": "5s", - "retries": 5, - "start_period": "15s", - "start_interval": "2s", - } - assert output["services"]["redis_container"]["volumes"] == [ - { - "type": "volume", - "source": "test_volume", - "target": "/data", - "read_only": False, - "volume": {"nocopy": False}, - } - ] - assert output["services"]["redis_container"]["environment"] == { - "TZ": "Etc/UTC", - "UMASK": "002", - "UMASK_SET": "002", - "NVIDIA_VISIBLE_DEVICES": "void", - "REDIS_PASSWORD": "test&password@", - } - assert output["services"]["redis_container"]["depends_on"] == { - "perms_container": {"condition": "service_completed_successfully"} - } - - -def test_add_mariadb_missing_config(mock_values): - render = Render(mock_values) - c1 = render.add_container("test_container", "test_image") - c1.healthcheck.disable() - with pytest.raises(Exception): - render.deps.mariadb( - "mariadb_container", - "test_image", - {"user": "test_user", "password": "test_password", "database": "test_database"}, # type: ignore - ) - - -def test_add_mariadb_unsupported_repo(mock_values): - mock_values["images"]["mariadb_image"] = {"repository": "unsupported_repo", "tag": "latest"} - render = Render(mock_values) - c1 = render.add_container("test_container", "test_image") - c1.healthcheck.disable() - perms_container = render.deps.perms("perms_container") - with pytest.raises(Exception): - render.deps.mariadb( - "mariadb_container", - "mariadb_image", - { - "user": "test_user", - "password": "test_password", - "database": "test_database", - "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, - }, - perms_container, - ) - - -def test_add_mariadb(mock_values): - mock_values["images"]["mariadb_image"] = {"repository": "mariadb", "tag": "latest"} - render = Render(mock_values) - c1 = render.add_container("test_container", "test_image") - c1.healthcheck.disable() - perms_container = render.deps.perms("perms_container") - m = render.deps.mariadb( - "mariadb_container", - "mariadb_image", - { - "user": "test_user", - "password": "test_password", - "database": "test_database", - "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, - }, - perms_container, - ) - if perms_container.has_actions(): - perms_container.activate() - m.container.depends.add_dependency("perms_container", "service_completed_successfully") - output = render.render() - assert "devices" not in output["services"]["mariadb_container"] - assert "reservations" not in output["services"]["mariadb_container"]["deploy"]["resources"] - assert output["services"]["mariadb_container"]["image"] == "mariadb:latest" - assert output["services"]["mariadb_container"]["user"] == "999:999" - assert output["services"]["mariadb_container"]["deploy"]["resources"]["limits"]["cpus"] == "2.0" - assert output["services"]["mariadb_container"]["deploy"]["resources"]["limits"]["memory"] == "4096M" - assert output["services"]["mariadb_container"]["healthcheck"] == { - "test": [ - "CMD", - "mariadb-admin", - "--user=root", - "--host=127.0.0.1", - "--port=3306", - "--password=test_password", - "ping", - ], - "interval": "30s", - "timeout": "5s", - "retries": 5, - "start_period": "15s", - "start_interval": "2s", - } - assert output["services"]["mariadb_container"]["volumes"] == [ - { - "type": "volume", - "source": "test_volume", - "target": "/var/lib/mysql", - "read_only": False, - "volume": {"nocopy": False}, - } - ] - assert output["services"]["mariadb_container"]["environment"] == { - "TZ": "Etc/UTC", - "UMASK": "002", - "UMASK_SET": "002", - "NVIDIA_VISIBLE_DEVICES": "void", - "MARIADB_USER": "test_user", - "MARIADB_PASSWORD": "test_password", - "MARIADB_ROOT_PASSWORD": "test_password", - "MARIADB_DATABASE": "test_database", - "MARIADB_AUTO_UPGRADE": "true", - } - assert output["services"]["mariadb_container"]["depends_on"] == { - "perms_container": {"condition": "service_completed_successfully"} - } - - -def test_add_perms_container(mock_values): - mock_values["ix_volumes"] = { - "test_dataset1": "/mnt/test/1", - "test_dataset2": "/mnt/test/2", - "test_dataset3": "/mnt/test/3", - } - mock_values["images"]["postgres_image"] = {"repository": "postgres", "tag": "17.7-bookworm"} - mock_values["images"]["redis_image"] = {"repository": "valkey/valkey", "tag": "latest"} - mock_values["images"]["mariadb_image"] = {"repository": "mariadb", "tag": "latest"} - render = Render(mock_values) - c1 = render.add_container("test_container", "test_image") - c1.healthcheck.disable() - - # fmt: off - volume_perms = {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}} - volume_no_perms = {"type": "volume", "volume_config": {"volume_name": "test_volume"}} - host_path_perms = {"type": "host_path", "host_path_config": {"path": "/mnt/test", "auto_permissions": True}} - host_path_no_perms = {"type": "host_path", "host_path_config": {"path": "/mnt/test"}} - host_path_acl_perms = {"type": "host_path", "host_path_config": {"acl": {"path": "/mnt/test"}, "acl_enable": True, "auto_permissions": True}} # noqa - ix_volume_no_perms = {"type": "ix_volume", "ix_volume_config": {"dataset_name": "test_dataset1"}} - ix_volume_perms = {"type": "ix_volume", "ix_volume_config": {"dataset_name": "test_dataset2", "auto_permissions": True}} # noqa - ix_volume_acl_perms = {"type": "ix_volume", "ix_volume_config": {"dataset_name": "test_dataset3", "acl_enable": True, "auto_permissions": True}} # noqa - temp_volume = {"type": "temporary", "volume_config": {"volume_name": "test_temp_volume"}} - read_only_volume = {"type": "volume", "read_only": True, "volume_config": {"volume_name": "test_read_only_volume", "auto_permissions": True}} # noqa - # fmt: on - - c1.add_storage("/some/path1", volume_perms) - c1.add_storage("/some/path2", volume_no_perms) - c1.add_storage("/some/path3", host_path_perms) - c1.add_storage("/some/path4", host_path_no_perms) - c1.add_storage("/some/path5", host_path_acl_perms) - c1.add_storage("/some/path6", ix_volume_no_perms) - c1.add_storage("/some/path7", ix_volume_perms) - c1.add_storage("/some/path8", ix_volume_acl_perms) - c1.add_storage("/some/path9", temp_volume) - c1.add_storage("/some/path10", read_only_volume) - - perms_container = render.deps.perms("test_perms_container") - perms_container.add_or_skip_action("data", volume_perms, {"uid": 1000, "gid": 1000, "mode": "check"}) - perms_container.add_or_skip_action("data2", volume_no_perms, {"uid": 1000, "gid": 1000, "mode": "check"}) - perms_container.add_or_skip_action("data3", host_path_perms, {"uid": 1000, "gid": 1000, "mode": "check"}) - perms_container.add_or_skip_action("data4", host_path_no_perms, {"uid": 1000, "gid": 1000, "mode": "check"}) - perms_container.add_or_skip_action("data5", host_path_acl_perms, {"uid": 1000, "gid": 1000, "mode": "check"}) - perms_container.add_or_skip_action("data6", ix_volume_no_perms, {"uid": 1000, "gid": 1000, "mode": "check"}) - perms_container.add_or_skip_action("data7", ix_volume_perms, {"uid": 1000, "gid": 1000, "mode": "check"}) - perms_container.add_or_skip_action("data8", ix_volume_acl_perms, {"uid": 1000, "gid": 1000, "mode": "check"}) - perms_container.add_or_skip_action("data9", temp_volume, {"uid": 1000, "gid": 1000, "mode": "check"}) - perms_container.add_or_skip_action("data10", read_only_volume, {"uid": 1000, "gid": 1000, "mode": "check"}) - postgres = render.deps.postgres( - "postgres_container", - "postgres_image", - { - "user": "test_user", - "password": "test_password", - "database": "test_database", - "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, - }, - perms_container, - ) - redis = render.deps.redis( - "redis_container", - "redis_image", - { - "password": "test_password", - "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, - }, - perms_container, - ) - mariadb = render.deps.mariadb( - "mariadb_container", - "mariadb_image", - { - "user": "test_user", - "password": "test_password", - "database": "test_database", - "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, - }, - perms_container, - ) - - if perms_container.has_actions(): - perms_container.activate() - c1.depends.add_dependency("test_perms_container", "service_completed_successfully") - postgres.container.depends.add_dependency("test_perms_container", "service_completed_successfully") - redis.container.depends.add_dependency("test_perms_container", "service_completed_successfully") - mariadb.container.depends.add_dependency("test_perms_container", "service_completed_successfully") - output = render.render() - assert output["services"]["test_perms_container"]["network_mode"] == "none" - assert output["services"]["test_container"]["depends_on"] == { - "test_perms_container": {"condition": "service_completed_successfully"} - } - # fmt: off - content = [ - {"read_only": False, "mount_path": "/mnt/permission/data", "is_temporary": False, "identifier": "data", "recursive": False, "mode": "check", "uid": 1000, "gid": 1000, "chmod": None}, # noqa - {"read_only": False, "mount_path": "/mnt/permission/data3", "is_temporary": False, "identifier": "data3", "recursive": False, "mode": "check", "uid": 1000, "gid": 1000, "chmod": None}, # noqa - {"read_only": False, "mount_path": "/mnt/permission/data6", "is_temporary": False, "identifier": "data6", "recursive": False, "mode": "check", "uid": 1000, "gid": 1000, "chmod": None}, # noqa - {"read_only": False, "mount_path": "/mnt/permission/data7", "is_temporary": False, "identifier": "data7", "recursive": False, "mode": "check", "uid": 1000, "gid": 1000, "chmod": None}, # noqa - {"read_only": False, "mount_path": "/mnt/permission/data9", "is_temporary": True, "identifier": "data9", "recursive": True, "mode": "check", "uid": 1000, "gid": 1000, "chmod": None}, # noqa - {"read_only": True, "mount_path": "/mnt/permission/data10", "is_temporary": False, "identifier": "data10", "recursive": False, "mode": "check", "uid": 1000, "gid": 1000, "chmod": None}, # noqa - {"read_only": False, "mount_path": "/mnt/permission/postgres_container_postgres_data", "is_temporary": False, "identifier": "postgres_container_postgres_data", "recursive": False, "mode": "check", "uid": 999, "gid": 999, "chmod": None}, # noqa - {"read_only": False, "mount_path": "/mnt/permission/redis_container_redis_data", "is_temporary": False, "identifier": "redis_container_redis_data", "recursive": False, "mode": "check", "uid": 568, "gid": 568, "chmod": None}, # noqa - {"read_only": False, "mount_path": "/mnt/permission/mariadb_container_mariadb_data", "is_temporary": False, "identifier": "mariadb_container_mariadb_data", "recursive": False, "mode": "check", "uid": 999, "gid": 999, "chmod": None}, # noqa - ] - # fmt: on - assert output["configs"]["permissions_actions_data"]["content"] == json.dumps(content) - assert output["services"]["test_perms_container"]["entrypoint"] == ["python3", "/script/permissions.py"] - - -def test_add_duplicate_perms_action(mock_values): - render = Render(mock_values) - c1 = render.add_container("test_container", "test_image") - c1.healthcheck.disable() - vol_config = {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}} - c1.add_storage("/some/path", vol_config) - perms_container = render.deps.perms("test_perms_container") - perms_container.add_or_skip_action("data", vol_config, {"uid": 1000, "gid": 1000, "mode": "check"}) - with pytest.raises(Exception): - perms_container.add_or_skip_action("data", vol_config, {"uid": 1000, "gid": 1000, "mode": "check"}) - - -def test_add_perm_action_without_auto_perms_enabled(mock_values): - render = Render(mock_values) - c1 = render.add_container("test_container", "test_image") - c1.healthcheck.disable() - vol_config = {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": False}} - c1.add_storage("/some/path", vol_config) - perms_container = render.deps.perms("test_perms_container") - perms_container.add_or_skip_action("data", vol_config, {"uid": 1000, "gid": 1000, "mode": "check"}) - if perms_container.has_actions(): - perms_container.activate() - c1.depends.add_dependency("test_perms_container", "service_completed_successfully") - output = render.render() - assert "configs" not in output - assert "ix-test_perms_container" not in output["services"] - assert "depends_on" not in output["services"]["test_container"] - - -def test_add_unsupported_postgres_version(mock_values): - mock_values["images"]["pg_image"] = {"repository": "postgres", "tag": "99"} - render = Render(mock_values) - c1 = render.add_container("test_container", "test_image") - c1.healthcheck.disable() - with pytest.raises(Exception): - render.deps.postgres( - "test_container", - "test_image", - {"user": "test_user", "password": "test_password", "database": "test_database"}, # type: ignore - ) - - -def test_add_postgres_with_invalid_tag(mock_values): - mock_values["images"]["pg_image"] = {"repository": "postgres", "tag": "latest"} - render = Render(mock_values) - c1 = render.add_container("test_container", "test_image") - c1.healthcheck.disable() - with pytest.raises(Exception): - render.deps.postgres( - "pg_container", - "pg_image", - {"user": "test_user", "password": "test_password", "database": "test_database"}, # type: ignore - ) - - -def test_no_upgrade_container_with_non_postgres_image(mock_values): - mock_values["images"]["postgres_image"] = {"repository": "pgvector/pgvector", "tag": "0.8.1-pg17"} - render = Render(mock_values) - c1 = render.add_container("test_container", "test_image") - c1.healthcheck.disable() - perms_container = render.deps.perms("test_perms_container") - pg = render.deps.postgres( - "postgres_container", - "postgres_image", - { - "user": "test_user", - "password": "test_password", - "database": "test_database", - "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, - }, - perms_container, - ) - if perms_container.has_actions(): - perms_container.activate() - pg.add_dependency("test_perms_container", "service_completed_successfully") - output = render.render() - assert len(output["services"]) == 3 # c1, pg, perms - assert output["services"]["postgres_container"]["depends_on"] == { - "test_perms_container": {"condition": "service_completed_successfully"} - } - - -def test_postgres_with_upgrade_container(mock_values): - mock_values["images"]["pg_image"] = {"repository": "postgres", "tag": "16.6-bookworm"} - render = Render(mock_values) - c1 = render.add_container("test_container", "test_image") - c1.healthcheck.disable() - perms_container = render.deps.perms("test_perms_container") - pg = render.deps.postgres( - "postgres_container", - "pg_image", - { - "user": "test_user", - "password": "test_password", - "database": "test_database", - "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, - }, - perms_container, - ) - if perms_container.has_actions(): - perms_container.activate() - pg.add_dependency("test_perms_container", "service_completed_successfully") - output = render.render() - pg = output["services"]["postgres_container"] - pgup = output["services"]["postgres_container_upgrade"] - assert pg["volumes"] == pgup["volumes"] - assert pg["user"] == pgup["user"] - assert pgup["environment"]["TARGET_VERSION"] == "16" - assert pgup["environment"]["PGDATA"] == "/var/lib/postgresql/16/docker" - pgup_env = pgup["environment"] - pgup_env.pop("TARGET_VERSION") - assert pg["environment"] == pgup_env - assert pg["depends_on"] == { - "test_perms_container": {"condition": "service_completed_successfully"}, - "postgres_container_upgrade": {"condition": "service_completed_successfully"}, - } - assert pgup["depends_on"] == {"test_perms_container": {"condition": "service_completed_successfully"}} - assert pgup["restart"] == "on-failure:1" - assert pgup["healthcheck"] == {"disable": True} - assert pgup["image"] == "ixsystems/postgres-upgrade:1.0.0" - assert pgup["entrypoint"] == ["/bin/bash", "-c", "/upgrade.sh"] - - -def test_add_mongodb(mock_values): - mock_values["images"]["mongodb_image"] = {"repository": "mongodb", "tag": "latest"} - render = Render(mock_values) - c1 = render.add_container("test_container", "test_image") - c1.healthcheck.disable() - perms_container = render.deps.perms("perms_container") - m = render.deps.mongodb( - "mongodb_container", - "mongodb_image", - { - "user": "test_user", - "password": "test_password", - "database": "test_database", - "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, - }, - perms_container, - ) - if perms_container.has_actions(): - perms_container.activate() - m.container.depends.add_dependency("perms_container", "service_completed_successfully") - output = render.render() - assert "devices" not in output["services"]["mongodb_container"] - assert "reservations" not in output["services"]["mongodb_container"]["deploy"]["resources"] - assert output["services"]["mongodb_container"]["image"] == "mongodb:latest" - assert output["services"]["mongodb_container"]["user"] == "568:568" - assert output["services"]["mongodb_container"]["deploy"]["resources"]["limits"]["cpus"] == "2.0" - assert output["services"]["mongodb_container"]["deploy"]["resources"]["limits"]["memory"] == "4096M" - assert output["services"]["mongodb_container"]["healthcheck"] == { - "test": [ - "CMD", - "mongosh", - "--host", - "127.0.0.1", - "--port", - "27017", - "test_database", - "--eval", - 'db.adminCommand("ping")', - "--quiet", - ], - "interval": "30s", - "timeout": "5s", - "retries": 5, - "start_period": "15s", - "start_interval": "2s", - } - assert output["services"]["mongodb_container"]["volumes"] == [ - { - "type": "volume", - "source": "test_volume", - "target": "/data/db", - "read_only": False, - "volume": {"nocopy": False}, - } - ] - assert output["services"]["mongodb_container"]["environment"] == { - "TZ": "Etc/UTC", - "UMASK": "002", - "UMASK_SET": "002", - "NVIDIA_VISIBLE_DEVICES": "void", - "MONGO_INITDB_ROOT_USERNAME": "test_user", - "MONGO_INITDB_ROOT_PASSWORD": "test_password", - "MONGO_INITDB_DATABASE": "test_database", - } - assert output["services"]["mongodb_container"]["depends_on"] == { - "perms_container": {"condition": "service_completed_successfully"} - } - - -def test_add_mongodb_unsupported_repo(mock_values): - mock_values["images"]["mongo_image"] = {"repository": "unsupported_repo", "tag": "7"} - render = Render(mock_values) - c1 = render.add_container("test_container", "test_image") - c1.healthcheck.disable() - perms_container = render.deps.perms("perms_container") - with pytest.raises(Exception): - render.deps.mongodb( - "mongo_container", - "mongo_image", - { - "user": "test_user", - "password": "test_@password", - "database": "test_database", - "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, - }, - perms_container, - ) - - -def test_add_meilisearch(mock_values): - mock_values["images"]["meili_image"] = {"repository": "getmeili/meilisearch", "tag": "v1.17.0"} - render = Render(mock_values) - c1 = render.add_container("test_container", "test_image") - c1.healthcheck.disable() - perms_container = render.deps.perms("perms_container") - m = render.deps.meilisearch( - "meili_container", - "meili_image", - { - "master_key": "test_master_key", - "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, - }, - perms_container, - ) - if perms_container.has_actions(): - perms_container.activate() - m.container.depends.add_dependency("perms_container", "service_completed_successfully") - output = render.render() - assert "devices" not in output["services"]["meili_container"] - assert "reservations" not in output["services"]["meili_container"]["deploy"]["resources"] - assert output["services"]["meili_container"]["image"] == "getmeili/meilisearch:v1.17.0" - assert output["services"]["meili_container"]["user"] == "568:568" - assert output["services"]["meili_container"]["deploy"]["resources"]["limits"]["cpus"] == "2.0" - assert output["services"]["meili_container"]["deploy"]["resources"]["limits"]["memory"] == "4096M" - assert output["services"]["meili_container"]["healthcheck"] == { - "test": [ - "CMD", - "curl", - "--request", - "GET", - "--silent", - "--output", - "/dev/null", - "--show-error", - "--fail", - "http://127.0.0.1:7700/health", - ], - "interval": "30s", - "timeout": "5s", - "retries": 5, - "start_period": "15s", - "start_interval": "2s", - } - assert output["services"]["meili_container"]["volumes"] == [ - { - "type": "volume", - "source": "test_volume", - "target": "/meili_data", - "read_only": False, - "volume": {"nocopy": False}, - } - ] - assert output["services"]["meili_container"]["environment"] == { - "TZ": "Etc/UTC", - "UMASK": "002", - "UMASK_SET": "002", - "NVIDIA_VISIBLE_DEVICES": "void", - "MEILI_MASTER_KEY": "test_master_key", - "MEILI_HTTP_ADDR": "0.0.0.0:7700", - "MEILI_NO_ANALYTICS": "true", - "MEILI_EXPERIMENTAL_DUMPLESS_UPGRADE": "true", - } - assert output["services"]["meili_container"]["depends_on"] == { - "perms_container": {"condition": "service_completed_successfully"} - } - - -def test_add_meilisearch_unsupported_repo(mock_values): - mock_values["images"]["meili_image"] = {"repository": "unsupported_repo", "tag": "7"} - render = Render(mock_values) - c1 = render.add_container("test_container", "test_image") - c1.healthcheck.disable() - perms_container = render.deps.perms("perms_container") - with pytest.raises(Exception): - render.deps.meilisearch( - "meili_container", - "meili_image", - { - "master_key": "test_master_key", - "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, - }, - perms_container, - ) - - -def test_add_elasticsearch(mock_values): - mock_values["images"]["elastic_image"] = { - "repository": "docker.elastic.co/elasticsearch/elasticsearch", - "tag": "9.1.2", - } - render = Render(mock_values) - c1 = render.add_container("test_container", "test_image") - c1.healthcheck.disable() - perms_container = render.deps.perms("perms_container") - m = render.deps.elasticsearch( - "elastic_container", - "elastic_image", - { - "password": "test_password", - "node_name": "some_test_node", - "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, - }, - perms_container, - ) - if perms_container.has_actions(): - perms_container.activate() - m.container.depends.add_dependency("perms_container", "service_completed_successfully") - output = render.render() - assert "devices" not in output["services"]["elastic_container"] - assert "reservations" not in output["services"]["elastic_container"]["deploy"]["resources"] - assert output["services"]["elastic_container"]["image"] == "docker.elastic.co/elasticsearch/elasticsearch:9.1.2" - assert output["services"]["elastic_container"]["user"] == "1000:1000" - assert output["services"]["elastic_container"]["deploy"]["resources"]["limits"]["cpus"] == "2.0" - assert output["services"]["elastic_container"]["deploy"]["resources"]["limits"]["memory"] == "4096M" - assert output["services"]["elastic_container"]["healthcheck"] == { - "test": [ - "CMD", - "curl", - "--request", - "GET", - "--silent", - "--output", - "/dev/null", - "--show-error", - "--fail", - "--header", - "Authorization: Basic ZWxhc3RpYzp0ZXN0X3Bhc3N3b3Jk", - "http://127.0.0.1:9200/_cluster/health?local=true", - ], # noqa - "interval": "30s", - "timeout": "5s", - "retries": 5, - "start_period": "15s", - "start_interval": "2s", - } - assert output["services"]["elastic_container"]["volumes"] == [ - { - "type": "volume", - "source": "test_volume", - "target": "/usr/share/elasticsearch/data", - "read_only": False, - "volume": {"nocopy": False}, - } - ] - assert output["services"]["elastic_container"]["environment"] == { - "TZ": "Etc/UTC", - "UMASK": "002", - "UMASK_SET": "002", - "NVIDIA_VISIBLE_DEVICES": "void", - "ELASTIC_PASSWORD": "test_password", - "http.port": "9200", - "path.data": "/usr/share/elasticsearch/data", - "path.repo": "/usr/share/elasticsearch/data/snapshots", - "node.name": "some_test_node", - "discovery.type": "single-node", - "xpack.security.enabled": "true", - "xpack.security.transport.ssl.enabled": "false", - } - assert output["services"]["elastic_container"]["depends_on"] == { - "perms_container": {"condition": "service_completed_successfully"} - } - - -def test_add_elasticsearch_unsupported_repo(mock_values): - mock_values["images"]["elastic_image"] = {"repository": "unsupported_repo", "tag": "7"} - render = Render(mock_values) - c1 = render.add_container("test_container", "test_image") - c1.healthcheck.disable() - perms_container = render.deps.perms("perms_container") - with pytest.raises(Exception): - render.deps.elasticsearch( - "elastic_container", - "elastic_image", - { - "password": "test_password", - "node_name": "some_test_node", - "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, - }, - perms_container, - ) - - -def test_add_solr(mock_values): - mock_values["images"]["solr_image"] = {"repository": "solr", "tag": "9.9.0"} - render = Render(mock_values) - c1 = render.add_container("test_container", "test_image") - c1.healthcheck.disable() - perms_container = render.deps.perms("perms_container") - m = render.deps.solr( - "solr_container", - "solr_image", - { - "core": "test_core", - "modules": ["analysis-extras", "some-other-module"], - "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, - }, - perms_container, - ) - if perms_container.has_actions(): - perms_container.activate() - m.container.depends.add_dependency("perms_container", "service_completed_successfully") - output = render.render() - assert "devices" not in output["services"]["solr_container"] - assert "reservations" not in output["services"]["solr_container"]["deploy"]["resources"] - assert output["services"]["solr_container"]["image"] == "solr:9.9.0" - assert output["services"]["solr_container"]["user"] == "568:568" - assert output["services"]["solr_container"]["deploy"]["resources"]["limits"]["cpus"] == "2.0" - assert output["services"]["solr_container"]["deploy"]["resources"]["limits"]["memory"] == "4096M" - assert output["services"]["solr_container"]["healthcheck"] == { - "test": [ - "CMD", - "curl", - "--request", - "GET", - "--silent", - "--output", - "/dev/null", - "--show-error", - "--fail", - "http://127.0.0.1:8983/solr/test_core/admin/ping", - ], - "interval": "30s", - "timeout": "5s", - "retries": 5, - "start_period": "15s", - "start_interval": "2s", - } - assert output["services"]["solr_container"]["volumes"] == [ - { - "type": "volume", - "source": "test_volume", - "target": "/var/solr", - "read_only": False, - "volume": {"nocopy": False}, - } - ] - assert output["services"]["solr_container"]["environment"] == { - "TZ": "Etc/UTC", - "UMASK": "002", - "UMASK_SET": "002", - "NVIDIA_VISIBLE_DEVICES": "void", - "SOLR_PORT": "8983", - "SOLR_MODULES": "analysis-extras,some-other-module", - } - assert output["services"]["solr_container"]["command"] == ["solr-precreate", "test_core"] - assert output["services"]["solr_container"]["depends_on"] == { - "perms_container": {"condition": "service_completed_successfully"} - } - - -def test_add_solr_unsupported_repo(mock_values): - mock_values["images"]["solr_image"] = {"repository": "unsupported_repo", "tag": "7"} - render = Render(mock_values) - c1 = render.add_container("test_container", "test_image") - c1.healthcheck.disable() - perms_container = render.deps.perms("perms_container") - with pytest.raises(Exception): - render.deps.solr( - "solr_container", - "solr_image", - { - "core": "test_core", - "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, - }, - perms_container, - ) - - -def test_add_tika(mock_values): - mock_values["images"]["tika_image"] = {"repository": "apache/tika", "tag": "3.2.3.0-full"} - render = Render(mock_values) - c1 = render.add_container("test_container", "test_image") - c1.healthcheck.disable() - render.deps.tika( - "tika_container", - "tika_image", - { - "port": 10999, - }, - ) - output = render.render() - assert "devices" not in output["services"]["tika_container"] - assert "reservations" not in output["services"]["tika_container"]["deploy"]["resources"] - assert output["services"]["tika_container"]["image"] == "apache/tika:3.2.3.0-full" - assert output["services"]["tika_container"]["user"] == "568:568" - assert output["services"]["tika_container"]["deploy"]["resources"]["limits"]["cpus"] == "2.0" - assert output["services"]["tika_container"]["deploy"]["resources"]["limits"]["memory"] == "4096M" - assert output["services"]["tika_container"]["healthcheck"] == { - "test": [ - "CMD", - "wget", - "--quiet", - "-O", - "/dev/null", - "http://127.0.0.1:10999/tika", - ], - "interval": "30s", - "timeout": "5s", - "retries": 5, - "start_period": "15s", - "start_interval": "2s", - } - assert output["services"]["tika_container"]["environment"] == { - "TZ": "Etc/UTC", - "UMASK": "002", - "UMASK_SET": "002", - "NVIDIA_VISIBLE_DEVICES": "void", - } - assert output["services"]["tika_container"]["command"] == ["--port", "10999"] - - -def test_add_tika_unsupported_repo(mock_values): - mock_values["images"]["tika_image"] = {"repository": "unsupported_repo", "tag": "7"} - render = Render(mock_values) - c1 = render.add_container("test_container", "test_image") - c1.healthcheck.disable() - with pytest.raises(Exception): - render.deps.tika( - "tika_container", - "tika_image", - {}, - ) diff --git a/library/2.1.65/__init__.py b/library/2.1.66/__init__.py similarity index 100% rename from library/2.1.65/__init__.py rename to library/2.1.66/__init__.py diff --git a/library/2.1.65/client.py b/library/2.1.66/client.py similarity index 100% rename from library/2.1.65/client.py rename to library/2.1.66/client.py diff --git a/library/2.1.65/configs.py b/library/2.1.66/configs.py similarity index 100% rename from library/2.1.65/configs.py rename to library/2.1.66/configs.py diff --git a/library/2.1.65/container.py b/library/2.1.66/container.py similarity index 100% rename from library/2.1.65/container.py rename to library/2.1.66/container.py diff --git a/library/2.1.65/depends.py b/library/2.1.66/depends.py similarity index 100% rename from library/2.1.65/depends.py rename to library/2.1.66/depends.py diff --git a/library/2.1.65/deploy.py b/library/2.1.66/deploy.py similarity index 100% rename from library/2.1.65/deploy.py rename to library/2.1.66/deploy.py diff --git a/library/2.1.65/deps.py b/library/2.1.66/deps.py similarity index 100% rename from library/2.1.65/deps.py rename to library/2.1.66/deps.py diff --git a/library/2.1.65/deps_elastic.py b/library/2.1.66/deps_elastic.py similarity index 100% rename from library/2.1.65/deps_elastic.py rename to library/2.1.66/deps_elastic.py diff --git a/library/2.1.65/deps_mariadb.py b/library/2.1.66/deps_mariadb.py similarity index 100% rename from library/2.1.65/deps_mariadb.py rename to library/2.1.66/deps_mariadb.py diff --git a/library/2.1.65/deps_meilisearch.py b/library/2.1.66/deps_meilisearch.py similarity index 100% rename from library/2.1.65/deps_meilisearch.py rename to library/2.1.66/deps_meilisearch.py diff --git a/library/2.1.65/deps_mongodb.py b/library/2.1.66/deps_mongodb.py similarity index 100% rename from library/2.1.65/deps_mongodb.py rename to library/2.1.66/deps_mongodb.py diff --git a/library/2.1.65/deps_perms.py b/library/2.1.66/deps_perms.py similarity index 100% rename from library/2.1.65/deps_perms.py rename to library/2.1.66/deps_perms.py diff --git a/library/2.1.66/deps_postgres.py b/library/2.1.66/deps_postgres.py new file mode 100644 index 0000000000..1e6f7471c8 --- /dev/null +++ b/library/2.1.66/deps_postgres.py @@ -0,0 +1,220 @@ +import re +import urllib.parse +from typing import TYPE_CHECKING, TypedDict, NotRequired + + +if TYPE_CHECKING: + from render import Render + from storage import IxStorage + + +try: + from .error import RenderError + from .deps_perms import PermsContainer + from .validations import valid_port_or_raise +except ImportError: + from error import RenderError + from deps_perms import PermsContainer + from validations import valid_port_or_raise + + +class PostgresConfig(TypedDict): + user: str + password: str + database: str + port: NotRequired[int] + volume: "IxStorage" + additional_options: NotRequired[dict[str, str]] + + +MAX_POSTGRES_VERSION = 18 +SUPPORTED_REPOS = [ + "postgres", + "postgis/postgis", + "pgvector/pgvector", + "ghcr.io/immich-app/postgres", +] +SUPPORTED_UPGRADE_REPOS = [ + "postgres", + "postgis/postgis", + "pgvector/pgvector", +] + + +def get_major_version(variant: str, tag: str): + if variant == "postgres": + # 17.7-bookworm + regex = re.compile(r"^\d+\.\d+-\w+") + + def oper(x): + return x.split(".")[0] + + elif variant == "postgis/postgis": + # 17-3.5 + regex = re.compile(r"^\d+\-\d+\.\d+") + + def oper(x): + return x.split("-")[0] + + elif variant == "pgvector/pgvector": + # 0.8.1-pg17-trixie + regex = re.compile(r"^\d+\.\d+\.\d+\-pg\d+(\-\w+)?") + + def oper(x): + parts = x.split("-") + return parts[1].lstrip("pg") + + elif variant == "ghcr.io/immich-app/postgres": + # 15-vectorchord0.4.3 + regex = re.compile(r"^\d+\-vectorchord\d+\.\d+\.\d+") + + def oper(x): + return x.split("-")[0] + + if not regex.match(tag): + raise RenderError(f"Could not determine major version from tag [{tag}] for variant [{variant}]") + + return oper(tag) + + +class PostgresContainer: + def __init__( + self, render_instance: "Render", name: str, image: str, config: PostgresConfig, perms_instance: PermsContainer + ): + self._render_instance = render_instance + self._name = name + self._config = config + self._data_dir = None + self._upgrade_name = f"{self._name}_upgrade" + self._upgrade_container = None + + for key in ("user", "password", "database", "volume"): + if key not in config: + raise RenderError(f"Expected [{key}] to be set for postgres") + + port = valid_port_or_raise(self.get_port()) + + # TODO: Set some defaults for ZFS Optimizations (Need to check if applies on updates) + # https://vadosware.io/post/everything-ive-seen-on-optimizing-postgres-on-zfs-on-linux/ + + opts = [] + for k, v in config.get("additional_options", {}).items(): + opts.extend(["-c", f"{k}={v}"]) + + common_variables = { + "POSTGRES_USER": config["user"], + "POSTGRES_PASSWORD": config["password"], + "POSTGRES_DB": config["database"], + "PGPORT": port, + } + + c = self._render_instance.add_container(name, image) + c.healthcheck.set_test("postgres", {"user": config["user"], "db": config["database"]}) + c.set_shm_size_mb(256) + + if opts: + c.set_command(opts) + + containers = [c] + + # eg we don't want to handle upgrades of pg_vector or immich at the moment + repo = self._get_repo(image) + if repo in SUPPORTED_UPGRADE_REPOS: + self._data_dir = "/var/lib/postgresql" + target_major_version = self._get_target_version(image) + # This is the new format upstream Postgres uses/suggests. + # E.g., for Postgres 17, the data dir is /var/lib/postgresql/17/docker + common_variables.update({"PGDATA": f"{self._data_dir}/{target_major_version}/docker"}) + + upg = self._render_instance.add_container(self._upgrade_name, "postgres_upgrade_image") + + self._upgrade_container = upg + containers.append(upg) + + upg.set_entrypoint(["/bin/bash", "-c", "/upgrade.sh"]) + upg.restart.set_policy("on-failure", 1) + upg.healthcheck.disable() + upg.setup_as_helper(profile="medium") + upg.environment.add_env("TARGET_VERSION", target_major_version) + + c.depends.add_dependency(self._upgrade_name, "service_completed_successfully") + else: + self._data_dir = "/var/lib/postgresql/data" + + for container in containers: + # TODO: We can now use 568:568 (or any user/group). + # Need to first plan a migration path for the existing users. + container.set_user(999, 999) + container.remove_devices() + container.add_storage(self._data_dir, config["volume"]) + for k, v in common_variables.items(): + container.environment.add_env(k, v) + + perms_instance.add_or_skip_action( + f"{self._name}_postgres_data", config["volume"], {"uid": 999, "gid": 999, "mode": "check"} + ) + + # Store container for further configuration + # For example: c.depends.add_dependency("other_container", "service_started") + self._container = c + + @property + def container(self): + return self._container + + def add_dependency(self, container_name: str, condition: str): + self._container.depends.add_dependency(container_name, condition) + if self._upgrade_container: + self._upgrade_container.depends.add_dependency(container_name, condition) + + def _get_repo(self, image): + images = self._render_instance.values["images"] + if image not in images: + raise RenderError(f"Image [{image}] not found in values. Available images: [{', '.join(images.keys())}]") + repo = images[image].get("repository") + if not repo: + raise RenderError("Could not determine repo") + if repo not in SUPPORTED_REPOS: + raise RenderError(f"Unsupported repo [{repo}] for postgres. Supported repos: {', '.join(SUPPORTED_REPOS)}") + return repo + + def _get_target_version(self, image): + repo = self._get_repo(image) + images = self._render_instance.values["images"] + if image not in images: + raise RenderError(f"Image [{image}] not found in values. Available images: [{', '.join(images.keys())}]") + tag = str(images[image].get("tag", "")) + target_major_version = get_major_version(repo, tag) + + try: + # Make sure we end up with an integer + target_major_version = int(target_major_version) + except ValueError: + raise RenderError(f"Could not determine target major version from tag [{tag}]") + + if target_major_version > MAX_POSTGRES_VERSION: + raise RenderError(f"Postgres version [{target_major_version}] is not supported") + + return target_major_version + + def get_port(self): + return self._config.get("port") or 5432 + + def get_url(self, variant: str): + user = urllib.parse.quote_plus(self._config["user"]) + password = urllib.parse.quote_plus(self._config["password"]) + creds = f"{user}:{password}" + addr = f"{self._name}:{self.get_port()}" + db = self._config["database"] + + urls = { + "postgres": f"postgres://{creds}@{addr}/{db}?sslmode=disable", + "postgresql": f"postgresql://{creds}@{addr}/{db}?sslmode=disable", + "postgresql_no_creds": f"postgresql://{addr}/{db}?sslmode=disable", + "jdbc": f"jdbc:postgresql://{addr}/{db}", + "host_port": addr, + } + + if variant not in urls: + raise RenderError(f"Expected [variant] to be one of [{', '.join(urls.keys())}], got [{variant}]") + return urls[variant] diff --git a/library/2.1.65/deps_redis.py b/library/2.1.66/deps_redis.py similarity index 100% rename from library/2.1.65/deps_redis.py rename to library/2.1.66/deps_redis.py diff --git a/library/2.1.65/deps_solr.py b/library/2.1.66/deps_solr.py similarity index 100% rename from library/2.1.65/deps_solr.py rename to library/2.1.66/deps_solr.py diff --git a/library/2.1.65/deps_tika.py b/library/2.1.66/deps_tika.py similarity index 100% rename from library/2.1.65/deps_tika.py rename to library/2.1.66/deps_tika.py diff --git a/library/2.1.65/device.py b/library/2.1.66/device.py similarity index 100% rename from library/2.1.65/device.py rename to library/2.1.66/device.py diff --git a/library/2.1.65/device_cgroup_rules.py b/library/2.1.66/device_cgroup_rules.py similarity index 100% rename from library/2.1.65/device_cgroup_rules.py rename to library/2.1.66/device_cgroup_rules.py diff --git a/library/2.1.65/devices.py b/library/2.1.66/devices.py similarity index 100% rename from library/2.1.65/devices.py rename to library/2.1.66/devices.py diff --git a/library/2.1.65/dns.py b/library/2.1.66/dns.py similarity index 100% rename from library/2.1.65/dns.py rename to library/2.1.66/dns.py diff --git a/library/2.1.65/environment.py b/library/2.1.66/environment.py similarity index 100% rename from library/2.1.65/environment.py rename to library/2.1.66/environment.py diff --git a/library/2.1.65/error.py b/library/2.1.66/error.py similarity index 100% rename from library/2.1.65/error.py rename to library/2.1.66/error.py diff --git a/library/2.1.65/expose.py b/library/2.1.66/expose.py similarity index 100% rename from library/2.1.65/expose.py rename to library/2.1.66/expose.py diff --git a/library/2.1.65/extra_hosts.py b/library/2.1.66/extra_hosts.py similarity index 100% rename from library/2.1.65/extra_hosts.py rename to library/2.1.66/extra_hosts.py diff --git a/library/2.1.65/formatter.py b/library/2.1.66/formatter.py similarity index 100% rename from library/2.1.65/formatter.py rename to library/2.1.66/formatter.py diff --git a/library/2.1.65/functions.py b/library/2.1.66/functions.py similarity index 100% rename from library/2.1.65/functions.py rename to library/2.1.66/functions.py diff --git a/library/2.1.65/healthcheck.py b/library/2.1.66/healthcheck.py similarity index 100% rename from library/2.1.65/healthcheck.py rename to library/2.1.66/healthcheck.py diff --git a/library/2.1.65/labels.py b/library/2.1.66/labels.py similarity index 100% rename from library/2.1.65/labels.py rename to library/2.1.66/labels.py diff --git a/library/2.1.65/notes.py b/library/2.1.66/notes.py similarity index 100% rename from library/2.1.65/notes.py rename to library/2.1.66/notes.py diff --git a/library/2.1.65/portals.py b/library/2.1.66/portals.py similarity index 100% rename from library/2.1.65/portals.py rename to library/2.1.66/portals.py diff --git a/library/2.1.65/ports.py b/library/2.1.66/ports.py similarity index 100% rename from library/2.1.65/ports.py rename to library/2.1.66/ports.py diff --git a/library/2.1.65/render.py b/library/2.1.66/render.py similarity index 100% rename from library/2.1.65/render.py rename to library/2.1.66/render.py diff --git a/library/2.1.65/resources.py b/library/2.1.66/resources.py similarity index 100% rename from library/2.1.65/resources.py rename to library/2.1.66/resources.py diff --git a/library/2.1.65/restart.py b/library/2.1.66/restart.py similarity index 100% rename from library/2.1.65/restart.py rename to library/2.1.66/restart.py diff --git a/library/2.1.65/security_opts.py b/library/2.1.66/security_opts.py similarity index 100% rename from library/2.1.65/security_opts.py rename to library/2.1.66/security_opts.py diff --git a/library/2.1.65/storage.py b/library/2.1.66/storage.py similarity index 100% rename from library/2.1.65/storage.py rename to library/2.1.66/storage.py diff --git a/library/2.1.65/sysctls.py b/library/2.1.66/sysctls.py similarity index 100% rename from library/2.1.65/sysctls.py rename to library/2.1.66/sysctls.py diff --git a/library/2.1.65/tests/__init__.py b/library/2.1.66/tests/__init__.py similarity index 100% rename from library/2.1.65/tests/__init__.py rename to library/2.1.66/tests/__init__.py diff --git a/library/2.1.65/tests/test_build_image.py b/library/2.1.66/tests/test_build_image.py similarity index 100% rename from library/2.1.65/tests/test_build_image.py rename to library/2.1.66/tests/test_build_image.py diff --git a/library/2.1.65/tests/test_configs.py b/library/2.1.66/tests/test_configs.py similarity index 100% rename from library/2.1.65/tests/test_configs.py rename to library/2.1.66/tests/test_configs.py diff --git a/library/2.1.65/tests/test_container.py b/library/2.1.66/tests/test_container.py similarity index 100% rename from library/2.1.65/tests/test_container.py rename to library/2.1.66/tests/test_container.py diff --git a/library/2.1.65/tests/test_depends.py b/library/2.1.66/tests/test_depends.py similarity index 100% rename from library/2.1.65/tests/test_depends.py rename to library/2.1.66/tests/test_depends.py diff --git a/library/2.1.66/tests/test_deps.py b/library/2.1.66/tests/test_deps.py new file mode 100644 index 0000000000..197486537a --- /dev/null +++ b/library/2.1.66/tests/test_deps.py @@ -0,0 +1,1021 @@ +import json +import pytest + +from render import Render + + +@pytest.fixture +def mock_values(): + return { + "images": { + "test_image": { + "repository": "nginx", + "tag": "latest", + }, + "container_utils_image": { + "repository": "ixsystems/container-utils", + "tag": "1.0.0", + }, + "postgres_upgrade_image": { + "repository": "ixsystems/postgres-upgrade", + "tag": "1.0.0", + }, + }, + } + + +def test_add_postgres_missing_config(mock_values): + render = Render(mock_values) + c1 = render.add_container("test_container", "test_image") + c1.healthcheck.disable() + with pytest.raises(Exception): + render.deps.postgres( + "pg_container", + "test_image", + {"user": "test_user", "password": "test_password", "database": "test_database"}, # type: ignore + ) + + +def test_add_postgres_unsupported_repo(mock_values): + mock_values["images"]["pg_image"] = {"repository": "unsupported_repo", "tag": "16.6-bookworm"} + render = Render(mock_values) + c1 = render.add_container("test_container", "test_image") + c1.healthcheck.disable() + perms_container = render.deps.perms("perms_container") + with pytest.raises(Exception): + render.deps.postgres( + "pg_container", + "pg_image", + { + "user": "test_user", + "password": "test_@password", + "database": "test_database", + "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, + }, + perms_container, + ) + + +def test_add_postgres(mock_values): + mock_values["images"]["pg_image"] = {"repository": "postgres", "tag": "16.6-bookworm"} + render = Render(mock_values) + c1 = render.add_container("test_container", "test_image") + c1.healthcheck.disable() + perms_container = render.deps.perms("perms_container") + p = render.deps.postgres( + "pg_container", + "pg_image", + { + "user": "test_user", + "password": "test_@password", + "database": "test_database", + "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, + }, + perms_container, + ) + if perms_container.has_actions(): + perms_container.activate() + p.container.depends.add_dependency("perms_container", "service_completed_successfully") + output = render.render() + assert ( + p.get_url("postgres") == "postgres://test_user:test_%40password@pg_container:5432/test_database?sslmode=disable" + ) + assert "devices" not in output["services"]["pg_container"] + assert "reservations" not in output["services"]["pg_container"]["deploy"]["resources"] + assert output["services"]["pg_container"]["image"] == "postgres:16.6-bookworm" + assert output["services"]["pg_container"]["user"] == "999:999" + assert output["services"]["pg_container"]["deploy"]["resources"]["limits"]["cpus"] == "2.0" + assert output["services"]["pg_container"]["deploy"]["resources"]["limits"]["memory"] == "4096M" + assert output["services"]["pg_container"]["healthcheck"] == { + "test": [ + "CMD", + "pg_isready", + "-h", + "127.0.0.1", + "-p", + "5432", + "-U", + "test_user", + "-d", + "test_database", + ], + "interval": "30s", + "timeout": "5s", + "retries": 5, + "start_period": "15s", + "start_interval": "2s", + } + assert output["services"]["pg_container"]["volumes"] == [ + { + "type": "volume", + "source": "test_volume", + "target": "/var/lib/postgresql", + "read_only": False, + "volume": {"nocopy": False}, + } + ] + assert output["services"]["pg_container"]["environment"] == { + "TZ": "Etc/UTC", + "UMASK": "002", + "UMASK_SET": "002", + "NVIDIA_VISIBLE_DEVICES": "void", + "POSTGRES_USER": "test_user", + "POSTGRES_PASSWORD": "test_@password", + "POSTGRES_DB": "test_database", + "PGPORT": "5432", + "PGDATA": "/var/lib/postgresql/16/docker", + } + assert output["services"]["pg_container"]["depends_on"] == { + "perms_container": {"condition": "service_completed_successfully"}, + "pg_container_upgrade": {"condition": "service_completed_successfully"}, + } + assert output["services"]["perms_container"]["restart"] == "on-failure:1" + + +def test_add_postgres_options(mock_values): + mock_values["images"]["pg_image"] = {"repository": "postgres", "tag": "16.6-bookworm"} + render = Render(mock_values) + c1 = render.add_container("test_container", "test_image") + c1.healthcheck.disable() + perms_container = render.deps.perms("perms_container") + render.deps.postgres( + "pg_container", + "pg_image", + { + "user": "test_user", + "password": "test_@password", + "database": "test_database", + "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, + "additional_options": {"maintenance_work_mem": "1024MB", "max_connections": "100"}, + }, + perms_container, + ) + + output = render.render() + assert output["services"]["pg_container"]["command"] == [ + "-c", + "maintenance_work_mem=1024MB", + "-c", + "max_connections=100", + ] + + +def test_add_redis_missing_config(mock_values): + render = Render(mock_values) + c1 = render.add_container("test_container", "test_image") + c1.healthcheck.disable() + with pytest.raises(Exception): + render.deps.redis( + "redis_container", + "test_image", + {"password": "test_password", "volume": {}}, # type: ignore + ) + + +def test_add_redis_unsupported_repo(mock_values): + mock_values["images"]["redis_image"] = {"repository": "unsupported_repo", "tag": "latest"} + render = Render(mock_values) + c1 = render.add_container("test_container", "test_image") + c1.healthcheck.disable() + perms_container = render.deps.perms("perms_container") + with pytest.raises(Exception): + render.deps.redis( + "redis_container", + "redis_image", + { + "password": "test&password@", + "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, + }, + perms_container, + ) + + +def test_add_redis_with_password_with_spaces(mock_values): + mock_values["images"]["redis_image"] = {"repository": "redis", "tag": "latest"} + render = Render(mock_values) + c1 = render.add_container("test_container", "test_image") + c1.healthcheck.disable() + with pytest.raises(Exception): + render.deps.redis( + "redis_container", + "redis_image", + {"password": "test password", "volume": {}}, # type: ignore + ) + + +def test_add_redis(mock_values): + mock_values["images"]["redis_image"] = {"repository": "valkey/valkey", "tag": "latest"} + mock_values["run_as"] = {"user": 0, "group": 0} + render = Render(mock_values) + c1 = render.add_container("test_container", "test_image") + c1.healthcheck.disable() + perms_container = render.deps.perms("perms_container") + r = render.deps.redis( + "redis_container", + "redis_image", + { + "password": "test&password@", + "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, + }, + perms_container, + ) + c1.environment.add_env("REDIS_URL", r.get_url("redis")) + if perms_container.has_actions(): + perms_container.activate() + r.container.depends.add_dependency("perms_container", "service_completed_successfully") + output = render.render() + assert "devices" not in output["services"]["redis_container"] + assert "reservations" not in output["services"]["redis_container"]["deploy"]["resources"] + assert ( + output["services"]["test_container"]["environment"]["REDIS_URL"] + == "redis://default:test%26password%40@redis_container:6379" + ) + assert output["services"]["redis_container"]["image"] == "valkey/valkey:latest" + assert output["services"]["redis_container"]["user"] == "568:568" + assert output["services"]["redis_container"]["deploy"]["resources"]["limits"]["cpus"] == "2.0" + assert output["services"]["redis_container"]["deploy"]["resources"]["limits"]["memory"] == "4096M" + assert output["services"]["redis_container"]["healthcheck"] == { + "test": [ + "CMD", + "redis-cli", + "-h", + "127.0.0.1", + "-p", + "6379", + "-a", + "test&password@", + "ping", + ], + "interval": "30s", + "timeout": "5s", + "retries": 5, + "start_period": "15s", + "start_interval": "2s", + } + assert output["services"]["redis_container"]["volumes"] == [ + { + "type": "volume", + "source": "test_volume", + "target": "/data", + "read_only": False, + "volume": {"nocopy": False}, + } + ] + assert output["services"]["redis_container"]["environment"] == { + "TZ": "Etc/UTC", + "UMASK": "002", + "UMASK_SET": "002", + "NVIDIA_VISIBLE_DEVICES": "void", + "REDIS_PASSWORD": "test&password@", + } + assert output["services"]["redis_container"]["depends_on"] == { + "perms_container": {"condition": "service_completed_successfully"} + } + + +def test_add_mariadb_missing_config(mock_values): + render = Render(mock_values) + c1 = render.add_container("test_container", "test_image") + c1.healthcheck.disable() + with pytest.raises(Exception): + render.deps.mariadb( + "mariadb_container", + "test_image", + {"user": "test_user", "password": "test_password", "database": "test_database"}, # type: ignore + ) + + +def test_add_mariadb_unsupported_repo(mock_values): + mock_values["images"]["mariadb_image"] = {"repository": "unsupported_repo", "tag": "latest"} + render = Render(mock_values) + c1 = render.add_container("test_container", "test_image") + c1.healthcheck.disable() + perms_container = render.deps.perms("perms_container") + with pytest.raises(Exception): + render.deps.mariadb( + "mariadb_container", + "mariadb_image", + { + "user": "test_user", + "password": "test_password", + "database": "test_database", + "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, + }, + perms_container, + ) + + +def test_add_mariadb(mock_values): + mock_values["images"]["mariadb_image"] = {"repository": "mariadb", "tag": "latest"} + render = Render(mock_values) + c1 = render.add_container("test_container", "test_image") + c1.healthcheck.disable() + perms_container = render.deps.perms("perms_container") + m = render.deps.mariadb( + "mariadb_container", + "mariadb_image", + { + "user": "test_user", + "password": "test_password", + "database": "test_database", + "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, + }, + perms_container, + ) + if perms_container.has_actions(): + perms_container.activate() + m.container.depends.add_dependency("perms_container", "service_completed_successfully") + output = render.render() + assert "devices" not in output["services"]["mariadb_container"] + assert "reservations" not in output["services"]["mariadb_container"]["deploy"]["resources"] + assert output["services"]["mariadb_container"]["image"] == "mariadb:latest" + assert output["services"]["mariadb_container"]["user"] == "999:999" + assert output["services"]["mariadb_container"]["deploy"]["resources"]["limits"]["cpus"] == "2.0" + assert output["services"]["mariadb_container"]["deploy"]["resources"]["limits"]["memory"] == "4096M" + assert output["services"]["mariadb_container"]["healthcheck"] == { + "test": [ + "CMD", + "mariadb-admin", + "--user=root", + "--host=127.0.0.1", + "--port=3306", + "--password=test_password", + "ping", + ], + "interval": "30s", + "timeout": "5s", + "retries": 5, + "start_period": "15s", + "start_interval": "2s", + } + assert output["services"]["mariadb_container"]["volumes"] == [ + { + "type": "volume", + "source": "test_volume", + "target": "/var/lib/mysql", + "read_only": False, + "volume": {"nocopy": False}, + } + ] + assert output["services"]["mariadb_container"]["environment"] == { + "TZ": "Etc/UTC", + "UMASK": "002", + "UMASK_SET": "002", + "NVIDIA_VISIBLE_DEVICES": "void", + "MARIADB_USER": "test_user", + "MARIADB_PASSWORD": "test_password", + "MARIADB_ROOT_PASSWORD": "test_password", + "MARIADB_DATABASE": "test_database", + "MARIADB_AUTO_UPGRADE": "true", + } + assert output["services"]["mariadb_container"]["depends_on"] == { + "perms_container": {"condition": "service_completed_successfully"} + } + + +def test_add_perms_container(mock_values): + mock_values["ix_volumes"] = { + "test_dataset1": "/mnt/test/1", + "test_dataset2": "/mnt/test/2", + "test_dataset3": "/mnt/test/3", + } + mock_values["images"]["postgres_image"] = {"repository": "postgres", "tag": "17.7-bookworm"} + mock_values["images"]["redis_image"] = {"repository": "valkey/valkey", "tag": "latest"} + mock_values["images"]["mariadb_image"] = {"repository": "mariadb", "tag": "latest"} + render = Render(mock_values) + c1 = render.add_container("test_container", "test_image") + c1.healthcheck.disable() + + # fmt: off + volume_perms = {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}} + volume_no_perms = {"type": "volume", "volume_config": {"volume_name": "test_volume"}} + host_path_perms = {"type": "host_path", "host_path_config": {"path": "/mnt/test", "auto_permissions": True}} + host_path_no_perms = {"type": "host_path", "host_path_config": {"path": "/mnt/test"}} + host_path_acl_perms = {"type": "host_path", "host_path_config": {"acl": {"path": "/mnt/test"}, "acl_enable": True, "auto_permissions": True}} # noqa + ix_volume_no_perms = {"type": "ix_volume", "ix_volume_config": {"dataset_name": "test_dataset1"}} + ix_volume_perms = {"type": "ix_volume", "ix_volume_config": {"dataset_name": "test_dataset2", "auto_permissions": True}} # noqa + ix_volume_acl_perms = {"type": "ix_volume", "ix_volume_config": {"dataset_name": "test_dataset3", "acl_enable": True, "auto_permissions": True}} # noqa + temp_volume = {"type": "temporary", "volume_config": {"volume_name": "test_temp_volume"}} + read_only_volume = {"type": "volume", "read_only": True, "volume_config": {"volume_name": "test_read_only_volume", "auto_permissions": True}} # noqa + # fmt: on + + c1.add_storage("/some/path1", volume_perms) + c1.add_storage("/some/path2", volume_no_perms) + c1.add_storage("/some/path3", host_path_perms) + c1.add_storage("/some/path4", host_path_no_perms) + c1.add_storage("/some/path5", host_path_acl_perms) + c1.add_storage("/some/path6", ix_volume_no_perms) + c1.add_storage("/some/path7", ix_volume_perms) + c1.add_storage("/some/path8", ix_volume_acl_perms) + c1.add_storage("/some/path9", temp_volume) + c1.add_storage("/some/path10", read_only_volume) + + perms_container = render.deps.perms("test_perms_container") + perms_container.add_or_skip_action("data", volume_perms, {"uid": 1000, "gid": 1000, "mode": "check"}) + perms_container.add_or_skip_action("data2", volume_no_perms, {"uid": 1000, "gid": 1000, "mode": "check"}) + perms_container.add_or_skip_action("data3", host_path_perms, {"uid": 1000, "gid": 1000, "mode": "check"}) + perms_container.add_or_skip_action("data4", host_path_no_perms, {"uid": 1000, "gid": 1000, "mode": "check"}) + perms_container.add_or_skip_action("data5", host_path_acl_perms, {"uid": 1000, "gid": 1000, "mode": "check"}) + perms_container.add_or_skip_action("data6", ix_volume_no_perms, {"uid": 1000, "gid": 1000, "mode": "check"}) + perms_container.add_or_skip_action("data7", ix_volume_perms, {"uid": 1000, "gid": 1000, "mode": "check"}) + perms_container.add_or_skip_action("data8", ix_volume_acl_perms, {"uid": 1000, "gid": 1000, "mode": "check"}) + perms_container.add_or_skip_action("data9", temp_volume, {"uid": 1000, "gid": 1000, "mode": "check"}) + perms_container.add_or_skip_action("data10", read_only_volume, {"uid": 1000, "gid": 1000, "mode": "check"}) + postgres = render.deps.postgres( + "postgres_container", + "postgres_image", + { + "user": "test_user", + "password": "test_password", + "database": "test_database", + "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, + }, + perms_container, + ) + redis = render.deps.redis( + "redis_container", + "redis_image", + { + "password": "test_password", + "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, + }, + perms_container, + ) + mariadb = render.deps.mariadb( + "mariadb_container", + "mariadb_image", + { + "user": "test_user", + "password": "test_password", + "database": "test_database", + "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, + }, + perms_container, + ) + + if perms_container.has_actions(): + perms_container.activate() + c1.depends.add_dependency("test_perms_container", "service_completed_successfully") + postgres.container.depends.add_dependency("test_perms_container", "service_completed_successfully") + redis.container.depends.add_dependency("test_perms_container", "service_completed_successfully") + mariadb.container.depends.add_dependency("test_perms_container", "service_completed_successfully") + output = render.render() + assert output["services"]["test_perms_container"]["network_mode"] == "none" + assert output["services"]["test_container"]["depends_on"] == { + "test_perms_container": {"condition": "service_completed_successfully"} + } + # fmt: off + content = [ + {"read_only": False, "mount_path": "/mnt/permission/data", "is_temporary": False, "identifier": "data", "recursive": False, "mode": "check", "uid": 1000, "gid": 1000, "chmod": None}, # noqa + {"read_only": False, "mount_path": "/mnt/permission/data3", "is_temporary": False, "identifier": "data3", "recursive": False, "mode": "check", "uid": 1000, "gid": 1000, "chmod": None}, # noqa + {"read_only": False, "mount_path": "/mnt/permission/data6", "is_temporary": False, "identifier": "data6", "recursive": False, "mode": "check", "uid": 1000, "gid": 1000, "chmod": None}, # noqa + {"read_only": False, "mount_path": "/mnt/permission/data7", "is_temporary": False, "identifier": "data7", "recursive": False, "mode": "check", "uid": 1000, "gid": 1000, "chmod": None}, # noqa + {"read_only": False, "mount_path": "/mnt/permission/data9", "is_temporary": True, "identifier": "data9", "recursive": True, "mode": "check", "uid": 1000, "gid": 1000, "chmod": None}, # noqa + {"read_only": True, "mount_path": "/mnt/permission/data10", "is_temporary": False, "identifier": "data10", "recursive": False, "mode": "check", "uid": 1000, "gid": 1000, "chmod": None}, # noqa + {"read_only": False, "mount_path": "/mnt/permission/postgres_container_postgres_data", "is_temporary": False, "identifier": "postgres_container_postgres_data", "recursive": False, "mode": "check", "uid": 999, "gid": 999, "chmod": None}, # noqa + {"read_only": False, "mount_path": "/mnt/permission/redis_container_redis_data", "is_temporary": False, "identifier": "redis_container_redis_data", "recursive": False, "mode": "check", "uid": 568, "gid": 568, "chmod": None}, # noqa + {"read_only": False, "mount_path": "/mnt/permission/mariadb_container_mariadb_data", "is_temporary": False, "identifier": "mariadb_container_mariadb_data", "recursive": False, "mode": "check", "uid": 999, "gid": 999, "chmod": None}, # noqa + ] + # fmt: on + assert output["configs"]["permissions_actions_data"]["content"] == json.dumps(content) + assert output["services"]["test_perms_container"]["entrypoint"] == ["python3", "/script/permissions.py"] + + +def test_add_duplicate_perms_action(mock_values): + render = Render(mock_values) + c1 = render.add_container("test_container", "test_image") + c1.healthcheck.disable() + vol_config = {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}} + c1.add_storage("/some/path", vol_config) + perms_container = render.deps.perms("test_perms_container") + perms_container.add_or_skip_action("data", vol_config, {"uid": 1000, "gid": 1000, "mode": "check"}) + with pytest.raises(Exception): + perms_container.add_or_skip_action("data", vol_config, {"uid": 1000, "gid": 1000, "mode": "check"}) + + +def test_add_perm_action_without_auto_perms_enabled(mock_values): + render = Render(mock_values) + c1 = render.add_container("test_container", "test_image") + c1.healthcheck.disable() + vol_config = {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": False}} + c1.add_storage("/some/path", vol_config) + perms_container = render.deps.perms("test_perms_container") + perms_container.add_or_skip_action("data", vol_config, {"uid": 1000, "gid": 1000, "mode": "check"}) + if perms_container.has_actions(): + perms_container.activate() + c1.depends.add_dependency("test_perms_container", "service_completed_successfully") + output = render.render() + assert "configs" not in output + assert "ix-test_perms_container" not in output["services"] + assert "depends_on" not in output["services"]["test_container"] + + +def test_add_unsupported_postgres_version(mock_values): + mock_values["images"]["pg_image"] = {"repository": "postgres", "tag": "99"} + render = Render(mock_values) + c1 = render.add_container("test_container", "test_image") + c1.healthcheck.disable() + with pytest.raises(Exception): + render.deps.postgres( + "test_container", + "test_image", + {"user": "test_user", "password": "test_password", "database": "test_database"}, # type: ignore + ) + + +def test_add_postgres_with_invalid_tag(mock_values): + mock_values["images"]["pg_image"] = {"repository": "postgres", "tag": "latest"} + render = Render(mock_values) + c1 = render.add_container("test_container", "test_image") + c1.healthcheck.disable() + with pytest.raises(Exception): + render.deps.postgres( + "pg_container", + "pg_image", + {"user": "test_user", "password": "test_password", "database": "test_database"}, # type: ignore + ) + + +def test_no_upgrade_container_with_non_postgres_image(mock_values): + mock_values["images"]["postgres_image"] = { + "repository": "ghcr.io/immich-app/postgres", + "tag": "15-vectorchord0.4.3-pgvectors0.2.0", + } + render = Render(mock_values) + c1 = render.add_container("test_container", "test_image") + c1.healthcheck.disable() + perms_container = render.deps.perms("test_perms_container") + pg = render.deps.postgres( + "postgres_container", + "postgres_image", + { + "user": "test_user", + "password": "test_password", + "database": "test_database", + "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, + }, + perms_container, + ) + if perms_container.has_actions(): + perms_container.activate() + pg.add_dependency("test_perms_container", "service_completed_successfully") + output = render.render() + assert len(output["services"]) == 3 # c1, pg, perms + assert output["services"]["postgres_container"]["depends_on"] == { + "test_perms_container": {"condition": "service_completed_successfully"} + } + + +def test_postgres_with_upgrade_container(mock_values): + mock_values["images"]["pg_image"] = {"repository": "postgres", "tag": "16.6-bookworm"} + render = Render(mock_values) + c1 = render.add_container("test_container", "test_image") + c1.healthcheck.disable() + perms_container = render.deps.perms("test_perms_container") + pg = render.deps.postgres( + "postgres_container", + "pg_image", + { + "user": "test_user", + "password": "test_password", + "database": "test_database", + "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, + }, + perms_container, + ) + if perms_container.has_actions(): + perms_container.activate() + pg.add_dependency("test_perms_container", "service_completed_successfully") + output = render.render() + pg = output["services"]["postgres_container"] + pgup = output["services"]["postgres_container_upgrade"] + assert pg["volumes"] == pgup["volumes"] + assert pg["user"] == pgup["user"] + assert pgup["environment"]["TARGET_VERSION"] == "16" + assert pgup["environment"]["PGDATA"] == "/var/lib/postgresql/16/docker" + pgup_env = pgup["environment"] + pgup_env.pop("TARGET_VERSION") + assert pg["environment"] == pgup_env + assert pg["depends_on"] == { + "test_perms_container": {"condition": "service_completed_successfully"}, + "postgres_container_upgrade": {"condition": "service_completed_successfully"}, + } + assert pgup["depends_on"] == {"test_perms_container": {"condition": "service_completed_successfully"}} + assert pgup["restart"] == "on-failure:1" + assert pgup["healthcheck"] == {"disable": True} + assert pgup["image"] == "ixsystems/postgres-upgrade:1.0.0" + assert pgup["entrypoint"] == ["/bin/bash", "-c", "/upgrade.sh"] + + +def test_add_mongodb(mock_values): + mock_values["images"]["mongodb_image"] = {"repository": "mongo", "tag": "latest"} + render = Render(mock_values) + c1 = render.add_container("test_container", "test_image") + c1.healthcheck.disable() + perms_container = render.deps.perms("perms_container") + m = render.deps.mongodb( + "mongodb_container", + "mongodb_image", + { + "user": "test_user", + "password": "test_password", + "database": "test_database", + "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, + }, + perms_container, + ) + if perms_container.has_actions(): + perms_container.activate() + m.container.depends.add_dependency("perms_container", "service_completed_successfully") + output = render.render() + assert "devices" not in output["services"]["mongodb_container"] + assert "reservations" not in output["services"]["mongodb_container"]["deploy"]["resources"] + assert output["services"]["mongodb_container"]["image"] == "mongo:latest" + assert output["services"]["mongodb_container"]["user"] == "568:568" + assert output["services"]["mongodb_container"]["deploy"]["resources"]["limits"]["cpus"] == "2.0" + assert output["services"]["mongodb_container"]["deploy"]["resources"]["limits"]["memory"] == "4096M" + assert output["services"]["mongodb_container"]["healthcheck"] == { + "test": [ + "CMD", + "mongosh", + "--host", + "127.0.0.1", + "--port", + "27017", + "test_database", + "--eval", + 'db.adminCommand("ping")', + "--quiet", + ], + "interval": "30s", + "timeout": "5s", + "retries": 5, + "start_period": "15s", + "start_interval": "2s", + } + assert output["services"]["mongodb_container"]["volumes"] == [ + { + "type": "volume", + "source": "test_volume", + "target": "/data/db", + "read_only": False, + "volume": {"nocopy": False}, + } + ] + assert output["services"]["mongodb_container"]["environment"] == { + "TZ": "Etc/UTC", + "UMASK": "002", + "UMASK_SET": "002", + "NVIDIA_VISIBLE_DEVICES": "void", + "MONGO_INITDB_ROOT_USERNAME": "test_user", + "MONGO_INITDB_ROOT_PASSWORD": "test_password", + "MONGO_INITDB_DATABASE": "test_database", + } + assert output["services"]["mongodb_container"]["depends_on"] == { + "perms_container": {"condition": "service_completed_successfully"} + } + + +def test_add_mongodb_unsupported_repo(mock_values): + mock_values["images"]["mongo_image"] = {"repository": "unsupported_repo", "tag": "7"} + render = Render(mock_values) + c1 = render.add_container("test_container", "test_image") + c1.healthcheck.disable() + perms_container = render.deps.perms("perms_container") + with pytest.raises(Exception): + render.deps.mongodb( + "mongo_container", + "mongo_image", + { + "user": "test_user", + "password": "test_@password", + "database": "test_database", + "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, + }, + perms_container, + ) + + +def test_add_meilisearch(mock_values): + mock_values["images"]["meili_image"] = {"repository": "getmeili/meilisearch", "tag": "v1.17.0"} + render = Render(mock_values) + c1 = render.add_container("test_container", "test_image") + c1.healthcheck.disable() + perms_container = render.deps.perms("perms_container") + m = render.deps.meilisearch( + "meili_container", + "meili_image", + { + "master_key": "test_master_key", + "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, + }, + perms_container, + ) + if perms_container.has_actions(): + perms_container.activate() + m.container.depends.add_dependency("perms_container", "service_completed_successfully") + output = render.render() + assert "devices" not in output["services"]["meili_container"] + assert "reservations" not in output["services"]["meili_container"]["deploy"]["resources"] + assert output["services"]["meili_container"]["image"] == "getmeili/meilisearch:v1.17.0" + assert output["services"]["meili_container"]["user"] == "568:568" + assert output["services"]["meili_container"]["deploy"]["resources"]["limits"]["cpus"] == "2.0" + assert output["services"]["meili_container"]["deploy"]["resources"]["limits"]["memory"] == "4096M" + assert output["services"]["meili_container"]["healthcheck"] == { + "test": [ + "CMD", + "curl", + "--request", + "GET", + "--silent", + "--output", + "/dev/null", + "--show-error", + "--fail", + "http://127.0.0.1:7700/health", + ], + "interval": "30s", + "timeout": "5s", + "retries": 5, + "start_period": "15s", + "start_interval": "2s", + } + assert output["services"]["meili_container"]["volumes"] == [ + { + "type": "volume", + "source": "test_volume", + "target": "/meili_data", + "read_only": False, + "volume": {"nocopy": False}, + } + ] + assert output["services"]["meili_container"]["environment"] == { + "TZ": "Etc/UTC", + "UMASK": "002", + "UMASK_SET": "002", + "NVIDIA_VISIBLE_DEVICES": "void", + "MEILI_MASTER_KEY": "test_master_key", + "MEILI_HTTP_ADDR": "0.0.0.0:7700", + "MEILI_NO_ANALYTICS": "true", + "MEILI_EXPERIMENTAL_DUMPLESS_UPGRADE": "true", + } + assert output["services"]["meili_container"]["depends_on"] == { + "perms_container": {"condition": "service_completed_successfully"} + } + + +def test_add_meilisearch_unsupported_repo(mock_values): + mock_values["images"]["meili_image"] = {"repository": "unsupported_repo", "tag": "7"} + render = Render(mock_values) + c1 = render.add_container("test_container", "test_image") + c1.healthcheck.disable() + perms_container = render.deps.perms("perms_container") + with pytest.raises(Exception): + render.deps.meilisearch( + "meili_container", + "meili_image", + { + "master_key": "test_master_key", + "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, + }, + perms_container, + ) + + +def test_add_elasticsearch(mock_values): + mock_values["images"]["elastic_image"] = { + "repository": "elasticsearch", + "tag": "9.1.2", + } + render = Render(mock_values) + c1 = render.add_container("test_container", "test_image") + c1.healthcheck.disable() + perms_container = render.deps.perms("perms_container") + m = render.deps.elasticsearch( + "elastic_container", + "elastic_image", + { + "password": "test_password", + "node_name": "some_test_node", + "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, + }, + perms_container, + ) + if perms_container.has_actions(): + perms_container.activate() + m.container.depends.add_dependency("perms_container", "service_completed_successfully") + output = render.render() + assert "devices" not in output["services"]["elastic_container"] + assert "reservations" not in output["services"]["elastic_container"]["deploy"]["resources"] + assert output["services"]["elastic_container"]["image"] == "elasticsearch:9.1.2" + assert output["services"]["elastic_container"]["user"] == "1000:1000" + assert output["services"]["elastic_container"]["deploy"]["resources"]["limits"]["cpus"] == "2.0" + assert output["services"]["elastic_container"]["deploy"]["resources"]["limits"]["memory"] == "4096M" + assert output["services"]["elastic_container"]["healthcheck"] == { + "test": [ + "CMD", + "curl", + "--request", + "GET", + "--silent", + "--output", + "/dev/null", + "--show-error", + "--fail", + "--header", + "Authorization: Basic ZWxhc3RpYzp0ZXN0X3Bhc3N3b3Jk", + "http://127.0.0.1:9200/_cluster/health?local=true", + ], # noqa + "interval": "30s", + "timeout": "5s", + "retries": 5, + "start_period": "15s", + "start_interval": "2s", + } + assert output["services"]["elastic_container"]["volumes"] == [ + { + "type": "volume", + "source": "test_volume", + "target": "/usr/share/elasticsearch/data", + "read_only": False, + "volume": {"nocopy": False}, + } + ] + assert output["services"]["elastic_container"]["environment"] == { + "TZ": "Etc/UTC", + "UMASK": "002", + "UMASK_SET": "002", + "NVIDIA_VISIBLE_DEVICES": "void", + "ELASTIC_PASSWORD": "test_password", + "http.port": "9200", + "path.data": "/usr/share/elasticsearch/data", + "path.repo": "/usr/share/elasticsearch/data/snapshots", + "node.name": "some_test_node", + "discovery.type": "single-node", + "xpack.security.enabled": "true", + "xpack.security.transport.ssl.enabled": "false", + } + assert output["services"]["elastic_container"]["depends_on"] == { + "perms_container": {"condition": "service_completed_successfully"} + } + + +def test_add_elasticsearch_unsupported_repo(mock_values): + mock_values["images"]["elastic_image"] = {"repository": "unsupported_repo", "tag": "7"} + render = Render(mock_values) + c1 = render.add_container("test_container", "test_image") + c1.healthcheck.disable() + perms_container = render.deps.perms("perms_container") + with pytest.raises(Exception): + render.deps.elasticsearch( + "elastic_container", + "elastic_image", + { + "password": "test_password", + "node_name": "some_test_node", + "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, + }, + perms_container, + ) + + +def test_add_solr(mock_values): + mock_values["images"]["solr_image"] = {"repository": "solr", "tag": "9.9.0"} + render = Render(mock_values) + c1 = render.add_container("test_container", "test_image") + c1.healthcheck.disable() + perms_container = render.deps.perms("perms_container") + m = render.deps.solr( + "solr_container", + "solr_image", + { + "core": "test_core", + "modules": ["analysis-extras", "some-other-module"], + "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, + }, + perms_container, + ) + if perms_container.has_actions(): + perms_container.activate() + m.container.depends.add_dependency("perms_container", "service_completed_successfully") + output = render.render() + assert "devices" not in output["services"]["solr_container"] + assert "reservations" not in output["services"]["solr_container"]["deploy"]["resources"] + assert output["services"]["solr_container"]["image"] == "solr:9.9.0" + assert output["services"]["solr_container"]["user"] == "568:568" + assert output["services"]["solr_container"]["deploy"]["resources"]["limits"]["cpus"] == "2.0" + assert output["services"]["solr_container"]["deploy"]["resources"]["limits"]["memory"] == "4096M" + assert output["services"]["solr_container"]["healthcheck"] == { + "test": [ + "CMD", + "curl", + "--request", + "GET", + "--silent", + "--output", + "/dev/null", + "--show-error", + "--fail", + "http://127.0.0.1:8983/solr/test_core/admin/ping", + ], + "interval": "30s", + "timeout": "5s", + "retries": 5, + "start_period": "15s", + "start_interval": "2s", + } + assert output["services"]["solr_container"]["volumes"] == [ + { + "type": "volume", + "source": "test_volume", + "target": "/var/solr", + "read_only": False, + "volume": {"nocopy": False}, + } + ] + assert output["services"]["solr_container"]["environment"] == { + "TZ": "Etc/UTC", + "UMASK": "002", + "UMASK_SET": "002", + "NVIDIA_VISIBLE_DEVICES": "void", + "SOLR_PORT": "8983", + "SOLR_MODULES": "analysis-extras,some-other-module", + } + assert output["services"]["solr_container"]["command"] == ["solr-precreate", "test_core"] + assert output["services"]["solr_container"]["depends_on"] == { + "perms_container": {"condition": "service_completed_successfully"} + } + + +def test_add_solr_unsupported_repo(mock_values): + mock_values["images"]["solr_image"] = {"repository": "unsupported_repo", "tag": "7"} + render = Render(mock_values) + c1 = render.add_container("test_container", "test_image") + c1.healthcheck.disable() + perms_container = render.deps.perms("perms_container") + with pytest.raises(Exception): + render.deps.solr( + "solr_container", + "solr_image", + { + "core": "test_core", + "volume": {"type": "volume", "volume_config": {"volume_name": "test_volume", "auto_permissions": True}}, + }, + perms_container, + ) + + +def test_add_tika(mock_values): + mock_values["images"]["tika_image"] = {"repository": "apache/tika", "tag": "3.2.3.0-full"} + render = Render(mock_values) + c1 = render.add_container("test_container", "test_image") + c1.healthcheck.disable() + render.deps.tika( + "tika_container", + "tika_image", + { + "port": 10999, + }, + ) + output = render.render() + assert "devices" not in output["services"]["tika_container"] + assert "reservations" not in output["services"]["tika_container"]["deploy"]["resources"] + assert output["services"]["tika_container"]["image"] == "apache/tika:3.2.3.0-full" + assert output["services"]["tika_container"]["user"] == "568:568" + assert output["services"]["tika_container"]["deploy"]["resources"]["limits"]["cpus"] == "2.0" + assert output["services"]["tika_container"]["deploy"]["resources"]["limits"]["memory"] == "4096M" + assert output["services"]["tika_container"]["healthcheck"] == { + "test": [ + "CMD", + "wget", + "--quiet", + "-O", + "/dev/null", + "http://127.0.0.1:10999/tika", + ], + "interval": "30s", + "timeout": "5s", + "retries": 5, + "start_period": "15s", + "start_interval": "2s", + } + assert output["services"]["tika_container"]["environment"] == { + "TZ": "Etc/UTC", + "UMASK": "002", + "UMASK_SET": "002", + "NVIDIA_VISIBLE_DEVICES": "void", + } + assert output["services"]["tika_container"]["command"] == ["--port", "10999"] + + +def test_add_tika_unsupported_repo(mock_values): + mock_values["images"]["tika_image"] = {"repository": "unsupported_repo", "tag": "7"} + render = Render(mock_values) + c1 = render.add_container("test_container", "test_image") + c1.healthcheck.disable() + with pytest.raises(Exception): + render.deps.tika( + "tika_container", + "tika_image", + {}, + ) diff --git a/library/2.1.65/tests/test_device.py b/library/2.1.66/tests/test_device.py similarity index 100% rename from library/2.1.65/tests/test_device.py rename to library/2.1.66/tests/test_device.py diff --git a/library/2.1.65/tests/test_device_cgroup_rules.py b/library/2.1.66/tests/test_device_cgroup_rules.py similarity index 100% rename from library/2.1.65/tests/test_device_cgroup_rules.py rename to library/2.1.66/tests/test_device_cgroup_rules.py diff --git a/library/2.1.65/tests/test_dns.py b/library/2.1.66/tests/test_dns.py similarity index 100% rename from library/2.1.65/tests/test_dns.py rename to library/2.1.66/tests/test_dns.py diff --git a/library/2.1.65/tests/test_environment.py b/library/2.1.66/tests/test_environment.py similarity index 100% rename from library/2.1.65/tests/test_environment.py rename to library/2.1.66/tests/test_environment.py diff --git a/library/2.1.65/tests/test_expose.py b/library/2.1.66/tests/test_expose.py similarity index 100% rename from library/2.1.65/tests/test_expose.py rename to library/2.1.66/tests/test_expose.py diff --git a/library/2.1.65/tests/test_extra_hosts.py b/library/2.1.66/tests/test_extra_hosts.py similarity index 100% rename from library/2.1.65/tests/test_extra_hosts.py rename to library/2.1.66/tests/test_extra_hosts.py diff --git a/library/2.1.65/tests/test_formatter.py b/library/2.1.66/tests/test_formatter.py similarity index 100% rename from library/2.1.65/tests/test_formatter.py rename to library/2.1.66/tests/test_formatter.py diff --git a/library/2.1.65/tests/test_functions.py b/library/2.1.66/tests/test_functions.py similarity index 100% rename from library/2.1.65/tests/test_functions.py rename to library/2.1.66/tests/test_functions.py diff --git a/library/2.1.65/tests/test_healthcheck.py b/library/2.1.66/tests/test_healthcheck.py similarity index 100% rename from library/2.1.65/tests/test_healthcheck.py rename to library/2.1.66/tests/test_healthcheck.py diff --git a/library/2.1.65/tests/test_labels.py b/library/2.1.66/tests/test_labels.py similarity index 100% rename from library/2.1.65/tests/test_labels.py rename to library/2.1.66/tests/test_labels.py diff --git a/library/2.1.65/tests/test_notes.py b/library/2.1.66/tests/test_notes.py similarity index 100% rename from library/2.1.65/tests/test_notes.py rename to library/2.1.66/tests/test_notes.py diff --git a/library/2.1.65/tests/test_portal.py b/library/2.1.66/tests/test_portal.py similarity index 100% rename from library/2.1.65/tests/test_portal.py rename to library/2.1.66/tests/test_portal.py diff --git a/library/2.1.65/tests/test_ports.py b/library/2.1.66/tests/test_ports.py similarity index 100% rename from library/2.1.65/tests/test_ports.py rename to library/2.1.66/tests/test_ports.py diff --git a/library/2.1.65/tests/test_render.py b/library/2.1.66/tests/test_render.py similarity index 100% rename from library/2.1.65/tests/test_render.py rename to library/2.1.66/tests/test_render.py diff --git a/library/2.1.65/tests/test_resources.py b/library/2.1.66/tests/test_resources.py similarity index 100% rename from library/2.1.65/tests/test_resources.py rename to library/2.1.66/tests/test_resources.py diff --git a/library/2.1.65/tests/test_restart.py b/library/2.1.66/tests/test_restart.py similarity index 100% rename from library/2.1.65/tests/test_restart.py rename to library/2.1.66/tests/test_restart.py diff --git a/library/2.1.65/tests/test_security_opts.py b/library/2.1.66/tests/test_security_opts.py similarity index 100% rename from library/2.1.65/tests/test_security_opts.py rename to library/2.1.66/tests/test_security_opts.py diff --git a/library/2.1.65/tests/test_sysctls.py b/library/2.1.66/tests/test_sysctls.py similarity index 100% rename from library/2.1.65/tests/test_sysctls.py rename to library/2.1.66/tests/test_sysctls.py diff --git a/library/2.1.65/tests/test_validations.py b/library/2.1.66/tests/test_validations.py similarity index 100% rename from library/2.1.65/tests/test_validations.py rename to library/2.1.66/tests/test_validations.py diff --git a/library/2.1.65/tests/test_volumes.py b/library/2.1.66/tests/test_volumes.py similarity index 100% rename from library/2.1.65/tests/test_volumes.py rename to library/2.1.66/tests/test_volumes.py diff --git a/library/2.1.65/tmpfs.py b/library/2.1.66/tmpfs.py similarity index 100% rename from library/2.1.65/tmpfs.py rename to library/2.1.66/tmpfs.py diff --git a/library/2.1.65/validations.py b/library/2.1.66/validations.py similarity index 100% rename from library/2.1.65/validations.py rename to library/2.1.66/validations.py diff --git a/library/2.1.65/volume_mount.py b/library/2.1.66/volume_mount.py similarity index 100% rename from library/2.1.65/volume_mount.py rename to library/2.1.66/volume_mount.py diff --git a/library/2.1.65/volume_mount_types.py b/library/2.1.66/volume_mount_types.py similarity index 100% rename from library/2.1.65/volume_mount_types.py rename to library/2.1.66/volume_mount_types.py diff --git a/library/2.1.65/volume_sources.py b/library/2.1.66/volume_sources.py similarity index 100% rename from library/2.1.65/volume_sources.py rename to library/2.1.66/volume_sources.py diff --git a/library/2.1.65/volume_types.py b/library/2.1.66/volume_types.py similarity index 100% rename from library/2.1.65/volume_types.py rename to library/2.1.66/volume_types.py diff --git a/library/2.1.65/volumes.py b/library/2.1.66/volumes.py similarity index 100% rename from library/2.1.65/volumes.py rename to library/2.1.66/volumes.py diff --git a/library/hashes.yaml b/library/hashes.yaml index e100af1b67..749843242b 100644 --- a/library/hashes.yaml +++ b/library/hashes.yaml @@ -1,2 +1,2 @@ 0.0.1: f074617a82a86d2a6cc78a4c8a4296fc9d168e456f12713e50c696557b302133 -2.1.65: f92a9ee78c78fc77f86e7d8b545bd4c605c31c599e2c5da59f1615aa516cb8b5 +2.1.66: 986abcd60fd0cc6277c80d55d2798356ddda1bd6348580ca7198b003571707fa