lib/config: fix conn_max_age parsing (#13370) Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space> Co-authored-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
This commit is contained in:
		![98988430+gcp-cherry-pick-bot[bot]@users.noreply.github.com](/assets/img/avatar_default.png) gcp-cherry-pick-bot[bot]
					gcp-cherry-pick-bot[bot]
				
			
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			 GitHub
						GitHub
					
				
			
						parent
						
							e9764333ea
						
					
				
				
					commit
					35c739ee84
				
			| @ -282,16 +282,14 @@ class ConfigLoader: | |||||||
|  |  | ||||||
|     def get_optional_int(self, path: str, default=None) -> int | None: |     def get_optional_int(self, path: str, default=None) -> int | None: | ||||||
|         """Wrapper for get that converts value into int or None if set""" |         """Wrapper for get that converts value into int or None if set""" | ||||||
|         value = self.get(path, default) |         value = self.get(path, UNSET) | ||||||
|         if value is UNSET: |         if value is UNSET: | ||||||
|             return default |             return default | ||||||
|         try: |         try: | ||||||
|             return int(value) |             return int(value) | ||||||
|         except (ValueError, TypeError) as exc: |         except (ValueError, TypeError) as exc: | ||||||
|             if value is None or (isinstance(value, str) and value.lower() == "null"): |             if value is None or (isinstance(value, str) and value.lower() == "null"): | ||||||
|                 return default |                 return None | ||||||
|             if value is UNSET: |  | ||||||
|                 return default |  | ||||||
|             self.log("warning", "Failed to parse config as int", path=path, exc=str(exc)) |             self.log("warning", "Failed to parse config as int", path=path, exc=str(exc)) | ||||||
|             return default |             return default | ||||||
|  |  | ||||||
| @ -372,9 +370,9 @@ def django_db_config(config: ConfigLoader | None = None) -> dict: | |||||||
|                 "sslcert": config.get("postgresql.sslcert"), |                 "sslcert": config.get("postgresql.sslcert"), | ||||||
|                 "sslkey": config.get("postgresql.sslkey"), |                 "sslkey": config.get("postgresql.sslkey"), | ||||||
|             }, |             }, | ||||||
|             "CONN_MAX_AGE": CONFIG.get_optional_int("postgresql.conn_max_age", 0), |             "CONN_MAX_AGE": config.get_optional_int("postgresql.conn_max_age", 0), | ||||||
|             "CONN_HEALTH_CHECKS": CONFIG.get_bool("postgresql.conn_health_checks", False), |             "CONN_HEALTH_CHECKS": config.get_bool("postgresql.conn_health_checks", False), | ||||||
|             "DISABLE_SERVER_SIDE_CURSORS": CONFIG.get_bool( |             "DISABLE_SERVER_SIDE_CURSORS": config.get_bool( | ||||||
|                 "postgresql.disable_server_side_cursors", False |                 "postgresql.disable_server_side_cursors", False | ||||||
|             ), |             ), | ||||||
|             "TEST": { |             "TEST": { | ||||||
| @ -383,8 +381,8 @@ def django_db_config(config: ConfigLoader | None = None) -> dict: | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     conn_max_age = CONFIG.get_optional_int("postgresql.conn_max_age", UNSET) |     conn_max_age = config.get_optional_int("postgresql.conn_max_age", UNSET) | ||||||
|     disable_server_side_cursors = CONFIG.get_bool("postgresql.disable_server_side_cursors", UNSET) |     disable_server_side_cursors = config.get_bool("postgresql.disable_server_side_cursors", UNSET) | ||||||
|     if config.get_bool("postgresql.use_pgpool", False): |     if config.get_bool("postgresql.use_pgpool", False): | ||||||
|         db["default"]["DISABLE_SERVER_SIDE_CURSORS"] = True |         db["default"]["DISABLE_SERVER_SIDE_CURSORS"] = True | ||||||
|         if disable_server_side_cursors is not UNSET: |         if disable_server_side_cursors is not UNSET: | ||||||
|  | |||||||
| @ -158,6 +158,18 @@ class TestConfig(TestCase): | |||||||
|             test_obj = Test() |             test_obj = Test() | ||||||
|             dumps(test_obj, indent=4, cls=AttrEncoder) |             dumps(test_obj, indent=4, cls=AttrEncoder) | ||||||
|  |  | ||||||
|  |     def test_get_optional_int(self): | ||||||
|  |         config = ConfigLoader() | ||||||
|  |         self.assertEqual(config.get_optional_int("foo", 21), 21) | ||||||
|  |         self.assertEqual(config.get_optional_int("foo"), None) | ||||||
|  |         config.set("foo", "21") | ||||||
|  |         self.assertEqual(config.get_optional_int("foo"), 21) | ||||||
|  |         self.assertEqual(config.get_optional_int("foo", 0), 21) | ||||||
|  |         self.assertEqual(config.get_optional_int("foo", "null"), 21) | ||||||
|  |         config.set("foo", "null") | ||||||
|  |         self.assertEqual(config.get_optional_int("foo"), None) | ||||||
|  |         self.assertEqual(config.get_optional_int("foo", 21), None) | ||||||
|  |  | ||||||
|     @mock.patch.dict(environ, check_deprecations_env_vars) |     @mock.patch.dict(environ, check_deprecations_env_vars) | ||||||
|     def test_check_deprecations(self): |     def test_check_deprecations(self): | ||||||
|         """Test config key re-write for deprecated env vars""" |         """Test config key re-write for deprecated env vars""" | ||||||
| @ -221,6 +233,16 @@ class TestConfig(TestCase): | |||||||
|             }, |             }, | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|  |     def test_db_conn_max_age(self): | ||||||
|  |         """Test DB conn_max_age Config""" | ||||||
|  |         config = ConfigLoader() | ||||||
|  |         config.set("postgresql.conn_max_age", "null") | ||||||
|  |         conf = django_db_config(config) | ||||||
|  |         self.assertEqual( | ||||||
|  |             conf["default"]["CONN_MAX_AGE"], | ||||||
|  |             None, | ||||||
|  |         ) | ||||||
|  |  | ||||||
|     def test_db_read_replicas(self): |     def test_db_read_replicas(self): | ||||||
|         """Test read replicas""" |         """Test read replicas""" | ||||||
|         config = ConfigLoader() |         config = ConfigLoader() | ||||||
|  | |||||||
| @ -77,7 +77,7 @@ To check if your config has been applied correctly, you can run the following co | |||||||
| - `AUTHENTIK_POSTGRESQL__SSLCERT`: Path to x509 client certificate to authenticate to server | - `AUTHENTIK_POSTGRESQL__SSLCERT`: Path to x509 client certificate to authenticate to server | ||||||
| - `AUTHENTIK_POSTGRESQL__SSLKEY`: Path to private key of `SSLCERT` certificate | - `AUTHENTIK_POSTGRESQL__SSLKEY`: Path to private key of `SSLCERT` certificate | ||||||
| - `AUTHENTIK_POSTGRESQL__CONN_MAX_AGE`: Database connection lifetime. Defaults to `0` (no persistent connections). Can be set to `null` for unlimited persistent connections. See [Django's documentation](https://docs.djangoproject.com/en/stable/ref/settings/#conn-max-age) for more details. | - `AUTHENTIK_POSTGRESQL__CONN_MAX_AGE`: Database connection lifetime. Defaults to `0` (no persistent connections). Can be set to `null` for unlimited persistent connections. See [Django's documentation](https://docs.djangoproject.com/en/stable/ref/settings/#conn-max-age) for more details. | ||||||
| - `AUTHENTIK_POSTGRESQL__CONN_HEALTH_CHECK`: Existing persistent database connections will be health checked before they are reused if set to `true`. Defaults to `false`. See [Django's documentation](https://docs.djangoproject.com/en/stable/ref/settings/#conn-health-checks) for more details. | - `AUTHENTIK_POSTGRESQL__CONN_HEALTH_CHECKS`: Existing persistent database connections will be health checked before they are reused if set to `true`. Defaults to `false`. See [Django's documentation](https://docs.djangoproject.com/en/stable/ref/settings/#conn-health-checks) for more details. | ||||||
| - `AUTHENTIK_POSTGRESQL__DISABLE_SERVER_SIDE_CURSORS`: Disable server side cursors when set to `true`. Defaults to `false`. See [Django's documentation](https://docs.djangoproject.com/en/stable/ref/settings/#disable-server-side-cursors) for more details. | - `AUTHENTIK_POSTGRESQL__DISABLE_SERVER_SIDE_CURSORS`: Disable server side cursors when set to `true`. Defaults to `false`. See [Django's documentation](https://docs.djangoproject.com/en/stable/ref/settings/#disable-server-side-cursors) for more details. | ||||||
|  |  | ||||||
| The PostgreSQL settings `HOST`, `PORT`, `USER`, and `PASSWORD` support hot-reloading. Adding and removing read replicas doesn't support hot-reloading. | The PostgreSQL settings `HOST`, `PORT`, `USER`, and `PASSWORD` support hot-reloading. Adding and removing read replicas doesn't support hot-reloading. | ||||||
| @ -108,7 +108,7 @@ The same PostgreSQL settings as described above are used for each read replica. | |||||||
| - `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__SSLCERT` | - `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__SSLCERT` | ||||||
| - `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__SSLKEY` | - `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__SSLKEY` | ||||||
| - `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__CONN_MAX_AGE` | - `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__CONN_MAX_AGE` | ||||||
| - `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__CONN_HEALTH_CHECK` | - `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__CONN_HEALTH_CHECKS` | ||||||
| - `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__DISABLE_SERVER_SIDE_CURSORS` | - `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__DISABLE_SERVER_SIDE_CURSORS` | ||||||
|  |  | ||||||
| ### Using a PostgreSQL connection pooler (PgBouncer or PgPool) | ### Using a PostgreSQL connection pooler (PgBouncer or PgPool) | ||||||
| @ -125,7 +125,7 @@ When your PostgreSQL database(s) are running behind a connection pooler, like Pg | |||||||
|  |  | ||||||
|     Using a connection pooler in transaction pool mode (e.g. PgPool, or PgBouncer in transaction or statement pool mode) requires disabling server-side cursors, so this setting must be set to `false`. |     Using a connection pooler in transaction pool mode (e.g. PgPool, or PgBouncer in transaction or statement pool mode) requires disabling server-side cursors, so this setting must be set to `false`. | ||||||
|  |  | ||||||
| Additionally, you can set `AUTHENTIK_POSTGRESQL__CONN_HEALTH_CHECK` to perform health checks on persistent database connections before they are reused. | Additionally, you can set `AUTHENTIK_POSTGRESQL__CONN_HEALTH_CHECKS` to perform health checks on persistent database connections before they are reused. | ||||||
|  |  | ||||||
| ## Redis Settings | ## Redis Settings | ||||||
|  |  | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user