fujin-cli 0.9.0__py3-none-any.whl → 0.9.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of fujin-cli might be problematic. Click here for more details.

fujin/commands/_base.py CHANGED
@@ -10,8 +10,8 @@ from fujin.connection import Connection
10
10
  from fujin.connection import host_connection
11
11
  from fujin.errors import ImproperlyConfiguredError
12
12
  from fujin.hooks import HookManager
13
- from fujin.process_managers import ProcessManager
14
13
  from fujin.proxies import WebProxy
14
+ from fujin.systemd import ProcessManager
15
15
 
16
16
 
17
17
  @dataclass
@@ -66,15 +66,5 @@ class BaseCommand:
66
66
  def create_web_proxy(self, conn: Connection) -> WebProxy:
67
67
  return self.web_proxy_class.create(conn=conn, config=self.config)
68
68
 
69
- @cached_property
70
- def process_manager_class(self) -> type[ProcessManager]:
71
- module = importlib.import_module(self.config.process_manager)
72
- try:
73
- return getattr(module, "ProcessManager")
74
- except KeyError as e:
75
- raise ImproperlyConfiguredError(
76
- f"Missing ProcessManager class in {self.config.process_manager}"
77
- ) from e
78
-
79
69
  def create_process_manager(self, conn: Connection) -> ProcessManager:
80
- return self.process_manager_class.create(conn=conn, config=self.config)
70
+ return ProcessManager.create(conn=conn, config=self.config)
fujin/config.py CHANGED
@@ -116,6 +116,11 @@ Example:
116
116
  .. note::
117
117
 
118
118
  Commands are relative to your ``app_dir``. When generating systemd service files, the full path is automatically constructed.
119
+ Here are the templates for the service files:
120
+
121
+ - `web.service <https://github.com/falcopackages/fujin/blob/main/src/fujin/templates/web.service>`_
122
+ - `web.socket <https://github.com/falcopackages/fujin/blob/main/src/fujin/templates/web.socket>`_
123
+ - `simple.service <https://github.com/falcopackages/fujin/blob/main/src/fujin/templates/simple.service>`_ (for all additional processes)
119
124
 
120
125
  Host Configuration
121
126
  -------------------
@@ -235,7 +240,6 @@ class Config(msgspec.Struct, kw_only=True):
235
240
  aliases: dict[str, str] = msgspec.field(default_factory=dict)
236
241
  host: HostConfig
237
242
  processes: dict[str, str] = msgspec.field(default_factory=dict)
238
- process_manager: str = "fujin.process_managers.systemd"
239
243
  webserver: Webserver
240
244
  requirements: str | None = None
241
245
  hooks: HooksDict = msgspec.field(default_factory=dict)
fujin/proxies/caddy.py CHANGED
@@ -166,7 +166,8 @@ class WebProxy(msgspec.Struct):
166
166
  new_routes = [r for r in existing_routes if r.get("group") != self.app_name]
167
167
  current_config["routes"] = new_routes
168
168
  self.conn.run(
169
- f"curl localhost:2019/config/apps/http/servers/srv0 -H 'Content-Type: application/json' -d '{json.dumps(current_config)}'"
169
+ f"curl localhost:2019/config/apps/http/servers/srv0 -H 'Content-Type: application/json' -d '{json.dumps(current_config)}'",
170
+ hide="out",
170
171
  )
171
172
 
172
173
  def start(self) -> None:
@@ -4,6 +4,8 @@ import importlib.util
4
4
  from dataclasses import dataclass
5
5
  from pathlib import Path
6
6
 
7
+ import gevent
8
+
7
9
  from fujin.config import Config
8
10
  from fujin.connection import Connection
9
11
 
@@ -54,11 +56,23 @@ class ProcessManager:
54
56
  hide="out",
55
57
  )
56
58
 
59
+ threads = []
57
60
  for name in self.processes:
58
61
  if name == "web" and self.is_using_unix_socket:
