response = requests.post(self._create_url("/config/server/workers"), data=str(n))
print(response.text)
+ def set_groupid(self, gid: str) -> None:
+ response = requests.post(self._create_url("/config/server/groupid"), data=f'"{gid}"')
+ print(response.text)
+
def set_static_hints(self, hints: Dict[str, List[Union[ipaddress.IPv4Address, ipaddress.IPv6Address]]]) -> None:
payload = {name: [str(a) for a in addrs] for name, addrs in hints.items()}
response = requests.post(self._create_url("/config/static-hints/hints"), json=payload)
client.set_num_workers(instances)
+@main.command(help="Set the manager groupid")
+@click.argument("gid", type=str, nargs=1)
+@click.pass_context
+def groupid(ctx: click.Context, gid: str) -> None:
+ client = KnotManagerClient(ctx.obj[BASE_URL])
+ client.set_groupid(gid)
+
+
@main.command("one-static-hint", help="Set one inline static-hint hints (replaces old static hints)")
@click.argument("name", type=str, nargs=1)
@click.argument("ip", type=str, nargs=1)
return config.cache.storage.to_path()
-def kresd_config_file(_config: KresConfig, kres_id: KresID) -> Path:
- return Path(f"kresd_{kres_id}.conf")
+def kresd_config_file(config: KresConfig, kres_id: KresID) -> Path:
+ return Path(f"{config.server.groupid}kresd_{kres_id}.conf")
def supervisord_config_file(_config: KresConfig) -> Path:
KRESD_SERVICE_BASE_PATTERN = re.compile(r"^kresd_([0-9]+).service$")
+def service_name_remove_prefix(service_name: str, prefix: str) -> str:
+ return service_name[len(prefix) :] if service_name.startswith(prefix) else service_name # noqa: E203
+
+
def kres_id_from_service_name(service_name: str, config: KresConfig) -> KresID:
- base_service_name = service_name
- if service_name.startswith(config.server.groupid):
- base_service_name = service_name[len(config.server.groupid) :] # noqa: E203
- kid = KRESD_SERVICE_BASE_PATTERN.search(base_service_name)
+ service_name_noprefix = service_name_remove_prefix(service_name, config.server.groupid)
+ kid = KRESD_SERVICE_BASE_PATTERN.search(service_name_noprefix)
if kid:
return KresID.from_string(kid.groups()[0])
return KresID.from_string(service_name)
def is_service_name_ours(service_name: str, config: KresConfig) -> bool:
- if service_name.startswith(config.server.groupid):
- service_name = service_name[len(config.server.groupid) :] # noqa: E203
- is_ours = service_name == GC_SERVICE_BASE_NAME
- is_ours |= bool(KRESD_SERVICE_BASE_PATTERN.match(service_name))
+ service_name_noprefix = service_name_remove_prefix(service_name, config.server.groupid)
+ is_ours = service_name_noprefix == GC_SERVICE_BASE_NAME
+ is_ours |= bool(KRESD_SERVICE_BASE_PATTERN.match(service_name_noprefix))
return is_ours
async def _reconfigure(self, config: KresConfig) -> None:
await self._reconfigure_listen_address(config)
- async def _deny_listen_address_changes(self, config_old: KresConfig, config_new: KresConfig) -> Result[None, str]:
+ async def _deny_management_changes(self, config_old: KresConfig, config_new: KresConfig) -> Result[None, str]:
if config_old.server.management != config_new.server.management:
return Result.err(
- "Changing API listen address dynamically is not allowed as it's really dangerous. If you"
- " really need this feature, please contact the developers and explain why. Technically,"
+ "/server/management: Changing management API address/unix-socket dynamically is not allowed as it's really dangerous."
+ " If you really need this feature, please contact the developers and explain why. Technically,"
" there are no problems in supporting it. We are only blocking the dynamic changes because"
" we think the consequences of leaving this footgun unprotected are worse than its usefulness."
)
+ return Result.ok(None)
+ async def _deny_groupid_changes(self, config_old: KresConfig, config_new: KresConfig) -> Result[None, str]:
+ if config_old.server.groupid != config_new.server.groupid:
+ return Result.err(
+ "/server/groupid: Based on the groupid, the manager recognizes his subprocesses,"
+ " so it is not possible to change it while services are running."
+ )
return Result.ok(None)
async def sigint_handler(self) -> None:
asyncio_compat.add_async_signal_handler(signal.SIGINT, self.sigint_handler)
asyncio_compat.add_async_signal_handler(signal.SIGHUP, self.sighup_handler)
await self.runner.setup()
- await self.config_store.register_verifier(self._deny_listen_address_changes)
+ await self.config_store.register_verifier(self._deny_management_changes)
+ await self.config_store.register_verifier(self._deny_groupid_changes)
await self.config_store.register_on_change_callback(self._reconfigure)
async def wait_for_shutdown(self) -> None: