mkswarm 0.1.0__tar.gz

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.
@@ -0,0 +1,27 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ dist/
5
+ build/
6
+ .eggs/
7
+ *.egg
8
+ .env
9
+ .venv
10
+ venv/
11
+ env/
12
+ *.pyc
13
+ *.pyo
14
+ .pytest_cache/
15
+ .ruff_cache/
16
+ .mypy_cache/
17
+ htmlcov/
18
+ .coverage
19
+ .coverage.*
20
+ *.log
21
+ .DS_Store
22
+ .idea/
23
+ .vscode/
24
+ *.swp
25
+ *.swo
26
+ .hypothesis/
27
+ *.db
mkswarm-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Dario Clavijo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
mkswarm-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,185 @@
1
+ Metadata-Version: 2.4
2
+ Name: mkswarm
3
+ Version: 0.1.0
4
+ Summary: CLI tool for bootstrapping and managing Docker Swarm clusters
5
+ Project-URL: Homepage, https://github.com/daedalus/mkswarm
6
+ Project-URL: Repository, https://github.com/daedalus/mkswarm
7
+ Project-URL: Issues, https://github.com/daedalus/mkswarm/issues
8
+ Author-email: Dario Clavijo <clavijodario@gmail.com>
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Requires-Python: >=3.11
12
+ Requires-Dist: cryptography>=42.0.0
13
+ Requires-Dist: docker>=7.0.0
14
+ Requires-Dist: pysocks>=1.7.1
15
+ Provides-Extra: all
16
+ Requires-Dist: hatch; extra == 'all'
17
+ Requires-Dist: hypothesis; extra == 'all'
18
+ Requires-Dist: mypy; extra == 'all'
19
+ Requires-Dist: pip-api; extra == 'all'
20
+ Requires-Dist: pytest; extra == 'all'
21
+ Requires-Dist: pytest-asyncio; extra == 'all'
22
+ Requires-Dist: pytest-cov; extra == 'all'
23
+ Requires-Dist: pytest-mock; extra == 'all'
24
+ Requires-Dist: ruff; extra == 'all'
25
+ Provides-Extra: dev
26
+ Requires-Dist: hatch; extra == 'dev'
27
+ Requires-Dist: mypy; extra == 'dev'
28
+ Requires-Dist: pip-api; extra == 'dev'
29
+ Requires-Dist: ruff; extra == 'dev'
30
+ Provides-Extra: lint
31
+ Requires-Dist: mypy; extra == 'lint'
32
+ Requires-Dist: ruff; extra == 'lint'
33
+ Provides-Extra: test
34
+ Requires-Dist: hypothesis; extra == 'test'
35
+ Requires-Dist: pytest; extra == 'test'
36
+ Requires-Dist: pytest-asyncio; extra == 'test'
37
+ Requires-Dist: pytest-cov; extra == 'test'
38
+ Requires-Dist: pytest-mock; extra == 'test'
39
+ Description-Content-Type: text/markdown
40
+
41
+ # mkswarm
42
+
43
+ CLI tool for bootstrapping and managing Docker Swarm clusters.
44
+
45
+ [![PyPI](https://img.shields.io/pypi/v/mkswarm.svg)](https://pypi.org/project/mkswarm/)
46
+ [![Python](https://img.shields.io/pypi/pyversions/mkswarm.svg)](https://pypi.org/project/mkswarm/)
47
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
48
+
49
+ ## Install
50
+
51
+ ```bash
52
+ pip install mkswarm
53
+ ```
54
+
55
+ ## Usage
56
+
57
+ ```bash
58
+ # Initialize a new Docker Swarm
59
+ mkswarm init -i ips.txt -m 192.168.1.1 -r 0.2 -o join.sh
60
+
61
+ # Run pending node joins via Docker SDK
62
+ mkswarm run 1
63
+
64
+ # Show swarm state
65
+ mkswarm status 1
66
+
67
+ # List all swarms
68
+ mkswarm list
69
+
70
+ # Regenerate join script from database
71
+ mkswarm reemit 1 -o new_join.sh
72
+
73
+ # Force-leave all nodes and destroy swarm
74
+ mkswarm destroy 1
75
+ ```
76
+
77
+ ### IP File Format
78
+
79
+ Create a text file with one IPv4 address per line:
80
+
81
+ ```
82
+ # Manager node
83
+ 192.168.1.1
84
+
85
+ # Worker nodes
86
+ 192.168.1.2
87
+ 192.168.1.3
88
+ 192.168.1.4
89
+ ```
90
+
91
+ ### Token Encryption
92
+
93
+ Encrypt tokens at rest using Fernet:
94
+
95
+ ```bash
96
+ # Generate a key
97
+ python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
98
+
99
+ # Use with mkswarm
100
+ export MKSWARM_KEY="your-generated-key"
101
+ mkswarm init -i ips.txt -m 192.168.1.1 -r 0.2 -o join.sh -k "$MKSWARM_KEY"
102
+ ```
103
+
104
+ ### Proxy Support
105
+
106
+ Use SOCKS4, SOCKS5, or HTTP proxy:
107
+
108
+ ```bash
109
+ mkswarm init -i ips.txt -m 192.168.1.1 -r 0.2 -o join.sh -p socks5://proxy:1080
110
+ ```
111
+
112
+ ### TLS Support
113
+
114
+ Configure mutual TLS for Docker TCP connections:
115
+
116
+ ```bash
117
+ mkswarm init -i ips.txt -m 192.168.1.1 -r 0.2 -o join.sh \
118
+ --tls-cert client-cert.pem \
119
+ --tls-key client-key.pem \
120
+ --tls-ca ca.pem
121
+ ```
122
+
123
+ ## CLI Options
124
+
125
+ ### Global Options
126
+
127
+ - `--db FILE` - SQLite database path (default: swarm.db)
128
+ - `--verbose` - Enable debug logging
129
+ - `--quiet` - Suppress warnings
130
+ - `--log-file FILE` - Append logs to file
131
+ - `--dry-run` - Preview actions without contacting Docker or writing files
132
+
133
+ ### Subcommands
134
+
135
+ - `init` - Bootstrap a new swarm
136
+ - `run` - Join pending nodes via Docker SDK
137
+ - `status` - Show swarm state
138
+ - `list` - List all swarms
139
+ - `reemit` - Regenerate join script from DB
140
+ - `destroy` - Force-leave all nodes
141
+
142
+ ## API
143
+
144
+ ```python
145
+ from mkswarm import SwarmDB, encrypt_token, decrypt_token, load_ips
146
+
147
+ # Database operations
148
+ db = SwarmDB("swarm.db")
149
+ swarm_id = db.create_swarm("192.168.1.1", "worker_token", "manager_token", 0.2, "192.168.1.1:2377", "join.sh")
150
+ swarm = db.get_swarm(swarm_id)
151
+ db.close()
152
+
153
+ # Token encryption
154
+ key = generate_key() # Generate new key
155
+ encrypted = encrypt_token(token, key)
156
+ decrypted = decrypt_token(encrypted, key)
157
+
158
+ # IP validation
159
+ ip = parse_ipv4("192.168.1.1")
160
+ ips = load_ips("ips.txt")
161
+ ```
162
+
163
+ ## Development
164
+
165
+ ```bash
166
+ git clone https://github.com/daedalus/mkswarm.git
167
+ cd mkswarm
168
+ pip install -e ".[test]"
169
+
170
+ # run tests
171
+ pytest
172
+
173
+ # format
174
+ ruff format src/ tests/
175
+
176
+ # lint
177
+ ruff check src/ tests/
178
+
179
+ # type check
180
+ mypy src/
181
+ ```
182
+
183
+ ## License
184
+
185
+ MIT License - see LICENSE file for details.
@@ -0,0 +1,145 @@
1
+ # mkswarm
2
+
3
+ CLI tool for bootstrapping and managing Docker Swarm clusters.
4
+
5
+ [![PyPI](https://img.shields.io/pypi/v/mkswarm.svg)](https://pypi.org/project/mkswarm/)
6
+ [![Python](https://img.shields.io/pypi/pyversions/mkswarm.svg)](https://pypi.org/project/mkswarm/)
7
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ pip install mkswarm
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ```bash
18
+ # Initialize a new Docker Swarm
19
+ mkswarm init -i ips.txt -m 192.168.1.1 -r 0.2 -o join.sh
20
+
21
+ # Run pending node joins via Docker SDK
22
+ mkswarm run 1
23
+
24
+ # Show swarm state
25
+ mkswarm status 1
26
+
27
+ # List all swarms
28
+ mkswarm list
29
+
30
+ # Regenerate join script from database
31
+ mkswarm reemit 1 -o new_join.sh
32
+
33
+ # Force-leave all nodes and destroy swarm
34
+ mkswarm destroy 1
35
+ ```
36
+
37
+ ### IP File Format
38
+
39
+ Create a text file with one IPv4 address per line:
40
+
41
+ ```
42
+ # Manager node
43
+ 192.168.1.1
44
+
45
+ # Worker nodes
46
+ 192.168.1.2
47
+ 192.168.1.3
48
+ 192.168.1.4
49
+ ```
50
+
51
+ ### Token Encryption
52
+
53
+ Encrypt tokens at rest using Fernet:
54
+
55
+ ```bash
56
+ # Generate a key
57
+ python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
58
+
59
+ # Use with mkswarm
60
+ export MKSWARM_KEY="your-generated-key"
61
+ mkswarm init -i ips.txt -m 192.168.1.1 -r 0.2 -o join.sh -k "$MKSWARM_KEY"
62
+ ```
63
+
64
+ ### Proxy Support
65
+
66
+ Use SOCKS4, SOCKS5, or HTTP proxy:
67
+
68
+ ```bash
69
+ mkswarm init -i ips.txt -m 192.168.1.1 -r 0.2 -o join.sh -p socks5://proxy:1080
70
+ ```
71
+
72
+ ### TLS Support
73
+
74
+ Configure mutual TLS for Docker TCP connections:
75
+
76
+ ```bash
77
+ mkswarm init -i ips.txt -m 192.168.1.1 -r 0.2 -o join.sh \
78
+ --tls-cert client-cert.pem \
79
+ --tls-key client-key.pem \
80
+ --tls-ca ca.pem
81
+ ```
82
+
83
+ ## CLI Options
84
+
85
+ ### Global Options
86
+
87
+ - `--db FILE` - SQLite database path (default: swarm.db)
88
+ - `--verbose` - Enable debug logging
89
+ - `--quiet` - Suppress warnings
90
+ - `--log-file FILE` - Append logs to file
91
+ - `--dry-run` - Preview actions without contacting Docker or writing files
92
+
93
+ ### Subcommands
94
+
95
+ - `init` - Bootstrap a new swarm
96
+ - `run` - Join pending nodes via Docker SDK
97
+ - `status` - Show swarm state
98
+ - `list` - List all swarms
99
+ - `reemit` - Regenerate join script from DB
100
+ - `destroy` - Force-leave all nodes
101
+
102
+ ## API
103
+
104
+ ```python
105
+ from mkswarm import SwarmDB, encrypt_token, decrypt_token, load_ips
106
+
107
+ # Database operations
108
+ db = SwarmDB("swarm.db")
109
+ swarm_id = db.create_swarm("192.168.1.1", "worker_token", "manager_token", 0.2, "192.168.1.1:2377", "join.sh")
110
+ swarm = db.get_swarm(swarm_id)
111
+ db.close()
112
+
113
+ # Token encryption
114
+ key = generate_key() # Generate new key
115
+ encrypted = encrypt_token(token, key)
116
+ decrypted = decrypt_token(encrypted, key)
117
+
118
+ # IP validation
119
+ ip = parse_ipv4("192.168.1.1")
120
+ ips = load_ips("ips.txt")
121
+ ```
122
+
123
+ ## Development
124
+
125
+ ```bash
126
+ git clone https://github.com/daedalus/mkswarm.git
127
+ cd mkswarm
128
+ pip install -e ".[test]"
129
+
130
+ # run tests
131
+ pytest
132
+
133
+ # format
134
+ ruff format src/ tests/
135
+
136
+ # lint
137
+ ruff check src/ tests/
138
+
139
+ # type check
140
+ mypy src/
141
+ ```
142
+
143
+ ## License
144
+
145
+ MIT License - see LICENSE file for details.
@@ -0,0 +1,93 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "mkswarm"
7
+ version = "0.1.0"
8
+ description = "CLI tool for bootstrapping and managing Docker Swarm clusters"
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ license = {text = "MIT"}
12
+ authors = [
13
+ {name = "Dario Clavijo", email = "clavijodario@gmail.com"}
14
+ ]
15
+ dependencies = [
16
+ "docker>=7.0.0",
17
+ "PySocks>=1.7.1",
18
+ "cryptography>=42.0.0",
19
+ ]
20
+
21
+ [project.optional-dependencies]
22
+ dev = [
23
+ "ruff",
24
+ "mypy",
25
+ "hatch",
26
+ "pip-api",
27
+ ]
28
+ test = [
29
+ "pytest",
30
+ "pytest-cov",
31
+ "pytest-mock",
32
+ "pytest-asyncio",
33
+ "hypothesis",
34
+ ]
35
+ lint = [
36
+ "ruff",
37
+ "mypy",
38
+ ]
39
+ all = ["mkswarm[dev,test,lint]"]
40
+
41
+ [project.scripts]
42
+ mkswarm = "mkswarm.__main__:main"
43
+
44
+ [project.urls]
45
+ Homepage = "https://github.com/daedalus/mkswarm"
46
+ Repository = "https://github.com/daedalus/mkswarm"
47
+ Issues = "https://github.com/daedalus/mkswarm/issues"
48
+
49
+ [tool.hatch.build.targets.wheel]
50
+ packages = ["src/mkswarm"]
51
+
52
+ [tool.hatch.build.targets.sdist]
53
+ include = ["src/mkswarm"]
54
+
55
+ [tool.ruff]
56
+ line-length = 88
57
+ target-version = "py311"
58
+
59
+ [tool.ruff.lint]
60
+ select = ["E", "F", "W", "I", "UP", "ANN", "TCH", "N", "C4", "ARG"]
61
+ ignore = ["E501"]
62
+
63
+ [tool.ruff.lint.per-file-ignores]
64
+ "__init__.py" = ["F401"]
65
+
66
+ [tool.ruff.lint.pydocstyle]
67
+ convention = "google"
68
+
69
+ [tool.mypy]
70
+ python_version = "3.11"
71
+ strict = true
72
+ warn_return_any = true
73
+ warn_unused_ignores = true
74
+
75
+ [tool.pytest.ini_options]
76
+ testpaths = ["tests"]
77
+ addopts = "-v --tb=short --cov=src --cov-fail-under=80"
78
+ filterwarnings = ["ignore::DeprecationWarning"]
79
+
80
+ [tool.coverage.run]
81
+ source = ["src"]
82
+ branch = true
83
+
84
+ [tool.coverage.report]
85
+ exclude = ["tests/*", "*/__init__.py"]
86
+ exclude_lines = [
87
+ "pragma: no cover",
88
+ "def __repr__",
89
+ "raise AssertionError",
90
+ "raise NotImplementedError",
91
+ "if __name__ == .__main__.:",
92
+ "if TYPE_CHECKING:",
93
+ ]
@@ -0,0 +1,38 @@
1
+ __version__ = "0.1.0"
2
+ __all__ = [
3
+ "SwarmDB",
4
+ "encrypt_token",
5
+ "decrypt_token",
6
+ "generate_key",
7
+ "load_ips",
8
+ "parse_ipv4",
9
+ "check_reachable",
10
+ "configure_proxy",
11
+ "make_client",
12
+ "render_join_script",
13
+ "main",
14
+ "cli",
15
+ "KEY_ENV",
16
+ "DEFAULT_DB",
17
+ "DOCKER_PORT",
18
+ ]
19
+
20
+ from typing import TYPE_CHECKING
21
+
22
+ if TYPE_CHECKING:
23
+ from . import cli as cli_module
24
+ from .crypto import decrypt_token, encrypt_token, generate_key
25
+ from .db import SwarmDB
26
+ from .docker_client import check_reachable, configure_proxy, make_client
27
+ from .scripts import render_join_script
28
+ from .validation import load_ips, parse_ipv4
29
+
30
+
31
+ from . import cli as cli_module
32
+ from .crypto import decrypt_token, encrypt_token, generate_key
33
+ from .db import DEFAULT_DB, KEY_ENV, SwarmDB
34
+ from .docker_client import DOCKER_PORT, check_reachable, configure_proxy, make_client
35
+ from .scripts import render_join_script
36
+ from .validation import load_ips, parse_ipv4
37
+
38
+ main = cli_module.main
@@ -0,0 +1,18 @@
1
+ """Main entry point for mkswarm CLI."""
2
+
3
+
4
+ from mkswarm import cli
5
+
6
+
7
+ def main() -> int:
8
+ """Main entry point.
9
+
10
+ Returns:
11
+ Exit code.
12
+ """
13
+ cli.main()
14
+ return 0
15
+
16
+
17
+ if __name__ == "__main__":
18
+ raise SystemExit(main())