59
- self.run_pty(f"sudo systemctl enable --now {self.app_name}.socket")
62
+ threads.append(
63
+ gevent.spawn(
64
+ self.run_pty,
65
+ f"sudo systemctl enable --now {self.app_name}.socket",
66
+ )
67
+ )
60
68
  else:
61
- self.run_pty(f"sudo systemctl enable {self.get_service_name(name)}")
69
+ threads.append(
70
+ gevent.spawn(
71
+ self.run_pty,
72
+ f"sudo systemctl enable {self.get_service_name(name)}",
73
+ )
74
+ )
75
+ gevent.joinall(threads)
62
76
 
63
77
  def get_configuration_files(
64
78
  self, ignore_local: bool = False
@@ -105,47 +119,68 @@ class ProcessManager:
105
119
 
106
120
  def uninstall_services(self) -> None:
107
121
  self.stop_services()
108
- for name in self.service_names:
109
- self.run_pty(f"sudo systemctl disable {name}", warn=True)
110
- self.run_pty(f"sudo rm /etc/systemd/system/{name}", warn=True)
122
+ threads = [
123
+ gevent.spawn(self.run_pty, f"sudo systemctl disable {name}", warn=True)
124
+ for name in self.service_names
125
+ ]
126
+ gevent.joinall(threads)
127
+ files_to_delete = [f"/etc/systemd/system/{name}" for name in self.service_names]
128
+ self.run_pty(f"sudo rm {' '.join(files_to_delete)}", warn=True)
111
129
 
112
130
  def start_services(self, *names) -> None:
113
131
  names = names or self.service_names
114
- for name in names:
115
- if name in self.service_names:
116
- self.run_pty(f"sudo systemctl start {name}")
132
+ threads = [
133
+ gevent.spawn(self.run_pty, f"sudo systemctl start {name}")
134
+ for name in names
135
+ if name in self.service_names
136
+ ]
137
+ gevent.joinall(threads)
117
138
 
118
139
  def restart_services(self, *names) -> None:
119
140
  names = names or self.service_names
120
- for name in names:
121
- if name in self.service_names:
122
- self.run_pty(f"sudo systemctl restart {name}")
141
+ threads = [
142
+ gevent.spawn(self.run_pty, f"sudo systemctl restart {name}")
143
+ for name in names
144
+ if name in self.service_names
145
+ ]
146
+ gevent.joinall(threads)
123
147
 
124
148
  def stop_services(self, *names) -> None:
125
149
  names = names or self.service_names
126
- for name in names:
127
- if name in self.service_names:
128
- self.run_pty(f"sudo systemctl stop {name}")
150
+ threads = [
151
+ gevent.spawn(self.run_pty, f"sudo systemctl stop {name}")
152
+ for name in names
153
+ if name in self.service_names
154
+ ]
155
+ gevent.joinall(threads)
129
156
 
130
157
  def is_enabled(self, *names) -> dict[str, bool]:
131
158
  names = names or self.service_names
132
- return {
133
- name: self.run_pty(
134
- f"sudo systemctl is-enabled {name}", warn=True, hide=True
135
- ).stdout.strip()
136
- == "enabled"
159
+ threads = {
160
+ name: gevent.spawn(
161
+ self.run_pty, f"sudo systemctl is-enabled {name}", warn=True, hide=True
162
+ )
137
163
  for name in names
138
164
  }
165
+ gevent.joinall(threads.values())
166
+ return {
167
+ name: thread.value.stdout.strip() == "enabled"
168
+ for name, thread in threads.items()
169
+ }
139
170
 
140
171
  def is_active(self, *names) -> dict[str, bool]:
141
172
  names = names or self.service_names
142
- return {
143
- name: self.run_pty(
144
- f"sudo systemctl is-active {name}", warn=True, hide=True
145
- ).stdout.strip()
146
- == "active"
173
+ threads = {
174
+ name: gevent.spawn(
175
+ self.run_pty, f"sudo systemctl is-active {name}", warn=True, hide=True
176
+ )
147
177
  for name in names
148
178
  }
179
+ gevent.joinall(threads.values())
180
+ return {
181
+ name: thread.value.stdout.strip() == "active"
182
+ for name, thread in threads.items()
183
+ }
149
184
 
150
185
  def service_logs(self, name: str, follow: bool = False):
151
186
  # TODO: add more options here
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: fujin-cli
3
- Version: 0.9.0
3
+ Version: 0.9.1
4
4
  Summary: Get your project up and running in a few minutes on your own vps.
5
5
  Project-URL: Documentation, https://github.com/falcopackages/fujin#readme
6
6
  Project-URL: Issues, https://github.com/falcopackages/fujin/issues
@@ -1,11 +1,12 @@
1
1
  fujin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  fujin/__main__.py,sha256=VJMBzuQuxkQaAKNEySktGnms944bkRsrIAjj-XeaWR8,1813
3
- fujin/config.py,sha256=LjgOTBumgOQTHkgXLJ0Rb2ERz_WBO-8rDj1hTYo-z0s,11027
3
+ fujin/config.py,sha256=jE5iAu1ouHgv2eTut6CRBiKIzK-vxJqVtZuOr6NICEM,11365
4
4
  fujin/connection.py,sha256=LL7LhX9p0X9FmiGdlSroD3Ht216QY0Kd51xkSrXmM3s,2479
5
5
  fujin/errors.py,sha256=74Rh-Sgql1YspPdR_akQ2G3xZ48zecyafYCptpaFo1A,73
6
6
  fujin/hooks.py,sha256=EDVYNozlDJ5kc1xHtZrXgtuKplUMEMPTp65TLMP02Ek,1449
7
+ fujin/systemd.py,sha256=aWfN3CDl_NACjsfzyiVmO2h0-VTgc7y3g8RMG2jVsb4,6640
7
8
  fujin/commands/__init__.py,sha256=g0b13vzidPUbxne_Zo_Wv5jpEmwCiSK4AokCinH9uo4,39
8
- fujin/commands/_base.py,sha256=Rtf7kcO_Pg2JxPNKsXEx0UdhqfzYU6g7IiezC8cqEPQ,2610
9
+ fujin/commands/_base.py,sha256=2k9HGcxskFZQ7qYw8hcJh_73EZ_qVngLot7lOo2hQuw,2193
9
10
  fujin/commands/app.py,sha256=mazb4dCTdR5juh79bL3a9b68Nd6O8u_nR9IgYqQlqWE,5279
10
11
  fujin/commands/config.py,sha256=WymGla-H2yduhLcYE1Nb6IJaFIj0S0KIhV9fBDCKsAw,2779
11
12
  fujin/commands/deploy.py,sha256=AylcVNX47ekf-AFfQrYcSh86I3qltADEgjPtV9lQAfE,5831
@@ -19,10 +20,8 @@ fujin/commands/redeploy.py,sha256=491Mzz0qiaHqcI7BFUtZq-M34WQkiBd2ZgQbLRLp8T8,23
19
20
  fujin/commands/rollback.py,sha256=JsocJzQcdQelSnYD94klhjBh8UKkkdiRD9shfUfo4FI,2032
20
21
  fujin/commands/server.py,sha256=-3-PyBNR0fGm-RYE3fz50kP-LSDYGU9BzUxrbGZEghc,3312
21
22
  fujin/commands/up.py,sha256=OEK_n-6-mnnIUffFpR7QtVunr1V1F04pxlAAS1U62BY,419
22
- fujin/process_managers/__init__.py,sha256=MhhfTBhm64zWRAKgjvsZRIToOUJus60vGScbAjqpQ6Y,994
23
- fujin/process_managers/systemd.py,sha256=qG_4Ew8SEWtaTFOAW_XZXsMO2WjFWZ4dp5nBwAPBObk,5603
24
23
  fujin/proxies/__init__.py,sha256=UuWYU175tkdaz1WWRCDDpQgGfFVYYNR9PBxA3lTCNr0,695
25
- fujin/proxies/caddy.py,sha256=dzLD8s664_kIK-1hCE3y50JIwBd8kK9yS1LynUDRVSE,7908
24
+ fujin/proxies/caddy.py,sha256=H52D7cGEEGcxDaXxvClnny9lAat_h1G9dYlIlf6gwKo,7933
26
25
  fujin/proxies/dummy.py,sha256=qBKSn8XNEA9SVwB7GzRNX2l9Iw6tUjo2CFqZjWi0FjY,465
27
26
  fujin/proxies/nginx.py,sha256=BNJNLxLLRVAmBIGVCk8pb16iiSJsOI9jXOZhdSQGtX8,4151
28
27
  fujin/secrets/__init__.py,sha256=hiNZIBtOwM0WQbvAF3GhuMMCsQCjXjiSr5gTLAGN-VI,1375
@@ -31,8 +30,8 @@ fujin/secrets/onepassword.py,sha256=6Xj3XWttKfcjMbcoMZvXVpJW1KHxlD785DysmX_mqvk,
31
30
  fujin/templates/simple.service,sha256=-lyKjmSyfHGucP4O_vRQE1NNaHq0Qjsc0twdwoRLgI0,321
32
31
  fujin/templates/web.service,sha256=NZ7ZeaFvV_MZTBn8QqRQeu8PIrWHf3aWYWNzjOQeqCw,685
33
32
  fujin/templates/web.socket,sha256=2lJsiOHlMJL0YlN7YBLLnr5zqsytPEt81yP34nk0dmc,173
34
- fujin_cli-0.9.0.dist-info/METADATA,sha256=0OCkg_YffO4PLhTp1AKrk7OmncaCbZOO3IyTYkjGXxI,4576
35
- fujin_cli-0.9.0.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
36
- fujin_cli-0.9.0.dist-info/entry_points.txt,sha256=Y_TBtKt3j11qhwquMexZR5yqnDEqOBDACtresqQFE-s,46
37
- fujin_cli-0.9.0.dist-info/licenses/LICENSE.txt,sha256=0QF8XfuH0zkIHhSet6teXfiCze6JSdr8inRkmLLTDyo,1099
38
- fujin_cli-0.9.0.dist-info/RECORD,,
33
+ fujin_cli-0.9.1.dist-info/METADATA,sha256=5mtskwHoka7b0M4fs897ic7prKs3NgTBrdeMSWlfKBk,4576
34
+ fujin_cli-0.9.1.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
35
+ fujin_cli-0.9.1.dist-info/entry_points.txt,sha256=Y_TBtKt3j11qhwquMexZR5yqnDEqOBDACtresqQFE-s,46
36
+ fujin_cli-0.9.1.dist-info/licenses/LICENSE.txt,sha256=0QF8XfuH0zkIHhSet6teXfiCze6JSdr8inRkmLLTDyo,1099
37
+ fujin_cli-0.9.1.dist-info/RECORD,,
@@ -1,40 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import Protocol
4
- from typing import TYPE_CHECKING
5
-
6
- from fujin.connection import Connection
7
-
8
- if TYPE_CHECKING:
9
- from fujin.config import Config
10
-
11
-
12
- class ProcessManager(Protocol):
13
- service_names: list[str]
14
-
15
- @classmethod
16
- def create(cls, config: Config, conn: Connection) -> ProcessManager: ...
17
-
18
- def get_service_name(self, process_name: str): ...
19
-
20
- def install_services(self) -> None: ...
21
-
22
- def uninstall_services(self) -> None: ...
23
-
24
- def start_services(self, *names) -> None: ...
25
-
26
- def restart_services(self, *names) -> None: ...
27
-
28
- def stop_services(self, *names) -> None: ...
29
-
30
- def is_enabled(self, *names) -> dict[str, bool]: ...
31
-
32
- def is_active(self, *names) -> dict[str, bool]: ...
33
-
34
- def service_logs(self, name: str, follow: bool = False): ...
35
-
36
- def reload_configuration(self) -> None: ...
37
-
38
- def get_configuration_files(
39
- self, ignore_local: bool = False
40
- ) -> list[tuple[str, str]]: ...