fujin-cli 0.9.1__py3-none-any.whl → 0.11.4__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/__main__.py +2 -2
- fujin/commands/init.py +1 -1
- fujin/commands/prune.py +1 -1
- fujin/config.py +47 -40
- fujin/secrets/__init__.py +9 -1
- fujin/secrets/dopppler.py +31 -0
- fujin/secrets/system.py +19 -0
- fujin/templates/granian/web.service +22 -0
- fujin/templates/{web.service → gunicorn/web.service} +2 -2
- fujin/templates/simple.service +2 -1
- {fujin_cli-0.9.1.dist-info → fujin_cli-0.11.4.dist-info}/METADATA +3 -2
- {fujin_cli-0.9.1.dist-info → fujin_cli-0.11.4.dist-info}/RECORD +16 -13
- {fujin_cli-0.9.1.dist-info → fujin_cli-0.11.4.dist-info}/WHEEL +1 -1
- /fujin/templates/{web.socket → gunicorn/web.socket} +0 -0
- {fujin_cli-0.9.1.dist-info → fujin_cli-0.11.4.dist-info}/entry_points.txt +0 -0
- {fujin_cli-0.9.1.dist-info → fujin_cli-0.11.4.dist-info}/licenses/LICENSE.txt +0 -0
fujin/__main__.py
CHANGED
|
@@ -50,9 +50,9 @@ class Fujin:
|
|
|
50
50
|
def main():
|
|
51
51
|
alias_cmd = _parse_aliases()
|
|
52
52
|
if alias_cmd:
|
|
53
|
-
cappa.invoke(Fujin, argv=alias_cmd)
|
|
53
|
+
cappa.invoke(Fujin, argv=alias_cmd, version="0.11.4")
|
|
54
54
|
else:
|
|
55
|
-
cappa.invoke(Fujin)
|
|
55
|
+
cappa.invoke(Fujin, version="0.11.4")
|
|
56
56
|
|
|
57
57
|
|
|
58
58
|
def _parse_aliases() -> list[str] | None:
|
fujin/commands/init.py
CHANGED
fujin/commands/prune.py
CHANGED
|
@@ -8,7 +8,7 @@ from fujin.commands import BaseCommand
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
@cappa.command(
|
|
11
|
-
help="Prune old
|
|
11
|
+
help="Prune old artifacts, keeping only the specified number of recent versions"
|
|
12
12
|
)
|
|
13
13
|
@dataclass
|
|
14
14
|
class Prune(BaseCommand):
|
fujin/config.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
|
-
Fujin uses a
|
|
2
|
+
Fujin uses a **fujin.toml** file at the root of your project for configuration. Below are all available configuration options.
|
|
3
3
|
|
|
4
4
|
app
|
|
5
5
|
---
|
|
@@ -7,16 +7,16 @@ The name of your project or application. Must be a valid Python package name.
|
|
|
7
7
|
|
|
8
8
|
version
|
|
9
9
|
--------
|
|
10
|
-
The version of your project to build and deploy. If not specified, automatically parsed from
|
|
10
|
+
The version of your project to build and deploy. If not specified, automatically parsed from **pyproject.toml** under *project.version*.
|
|
11
11
|
|
|
12
12
|
python_version
|
|
13
13
|
--------------
|
|
14
|
-
The Python version for your virtualenv. If not specified, automatically parsed from
|
|
15
|
-
required if the installation mode is set to
|
|
14
|
+
The Python version for your virtualenv. If not specified, automatically parsed from **.python-version** file. This is only
|
|
15
|
+
required if the installation mode is set to **python-package**
|
|
16
16
|
|
|
17
17
|
requirements
|
|
18
18
|
------------
|
|
19
|
-
Optional path to your requirements file. This will only be used when the installation mode is set to
|
|
19
|
+
Optional path to your requirements file. This will only be used when the installation mode is set to *python-package*
|
|
20
20
|
|
|
21
21
|
versions_to_keep
|
|
22
22
|
----------------
|
|
@@ -30,31 +30,28 @@ The command to use to build your project's distribution file.
|
|
|
30
30
|
distfile
|
|
31
31
|
--------
|
|
32
32
|
Path to your project's distribution file. This should be the main artifact containing everything needed to run your project on the server.
|
|
33
|
-
Supports version placeholder, e.g.,
|
|
33
|
+
Supports version placeholder, e.g., **dist/app_name-{version}-py3-none-any.whl**
|
|
34
34
|
|
|
35
35
|
installation_mode
|
|
36
36
|
-----------------
|
|
37
37
|
|
|
38
|
-
Indicates whether the
|
|
39
|
-
The
|
|
40
|
-
|
|
38
|
+
Indicates whether the *distfile* is a Python package or a self-contained executable. The possible values are *python-package* and *binary*.
|
|
39
|
+
The *binary* option disables specific Python-related features, such as virtual environment creation and requirements installation. ``fujin`` will assume the provided
|
|
40
|
+
*distfile* already contains all the necessary dependencies to run your program.
|
|
41
41
|
|
|
42
42
|
release_command
|
|
43
43
|
---------------
|
|
44
|
-
Optional command to run at the end of deployment (e.g., database migrations).
|
|
44
|
+
Optional command to run at the end of deployment (e.g., database migrations) before your application is started.
|
|
45
45
|
|
|
46
46
|
secrets
|
|
47
47
|
-------
|
|
48
48
|
|
|
49
|
-
Optional secrets configuration. If set,
|
|
49
|
+
Optional secrets configuration. If set, ``fujin`` will load secrets from the specified secret management service.
|
|
50
50
|
Check out the `secrets </secrets.html>`_ page for more information.
|
|
51
51
|
|
|
52
52
|
adapter
|
|
53
53
|
~~~~~~~
|
|
54
|
-
The secret management service to use.
|
|
55
|
-
|
|
56
|
-
- ``bitwarden``
|
|
57
|
-
- ``1password``
|
|
54
|
+
The secret management service to use. The currently available options are *bitwarden*, *1password*, *doppler*
|
|
58
55
|
|
|
59
56
|
password_env
|
|
60
57
|
~~~~~~~~~~~~
|
|
@@ -63,35 +60,39 @@ Environment variable containing the password for the service account. This is on
|
|
|
63
60
|
Webserver
|
|
64
61
|
---------
|
|
65
62
|
|
|
63
|
+
Web server configurations.
|
|
64
|
+
|
|
66
65
|
type
|
|
67
66
|
~~~~
|
|
68
67
|
The reverse proxy implementation to use. Available options:
|
|
69
68
|
|
|
70
|
-
-
|
|
71
|
-
-
|
|
72
|
-
-
|
|
69
|
+
- *fujin.proxies.caddy* (default)
|
|
70
|
+
- *fujin.proxies.nginx*
|
|
71
|
+
- *fujin.proxies.dummy* (disables proxy)
|
|
73
72
|
|
|
74
73
|
upstream
|
|
75
74
|
~~~~~~~~
|
|
76
75
|
The address where your web application listens for requests. Supports any value compatible with your chosen web proxy:
|
|
77
76
|
|
|
78
|
-
- HTTP address (e.g.,
|
|
79
|
-
- Unix socket (e.g.,
|
|
77
|
+
- HTTP address (e.g., *localhost:8000* )
|
|
78
|
+
- Unix socket caddy (e.g., *unix//run/project.sock* )
|
|
79
|
+
- Unix socket nginx (e.g., *http://unix:/run/project.sock* )
|
|
80
80
|
|
|
81
81
|
certbot_email
|
|
82
82
|
~~~~~~~~~~~~~
|
|
83
|
-
Required when Nginx is used as a proxy
|
|
83
|
+
Required when Nginx is used as a proxy to obtain SSL certificates.
|
|
84
84
|
|
|
85
85
|
statics
|
|
86
86
|
~~~~~~~
|
|
87
87
|
|
|
88
88
|
Defines the mapping of URL paths to local directories for serving static files. The syntax and support for static
|
|
89
89
|
file serving depend on the selected reverse proxy. The directories you map should be accessible by the web server, meaning
|
|
90
|
-
with read permissions for the
|
|
90
|
+
with read permissions for the *www-data* group; a reliable choice is **/var/www**.
|
|
91
91
|
|
|
92
92
|
Example:
|
|
93
93
|
|
|
94
94
|
.. code-block:: toml
|
|
95
|
+
:caption: fujin.toml
|
|
95
96
|
|
|
96
97
|
[webserver]
|
|
97
98
|
upstream = "unix//run/project.sock"
|
|
@@ -102,12 +103,12 @@ processes
|
|
|
102
103
|
---------
|
|
103
104
|
|
|
104
105
|
A mapping of process names to commands that will be managed by the process manager. Define as many processes as needed, but
|
|
105
|
-
when using any proxy other than
|
|
106
|
-
setting on the host to understand how ``app_dir`` is determined.
|
|
106
|
+
when using any proxy other than *fujin.proxies.dummy*, a *web* process must be declared.
|
|
107
107
|
|
|
108
108
|
Example:
|
|
109
109
|
|
|
110
110
|
.. code-block:: toml
|
|
111
|
+
:caption: fujin.toml
|
|
111
112
|
|
|
112
113
|
[processes]
|
|
113
114
|
web = ".venv/bin/gunicorn myproject.wsgi:application"
|
|
@@ -115,7 +116,8 @@ Example:
|
|
|
115
116
|
|
|
116
117
|
.. note::
|
|
117
118
|
|
|
118
|
-
Commands are relative to your
|
|
119
|
+
Commands are relative to your *app_dir*. When generating systemd service files, the full path is automatically constructed.
|
|
120
|
+
Refer to the *apps_dir* setting on the host to understand how *app_dir* is determined.
|
|
119
121
|
Here are the templates for the service files:
|
|
120
122
|
|
|
121
123
|
- `web.service <https://github.com/falcopackages/fujin/blob/main/src/fujin/templates/web.service>`_
|
|
@@ -127,7 +129,7 @@ Host Configuration
|
|
|
127
129
|
|
|
128
130
|
ip
|
|
129
131
|
~~
|
|
130
|
-
The IP address or anything that resolves to the remote host IP's. This is use to communicate via ssh with the server, if omitted it's value will default to the one of the
|
|
132
|
+
The IP address or anything that resolves to the remote host IP's. This is use to communicate via ssh with the server, if omitted it's value will default to the one of the *domain_name*.
|
|
131
133
|
|
|
132
134
|
domain_name
|
|
133
135
|
~~~~~~~~~~~
|
|
@@ -141,23 +143,23 @@ The login user for running remote tasks. Should have passwordless sudo access fo
|
|
|
141
143
|
|
|
142
144
|
You can create a user with these requirements using the ``fujin server create-user`` command.
|
|
143
145
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
+
envfile
|
|
147
|
+
~~~~~~~
|
|
146
148
|
Path to the production environment file that will be copied to the host.
|
|
147
149
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
+
env
|
|
151
|
+
~~~
|
|
150
152
|
A string containing the production environment variables, ideal for scenarios where most variables are retrieved from secrets and you prefer not to use a separate file.
|
|
151
153
|
|
|
152
154
|
.. important::
|
|
153
155
|
|
|
154
|
-
|
|
156
|
+
*envfile* and *env* are mutually exclusive—you can define only one.
|
|
155
157
|
|
|
156
158
|
apps_dir
|
|
157
159
|
~~~~~~~~
|
|
158
160
|
|
|
159
161
|
Base directory for project storage on the host. Path is relative to user's home directory.
|
|
160
|
-
Default:
|
|
162
|
+
Default: **.local/share/fujin**. This value determines your project's **app_dir**, which is **{apps_dir}/{app}**.
|
|
161
163
|
|
|
162
164
|
password_env
|
|
163
165
|
~~~~~~~~~~~~
|
|
@@ -167,8 +169,7 @@ Environment variable containing the user's password. Only needed if the user can
|
|
|
167
169
|
ssh_port
|
|
168
170
|
~~~~~~~~
|
|
169
171
|
|
|
170
|
-
SSH port for connecting to the host.
|
|
171
|
-
Default: ``22``
|
|
172
|
+
SSH port for connecting to the host. Default to **22**.
|
|
172
173
|
|
|
173
174
|
key_filename
|
|
174
175
|
~~~~~~~~~~~~
|
|
@@ -183,6 +184,7 @@ A mapping of shortcut names to Fujin commands. Allows you to create convenient s
|
|
|
183
184
|
Example:
|
|
184
185
|
|
|
185
186
|
.. code-block:: toml
|
|
187
|
+
:caption: fujin.toml
|
|
186
188
|
|
|
187
189
|
[aliases]
|
|
188
190
|
console = "app exec -i shell_plus" # open an interactive django shell
|
|
@@ -221,6 +223,8 @@ class InstallationMode(StrEnum):
|
|
|
221
223
|
class SecretAdapter(StrEnum):
|
|
222
224
|
BITWARDEN = "bitwarden"
|
|
223
225
|
ONE_PASSWORD = "1password"
|
|
226
|
+
DOPPLER = "doppler"
|
|
227
|
+
SYSTEM = "system"
|
|
224
228
|
|
|
225
229
|
|
|
226
230
|
class SecretConfig(msgspec.Struct):
|
|
@@ -244,7 +248,10 @@ class Config(msgspec.Struct, kw_only=True):
|
|
|
244
248
|
requirements: str | None = None
|
|
245
249
|
hooks: HooksDict = msgspec.field(default_factory=dict)
|
|
246
250
|
local_config_dir: Path = Path(".fujin")
|
|
247
|
-
secret_config: SecretConfig | None = msgspec.field(
|
|
251
|
+
secret_config: SecretConfig | None = msgspec.field(
|
|
252
|
+
name="secrets",
|
|
253
|
+
default_factory=lambda: SecretConfig(adapter=SecretAdapter.SYSTEM),
|
|
254
|
+
)
|
|
248
255
|
|
|
249
256
|
def __post_init__(self):
|
|
250
257
|
if self.installation_mode == InstallationMode.PY_PACKAGE:
|
|
@@ -283,8 +290,8 @@ class HostConfig(msgspec.Struct, kw_only=True):
|
|
|
283
290
|
ip: str | None = None
|
|
284
291
|
domain_name: str
|
|
285
292
|
user: str
|
|
286
|
-
_env_file: str = msgspec.field(name="envfile", default=
|
|
287
|
-
env_content: str = ""
|
|
293
|
+
_env_file: str | None = msgspec.field(name="envfile", default=None)
|
|
294
|
+
env_content: str | None = msgspec.field(name="env", default=None)
|
|
288
295
|
apps_dir: str = ".local/share/fujin"
|
|
289
296
|
password_env: str | None = None
|
|
290
297
|
ssh_port: int = 22
|
|
@@ -293,14 +300,14 @@ class HostConfig(msgspec.Struct, kw_only=True):
|
|
|
293
300
|
def __post_init__(self):
|
|
294
301
|
if self._env_file and self.env_content:
|
|
295
302
|
raise ImproperlyConfiguredError(
|
|
296
|
-
"Cannot set both '
|
|
303
|
+
"Cannot set both 'env' and 'envfile' properties."
|
|
297
304
|
)
|
|
298
|
-
if
|
|
305
|
+
if self._env_file:
|
|
299
306
|
envfile = Path(self._env_file)
|
|
300
307
|
if not envfile.exists():
|
|
301
308
|
raise ImproperlyConfiguredError(f"{self._env_file} not found")
|
|
302
309
|
self.env_content = envfile.read_text()
|
|
303
|
-
self.env_content = self.env_content.strip()
|
|
310
|
+
self.env_content = self.env_content.strip() if self.env_content else ""
|
|
304
311
|
self.apps_dir = f"/home/{self.user}/{self.apps_dir}"
|
|
305
312
|
self.ip = self.ip or self.domain_name
|
|
306
313
|
|
fujin/secrets/__init__.py
CHANGED
|
@@ -10,18 +10,24 @@ from dotenv import dotenv_values
|
|
|
10
10
|
from fujin.config import SecretAdapter
|
|
11
11
|
from fujin.config import SecretConfig
|
|
12
12
|
from .bitwarden import bitwarden
|
|
13
|
+
from .dopppler import doppler
|
|
13
14
|
from .onepassword import one_password
|
|
15
|
+
from .system import system
|
|
14
16
|
|
|
15
17
|
secret_reader = Callable[[str], str]
|
|
16
18
|
secret_adapter_context = Callable[[SecretConfig], ContextManager[secret_reader]]
|
|
17
19
|
|
|
18
20
|
adapter_to_context: dict[SecretAdapter, secret_adapter_context] = {
|
|
21
|
+
SecretAdapter.SYSTEM: system,
|
|
19
22
|
SecretAdapter.BITWARDEN: bitwarden,
|
|
20
23
|
SecretAdapter.ONE_PASSWORD: one_password,
|
|
24
|
+
SecretAdapter.DOPPLER: doppler,
|
|
21
25
|
}
|
|
22
26
|
|
|
23
27
|
|
|
24
28
|
def resolve_secrets(env_content: str, secret_config: SecretConfig) -> str:
|
|
29
|
+
if not env_content: # this is really for empty string
|
|
30
|
+
return ""
|
|
25
31
|
with closing(StringIO(env_content)) as buffer:
|
|
26
32
|
env_dict = dotenv_values(stream=buffer)
|
|
27
33
|
secrets = {key: value for key, value in env_dict.items() if value.startswith("$")}
|
|
@@ -31,7 +37,9 @@ def resolve_secrets(env_content: str, secret_config: SecretConfig) -> str:
|
|
|
31
37
|
parsed_secrets = {}
|
|
32
38
|
with adapter_context(secret_config) as reader:
|
|
33
39
|
for key, secret in secrets.items():
|
|
34
|
-
parsed_secrets[key] = gevent.spawn(
|
|
40
|
+
parsed_secrets[key] = gevent.spawn(
|
|
41
|
+
reader, secret[1:]
|
|
42
|
+
) # remove the leading $
|
|
35
43
|
gevent.joinall(parsed_secrets.values())
|
|
36
44
|
env_dict.update({key: thread.value for key, thread in parsed_secrets.items()})
|
|
37
45
|
return "\n".join(f'{key}="{value}"' for key, value in env_dict.items())
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import subprocess
|
|
4
|
+
from contextlib import contextmanager
|
|
5
|
+
from typing import Generator
|
|
6
|
+
from typing import TYPE_CHECKING
|
|
7
|
+
|
|
8
|
+
import cappa
|
|
9
|
+
|
|
10
|
+
from fujin.config import SecretConfig
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from . import secret_reader
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@contextmanager
|
|
17
|
+
def doppler(_: SecretConfig) -> Generator[secret_reader, None, None]:
|
|
18
|
+
def read_secret(name: str) -> str:
|
|
19
|
+
result = subprocess.run(
|
|
20
|
+
["doppler", "run", "--command", f"echo ${name}"],
|
|
21
|
+
capture_output=True,
|
|
22
|
+
text=True,
|
|
23
|
+
)
|
|
24
|
+
if result.returncode != 0:
|
|
25
|
+
raise cappa.Exit(result.stderr)
|
|
26
|
+
return result.stdout.strip()
|
|
27
|
+
|
|
28
|
+
try:
|
|
29
|
+
yield read_secret
|
|
30
|
+
finally:
|
|
31
|
+
pass
|
fujin/secrets/system.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from contextlib import contextmanager
|
|
5
|
+
from typing import Generator
|
|
6
|
+
from typing import TYPE_CHECKING
|
|
7
|
+
|
|
8
|
+
from fujin.config import SecretConfig
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from . import secret_reader
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@contextmanager
|
|
15
|
+
def system(_: SecretConfig) -> Generator[secret_reader, None, None]:
|
|
16
|
+
try:
|
|
17
|
+
yield os.getenv
|
|
18
|
+
finally:
|
|
19
|
+
pass
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# All options are documented here https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html
|
|
2
|
+
# Inspiration was taken from here https://docs.gunicorn.org/en/stable/deploy.html#systemd
|
|
3
|
+
[Unit]
|
|
4
|
+
Description={app_name} daemon
|
|
5
|
+
After=network.target
|
|
6
|
+
|
|
7
|
+
[Service]
|
|
8
|
+
User={user}
|
|
9
|
+
Group={user}
|
|
10
|
+
RuntimeDirectory={app_name}
|
|
11
|
+
WorkingDirectory={app_dir}
|
|
12
|
+
ExecStart={app_dir}/{command}
|
|
13
|
+
EnvironmentFile={app_dir}/.env
|
|
14
|
+
ExecReload=/bin/kill -s HUP $MAINPID
|
|
15
|
+
KillMode=mixed
|
|
16
|
+
TimeoutStopSec=5
|
|
17
|
+
PrivateTmp=true
|
|
18
|
+
# if your app does not need administrative capabilities, let systemd know
|
|
19
|
+
ProtectSystem=strict
|
|
20
|
+
|
|
21
|
+
[Install]
|
|
22
|
+
WantedBy=multi-user.target
|
fujin/templates/simple.service
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: fujin-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.11.4
|
|
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
|
|
7
7
|
Project-URL: Source, https://github.com/falcopackages/fujin
|
|
8
8
|
Author-email: Tobi DEGNON <tobidegnon@proton.me>
|
|
9
|
+
License-File: LICENSE.txt
|
|
9
10
|
Keywords: caddy,deployment,django,fastapi,litestar,python,systemd
|
|
10
11
|
Classifier: Development Status :: 3 - Alpha
|
|
11
12
|
Classifier: Intended Audience :: Developers
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
fujin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
fujin/__main__.py,sha256=
|
|
3
|
-
fujin/config.py,sha256=
|
|
2
|
+
fujin/__main__.py,sha256=qnRqZD-ZGTGeRTcPeHVzlvNNUj3exzftC_KILAlx-Hs,1849
|
|
3
|
+
fujin/config.py,sha256=t7UnhQMl-wYDyFCIcOC5lLdfpSmYWDIRPHvozoSoVME,11707
|
|
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
|
|
@@ -12,10 +12,10 @@ fujin/commands/config.py,sha256=WymGla-H2yduhLcYE1Nb6IJaFIj0S0KIhV9fBDCKsAw,2779
|
|
|
12
12
|
fujin/commands/deploy.py,sha256=AylcVNX47ekf-AFfQrYcSh86I3qltADEgjPtV9lQAfE,5831
|
|
13
13
|
fujin/commands/docs.py,sha256=b5FZ8AgoAfn4q4BueEQvM2w5HCuh8-rwBqv_CRFVU8E,349
|
|
14
14
|
fujin/commands/down.py,sha256=aw_mxl_TMC66plKTXwlYP1W2XQBmHeROltQqOpQssyE,1577
|
|
15
|
-
fujin/commands/init.py,sha256=
|
|
15
|
+
fujin/commands/init.py,sha256=9yrja4YYFlJqEarN0ekg6yPd5niifPwvQ4i4wnC55a0,4007
|
|
16
16
|
fujin/commands/printenv.py,sha256=bS2mIgk7zd_w3yDhZLTa1PkHIzuSbBWjnYyM8CUjX0k,523
|
|
17
17
|
fujin/commands/proxy.py,sha256=ajXwboS0gDDiMWW7b9rtWU6WPF1h7JYYeycDyU-hQfg,3053
|
|
18
|
-
fujin/commands/prune.py,sha256=
|
|
18
|
+
fujin/commands/prune.py,sha256=3Y0ZpgoI8eb_FVD6XMmZK9lEp2delKUeJdK09kv9_08,1509
|
|
19
19
|
fujin/commands/redeploy.py,sha256=491Mzz0qiaHqcI7BFUtZq-M34WQkiBd2ZgQbLRLp8T8,2355
|
|
20
20
|
fujin/commands/rollback.py,sha256=JsocJzQcdQelSnYD94klhjBh8UKkkdiRD9shfUfo4FI,2032
|
|
21
21
|
fujin/commands/server.py,sha256=-3-PyBNR0fGm-RYE3fz50kP-LSDYGU9BzUxrbGZEghc,3312
|
|
@@ -24,14 +24,17 @@ fujin/proxies/__init__.py,sha256=UuWYU175tkdaz1WWRCDDpQgGfFVYYNR9PBxA3lTCNr0,695
|
|
|
24
24
|
fujin/proxies/caddy.py,sha256=H52D7cGEEGcxDaXxvClnny9lAat_h1G9dYlIlf6gwKo,7933
|
|
25
25
|
fujin/proxies/dummy.py,sha256=qBKSn8XNEA9SVwB7GzRNX2l9Iw6tUjo2CFqZjWi0FjY,465
|
|
26
26
|
fujin/proxies/nginx.py,sha256=BNJNLxLLRVAmBIGVCk8pb16iiSJsOI9jXOZhdSQGtX8,4151
|
|
27
|
-
fujin/secrets/__init__.py,sha256=
|
|
27
|
+
fujin/secrets/__init__.py,sha256=nicjIkcEX22rSD-Fleg0jG2IaBtvEq1dbkcfZ7lGlGI,1633
|
|
28
28
|
fujin/secrets/bitwarden.py,sha256=01GZL5hYwZzL6yXy5ab3L3kgBFBeOT8i3Yg9GC8YwFU,2008
|
|
29
|
+
fujin/secrets/dopppler.py,sha256=t5SGfyuA0RxsD9uvrAu4cG2TBDIUgB5gb6XYXPrd61Y,724
|
|
29
30
|
fujin/secrets/onepassword.py,sha256=6Xj3XWttKfcjMbcoMZvXVpJW1KHxlD785DysmX_mqvk,654
|
|
30
|
-
fujin/
|
|
31
|
-
fujin/templates/
|
|
32
|
-
fujin/templates/web.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
fujin_cli-0.
|
|
36
|
-
fujin_cli-0.
|
|
37
|
-
fujin_cli-0.
|
|
31
|
+
fujin/secrets/system.py,sha256=Z5uNc2V3rcR75ffBnOsJywndoWuDcih88O9nPXIJ3U0,382
|
|
32
|
+
fujin/templates/simple.service,sha256=ySlLqF354UCvlQaJcEVj4jf4hK7aKAq9qseE6pmtXJI,350
|
|
33
|
+
fujin/templates/granian/web.service,sha256=D3vHOHdP3wrZueKuhlhkB4syOCVvGSciDsNsmU_Bp68,626
|
|
34
|
+
fujin/templates/gunicorn/web.service,sha256=EfTJQP4VvwlOTDyVCch5Y7iVhpPvZVaRWE6MHI4_z4k,683
|
|
35
|
+
fujin/templates/gunicorn/web.socket,sha256=2lJsiOHlMJL0YlN7YBLLnr5zqsytPEt81yP34nk0dmc,173
|
|
36
|
+
fujin_cli-0.11.4.dist-info/METADATA,sha256=MOALo-mvFTBlNaK-mnrEUSY0aZJSIqHL28m0CYM97KQ,4603
|
|
37
|
+
fujin_cli-0.11.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
38
|
+
fujin_cli-0.11.4.dist-info/entry_points.txt,sha256=Y_TBtKt3j11qhwquMexZR5yqnDEqOBDACtresqQFE-s,46
|
|
39
|
+
fujin_cli-0.11.4.dist-info/licenses/LICENSE.txt,sha256=0QF8XfuH0zkIHhSet6teXfiCze6JSdr8inRkmLLTDyo,1099
|
|
40
|
+
fujin_cli-0.11.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|