diff --git a/libs/pageserver_api/src/models.rs b/libs/pageserver_api/src/models.rs index cf3252a9ae..e49b7051d2 100644 --- a/libs/pageserver_api/src/models.rs +++ b/libs/pageserver_api/src/models.rs @@ -117,6 +117,7 @@ impl TenantCreateRequest { #[serde_as] #[derive(Serialize, Deserialize)] pub struct TenantConfigRequest { + #[serde_as(as = "DisplayFromStr")] pub tenant_id: TenantId, #[serde(default)] #[serde_as(as = "Option")] diff --git a/pageserver/src/tenant.rs b/pageserver/src/tenant.rs index 80b65d281f..4fcb1e3ba3 100644 --- a/pageserver/src/tenant.rs +++ b/pageserver/src/tenant.rs @@ -1690,7 +1690,7 @@ impl Tenant { let _enter = info_span!("saving tenantconf").entered(); info!("persisting tenantconf to {}", target_config_path.display()); - // TODO this will prepend comments endlessly + // TODO this will prepend comments endlessly ? let mut conf_content = r#"# This file contains a specific per-tenant's config. # It is read in case of pageserver restart. @@ -1703,7 +1703,10 @@ impl Tenant { let mut target_config_file = VirtualFile::open_with_options( target_config_path, - OpenOptions::new().write(true).create_new(first_save), + OpenOptions::new() + .truncate(true) // This needed for overwriting with small config files + .write(true) + .create_new(first_save), )?; target_config_file diff --git a/test_runner/regress/test_tenant_conf.py b/test_runner/regress/test_tenant_conf.py index 46a945a58b..6d621fbb77 100644 --- a/test_runner/regress/test_tenant_conf.py +++ b/test_runner/regress/test_tenant_conf.py @@ -133,3 +133,28 @@ tenant_config={checkpoint_distance = 10000, compaction_target_size = 1048576}""" "pitr_interval": 2592000, }.items() ) + + # update the config with very short config and make sure no trailing chars are left from previous config + env.neon_cli.config_tenant( + tenant_id=tenant, + conf={ + "pitr_interval": "1 min", + }, + ) + + # restart the pageserver and ensure that the config is still correct + env.pageserver.stop() + env.pageserver.start() + + with closing(env.pageserver.connect()) as psconn: + with psconn.cursor(cursor_factory=psycopg2.extras.RealDictCursor) as pscur: + pscur.execute(f"show {tenant}") + res = pscur.fetchone() + log.info(f"after restart res: {res}") + assert all( + i in res.items() + for i in { + "compaction_period": 20, + "pitr_interval": 60, + }.items() + )