Skip to content

Commit 945f346

Browse files
committed
reload config changes, partial fix for #3
1 parent 932ca5d commit 945f346

File tree

4 files changed

+66
-20
lines changed

4 files changed

+66
-20
lines changed

supervisor_pydantic/client/xmlrpc.py

+32-12
Original file line numberDiff line numberDiff line change
@@ -130,24 +130,29 @@ def _build_rpcurl(self, username: Optional[str], password: Optional[str]) -> str
130130
def getAllProcessInfo(self) -> List[ProcessInfo]:
131131
return [ProcessInfo(**_) for _ in self._client.supervisor.getAllProcessInfo()]
132132

133-
def getState(self):
133+
def getState(self) -> SupervisorState:
134134
return SupervisorState(self._client.supervisor.getState()["statecode"])
135135

136136
# def readLog(self):
137137
# return self._client.supervisor.readLog(0, 0)
138138

139-
def restart(self):
140-
return self._client.supervisor.restart()
139+
def restart(self) -> SupervisorState:
140+
self._client.supervisor.restart()
141+
return self.getState()
141142

142-
def shutdown(self):
143-
return self._client.supervisor.shutdown()
143+
def shutdown(self) -> SupervisorState:
144+
self._client.supervisor.shutdown()
145+
return self.getState()
144146

145147
###################
146148
# process methods #
147149
###################
148-
def getProcessInfo(self, name: str):
150+
def getProcessInfo(self, name: str) -> ProcessInfo:
149151
if name not in self._cfg.program:
150152
raise RuntimeError(f"Unknown process: {name}")
153+
return self._getProcessInfoInternal(name)
154+
155+
def _getProcessInfoInternal(self, name: str) -> ProcessInfo:
151156
return ProcessInfo(**self._client.supervisor.getProcessInfo(name))
152157

153158
def readProcessLog(self, name: str):
@@ -191,17 +196,32 @@ def stopAllProcesses(self) -> Dict[str, ProcessInfo]:
191196
def stopProcess(self, name: str) -> ProcessInfo:
192197
if name not in self._cfg.program:
193198
raise RuntimeError(f"Unknown process: {name}")
199+
return self._stopProcessInternal(name)
200+
201+
def _stopProcessInternal(self, name: str) -> ProcessInfo:
194202
try:
195203
if self._client.supervisor.stopProcess(name):
196-
return self.getProcessInfo(name)
204+
return self._getProcessInfoInternal(name)
197205
except Fault as f:
198206
if f.faultCode == SupervisorMethodResult.NOT_RUNNING.value:
199-
return self.getProcessInfo(name)
207+
return self._getProcessInfoInternal(name)
200208
raise f
201-
return self.getProcessInfo(name)
202-
203-
# def reloadConfig(self):
204-
# return self._client.supervisor.reloadConfig()
209+
return self._getProcessInfoInternal(name)
210+
211+
def reloadConfig(self, start_new: bool = False) -> SupervisorState:
212+
added, changed, removed = self._client.supervisor.reloadConfig()[0]
213+
proc_infos = []
214+
for name in removed:
215+
proc_infos.append(self._stopProcessInternal(name))
216+
for name in changed:
217+
self._stopProcessInternal(name)
218+
proc_infos.append(self.startProcess(name))
219+
# Don't need to start as we'll do this separately
220+
for name in added:
221+
self._client.supervisor.addProcessGroup(name)
222+
if start_new:
223+
proc_infos.append(self.startProcess(name))
224+
return proc_infos
205225

206226
# def signalAllProcesses(self, signal):
207227
# return self._client.supervisor.signalAllProcesses()

supervisor_pydantic/config/convenience.py

+4
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ class ConvenienceConfiguration(_BaseCfgModel):
7777
default="/RPC2",
7878
description="Path for supervisor XMLRPC HTTP API. Used by the XMLRPC client",
7979
)
80+
81+
#########
82+
# Other #
83+
#########
8084
command_timeout: int = Field(
8185
default=30,
8286
description="Timeout for convenience commands sent to the supervisor, in seconds",

supervisor_pydantic/convenience/commands.py

+10
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,18 @@ def start_supervisor(
103103
cfg_obj = _load_or_pass(cfg)
104104
if not _check_same(cfg_obj):
105105
log.critical("Configs don't match")
106+
107+
# TODO check if "critical" things are different and restart
108+
# supervisor if necessary
109+
110+
# Otherwise just write and reload
111+
cfg_obj._write_self()
112+
client = SupervisorRemoteXMLRPCClient(cfg=cfg_obj)
113+
client.reloadConfig()
114+
106115
if _check_running(cfg_obj):
107116
return _raise_or_exit(True, _exit)
117+
108118
cfg_obj.start(daemon=True)
109119
running = _wait_or_while(until=lambda: cfg_obj.running(), timeout=cfg_obj.convenience.command_timeout)
110120
if not running:

supervisor_pydantic/tests/client/test_client_e2e.py

+20-8
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,35 @@
77
from supervisor_pydantic.client.xmlrpc import ProcessState
88

99

10-
def _assert_client_actions(client: SupervisorRemoteXMLRPCClient):
11-
assert client.getProcessInfo("test").state == ProcessState.STOPPED
10+
def _assert_client_actions(client: SupervisorRemoteXMLRPCClient, name: str = "test"):
11+
assert client.getProcessInfo(name).state == ProcessState.STOPPED
1212
sleep(1)
13-
assert client.startAllProcesses()["test"].state == ProcessState.RUNNING
13+
assert client.startAllProcesses()[name].state == ProcessState.RUNNING
1414
sleep(1)
15-
assert client.getProcessInfo("test").state == ProcessState.EXITED
16-
assert client.startProcess("test").state == ProcessState.RUNNING
17-
assert client.stopProcess("test").state == ProcessState.STOPPED
18-
assert client.startProcess("test").state == ProcessState.RUNNING
19-
assert client.stopAllProcesses()["test"].state == ProcessState.STOPPED
15+
assert client.getProcessInfo(name).state == ProcessState.EXITED
16+
assert client.startProcess(name).state == ProcessState.RUNNING
17+
assert client.stopProcess(name).state == ProcessState.STOPPED
18+
assert client.startProcess(name).state == ProcessState.RUNNING
19+
assert client.stopAllProcesses()[name].state == ProcessState.STOPPED
2020

2121

2222
def test_supervisor_client(supervisor_instance: SupervisorConvenienceConfiguration):
2323
client = SupervisorRemoteXMLRPCClient(supervisor_instance)
2424
_assert_client_actions(client=client)
2525

2626

27+
def test_supervisor_client_changes(supervisor_instance: SupervisorConvenienceConfiguration):
28+
client = SupervisorRemoteXMLRPCClient(supervisor_instance)
29+
_assert_client_actions(client=client)
30+
test_program = supervisor_instance.program.pop("test")
31+
supervisor_instance.program["test2"] = test_program
32+
supervisor_instance._write_self()
33+
client = SupervisorRemoteXMLRPCClient(supervisor_instance)
34+
client.reloadConfig()
35+
print(supervisor_instance)
36+
_assert_client_actions(client=client, name="test2")
37+
38+
2739
def test_permissioned_supervisor_client_rejected(permissioned_supervisor_instance: SupervisorConvenienceConfiguration):
2840
permissioned_supervisor_instance.convenience.username = "bad-username"
2941
client = SupervisorRemoteXMLRPCClient(permissioned_supervisor_instance)

0 commit comments

Comments
 (0)