nullgate 1.2.2__tar.gz → 1.2.4__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.
- {nullgate-1.2.2/src/nullgate.egg-info → nullgate-1.2.4}/PKG-INFO +11 -10
- {nullgate-1.2.2 → nullgate-1.2.4}/README.md +10 -9
- nullgate-1.2.4/src/nullgate/__init__.py +1 -0
- {nullgate-1.2.2 → nullgate-1.2.4}/src/nullgate/commands.py +39 -1
- {nullgate-1.2.2 → nullgate-1.2.4}/src/nullgate/session.py +1 -1
- {nullgate-1.2.2 → nullgate-1.2.4}/src/nullgate/transports.py +2 -2
- {nullgate-1.2.2 → nullgate-1.2.4/src/nullgate.egg-info}/PKG-INFO +11 -10
- {nullgate-1.2.2 → nullgate-1.2.4}/tests/test_commands.py +42 -3
- nullgate-1.2.2/src/nullgate/__init__.py +0 -1
- {nullgate-1.2.2 → nullgate-1.2.4}/LICENSE +0 -0
- {nullgate-1.2.2 → nullgate-1.2.4}/pyproject.toml +0 -0
- {nullgate-1.2.2 → nullgate-1.2.4}/setup.cfg +0 -0
- {nullgate-1.2.2 → nullgate-1.2.4}/src/nullgate/account.py +0 -0
- {nullgate-1.2.2 → nullgate-1.2.4}/src/nullgate/bridge.py +0 -0
- {nullgate-1.2.2 → nullgate-1.2.4}/src/nullgate/client_config.py +0 -0
- {nullgate-1.2.2 → nullgate-1.2.4}/src/nullgate/gateway.py +0 -0
- {nullgate-1.2.2 → nullgate-1.2.4}/src/nullgate/ingress.py +0 -0
- {nullgate-1.2.2 → nullgate-1.2.4}/src/nullgate/runtime.py +0 -0
- {nullgate-1.2.2 → nullgate-1.2.4}/src/nullgate/wsroute.py +0 -0
- {nullgate-1.2.2 → nullgate-1.2.4}/src/nullgate.egg-info/SOURCES.txt +0 -0
- {nullgate-1.2.2 → nullgate-1.2.4}/src/nullgate.egg-info/dependency_links.txt +0 -0
- {nullgate-1.2.2 → nullgate-1.2.4}/src/nullgate.egg-info/entry_points.txt +0 -0
- {nullgate-1.2.2 → nullgate-1.2.4}/src/nullgate.egg-info/requires.txt +0 -0
- {nullgate-1.2.2 → nullgate-1.2.4}/src/nullgate.egg-info/top_level.txt +0 -0
- {nullgate-1.2.2 → nullgate-1.2.4}/tests/test_account.py +0 -0
- {nullgate-1.2.2 → nullgate-1.2.4}/tests/test_bridge.py +0 -0
- {nullgate-1.2.2 → nullgate-1.2.4}/tests/test_gateway.py +0 -0
- {nullgate-1.2.2 → nullgate-1.2.4}/tests/test_ingress.py +0 -0
- {nullgate-1.2.2 → nullgate-1.2.4}/tests/test_install.py +0 -0
- {nullgate-1.2.2 → nullgate-1.2.4}/tests/test_wsroute.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nullgate
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.4
|
|
4
4
|
Summary: Disposable SSH gateway into confined directory workspaces
|
|
5
5
|
Requires-Python: >=3.10
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -19,7 +19,7 @@ Disposable SSH gateway into confined directory workspaces for remote containers,
|
|
|
19
19
|
Run Nullgate directly from PyPI without installing it first:
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
# Share the current directory over the default
|
|
22
|
+
# Share the current directory over the default srv.us provider
|
|
23
23
|
uvx nullgate start
|
|
24
24
|
|
|
25
25
|
# Share a specific workspace
|
|
@@ -36,13 +36,12 @@ uvx nullgate status
|
|
|
36
36
|
uvx nullgate connect
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
Nullgate
|
|
40
|
-
|
|
41
|
-
temporary endpoint.
|
|
39
|
+
Nullgate allows connections without credentials by default. Use
|
|
40
|
+
`--no-public-access` to require an authorized SSH key or generated password.
|
|
42
41
|
|
|
43
42
|
## Features
|
|
44
43
|
|
|
45
|
-
- **Ingress Transports**: Publish endpoints via
|
|
44
|
+
- **Ingress Transports**: Publish endpoints via srv.us reverse tunnels (default), Upterm WebSocket relays, Cloudflare Worker relays, or Cloudflare Argo (`cloudflared`) tunnels.
|
|
46
45
|
- **Confinement**: SFTP and SCP workloads are restricted to the designated workspace root; parent traversals and out-of-root symlinks are blocked.
|
|
47
46
|
- **Host file visibility**: Relative transfer paths begin in the workspace root while absolute paths address host locations, matching shell behavior; add `--restrict-file-transfer` for strict workspace-only transfers.
|
|
48
47
|
- **Direct Shell Access**: Authenticated PTY sessions run interactively under the local user credentials.
|
|
@@ -75,7 +74,7 @@ pip install nullgate
|
|
|
75
74
|
Launch the gateway service and ingress transport in the background:
|
|
76
75
|
|
|
77
76
|
```bash
|
|
78
|
-
# Default
|
|
77
|
+
# Default srv.us transport on port 4822 sharing current directory
|
|
79
78
|
nullgate start
|
|
80
79
|
|
|
81
80
|
# Custom path, port, and slot
|
|
@@ -94,11 +93,11 @@ nullgate start . --provider cloudflared --public-hostname workspace.example.com
|
|
|
94
93
|
Options:
|
|
95
94
|
- `-p`, `--ssh-port`: Local SSH server port.
|
|
96
95
|
- `-s`, `--tunnel-slot`: srv.us tunnel slot.
|
|
97
|
-
- `-t`, `--provider`: Public connection provider (`upterm`, `srvus`, `cloudflare`, or `cloudflared`). Defaults to `
|
|
96
|
+
- `-t`, `--provider`: Public connection provider (`upterm`, `srvus`, `cloudflare`, or `cloudflared`). Defaults to `srvus`.
|
|
98
97
|
- `-e`, `--relay-url`: WebSocket relay URL used with `upterm` or `cloudflare`.
|
|
99
98
|
- `-H`, `--public-hostname`: Public hostname used with `cloudflared`.
|
|
100
99
|
- `--cloudflare-token`: Cloudflare tunnel credential, or set `NULLGATE_CLOUDFLARED_TOKEN`.
|
|
101
|
-
- `--public-access`: Allow connections without credentials.
|
|
100
|
+
- `--public-access`: Allow connections without credentials. Enabled by default and unsafe on public endpoints.
|
|
102
101
|
- `--no-public-access`: Require authentication.
|
|
103
102
|
- `--tcp-forwarding`: Enable SSH TCP tunneling (`ssh -L`).
|
|
104
103
|
- `--no-tcp-forwarding`: Disable SSH TCP tunneling.
|
|
@@ -161,10 +160,12 @@ Short command aliases are `up`, `down`, `ps`, `ssh`, `log`, and `reload`.
|
|
|
161
160
|
The earlier names `open`, `shut`, `inspect`, `enter`, `trace`, and `cycle`
|
|
162
161
|
remain available as compatibility aliases. Their earlier option names also
|
|
163
162
|
remain accepted, but new scripts should use the names documented above.
|
|
163
|
+
Unknown flags and their optional values are ignored for compatibility with
|
|
164
|
+
external launchers.
|
|
164
165
|
|
|
165
166
|
## Authentication and Security Boundaries
|
|
166
167
|
|
|
167
|
-
- **Authentication Baseline**:
|
|
168
|
+
- **Authentication Baseline**: Public access is enabled by default. Pass `--no-public-access` to require authorized SSH keys from `~/.ssh/authorized_keys` or a high-entropy secret created in the runtime directory.
|
|
168
169
|
- **Public access (`--public-access`)**: Bypasses authentication checks entirely; any incoming connection with network access is accepted.
|
|
169
170
|
- **Upterm Transport**: Relies on authorized SSH public keys or `--public-access` (Upterm does not support password authentication). The relay itself is trusted for inbound multiplexing.
|
|
170
171
|
- **Filesystem Confinement**: SFTP and SCP access cannot escape the designated workspace directory.
|
|
@@ -7,7 +7,7 @@ Disposable SSH gateway into confined directory workspaces for remote containers,
|
|
|
7
7
|
Run Nullgate directly from PyPI without installing it first:
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
# Share the current directory over the default
|
|
10
|
+
# Share the current directory over the default srv.us provider
|
|
11
11
|
uvx nullgate start
|
|
12
12
|
|
|
13
13
|
# Share a specific workspace
|
|
@@ -24,13 +24,12 @@ uvx nullgate status
|
|
|
24
24
|
uvx nullgate connect
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
Nullgate
|
|
28
|
-
|
|
29
|
-
temporary endpoint.
|
|
27
|
+
Nullgate allows connections without credentials by default. Use
|
|
28
|
+
`--no-public-access` to require an authorized SSH key or generated password.
|
|
30
29
|
|
|
31
30
|
## Features
|
|
32
31
|
|
|
33
|
-
- **Ingress Transports**: Publish endpoints via
|
|
32
|
+
- **Ingress Transports**: Publish endpoints via srv.us reverse tunnels (default), Upterm WebSocket relays, Cloudflare Worker relays, or Cloudflare Argo (`cloudflared`) tunnels.
|
|
34
33
|
- **Confinement**: SFTP and SCP workloads are restricted to the designated workspace root; parent traversals and out-of-root symlinks are blocked.
|
|
35
34
|
- **Host file visibility**: Relative transfer paths begin in the workspace root while absolute paths address host locations, matching shell behavior; add `--restrict-file-transfer` for strict workspace-only transfers.
|
|
36
35
|
- **Direct Shell Access**: Authenticated PTY sessions run interactively under the local user credentials.
|
|
@@ -63,7 +62,7 @@ pip install nullgate
|
|
|
63
62
|
Launch the gateway service and ingress transport in the background:
|
|
64
63
|
|
|
65
64
|
```bash
|
|
66
|
-
# Default
|
|
65
|
+
# Default srv.us transport on port 4822 sharing current directory
|
|
67
66
|
nullgate start
|
|
68
67
|
|
|
69
68
|
# Custom path, port, and slot
|
|
@@ -82,11 +81,11 @@ nullgate start . --provider cloudflared --public-hostname workspace.example.com
|
|
|
82
81
|
Options:
|
|
83
82
|
- `-p`, `--ssh-port`: Local SSH server port.
|
|
84
83
|
- `-s`, `--tunnel-slot`: srv.us tunnel slot.
|
|
85
|
-
- `-t`, `--provider`: Public connection provider (`upterm`, `srvus`, `cloudflare`, or `cloudflared`). Defaults to `
|
|
84
|
+
- `-t`, `--provider`: Public connection provider (`upterm`, `srvus`, `cloudflare`, or `cloudflared`). Defaults to `srvus`.
|
|
86
85
|
- `-e`, `--relay-url`: WebSocket relay URL used with `upterm` or `cloudflare`.
|
|
87
86
|
- `-H`, `--public-hostname`: Public hostname used with `cloudflared`.
|
|
88
87
|
- `--cloudflare-token`: Cloudflare tunnel credential, or set `NULLGATE_CLOUDFLARED_TOKEN`.
|
|
89
|
-
- `--public-access`: Allow connections without credentials.
|
|
88
|
+
- `--public-access`: Allow connections without credentials. Enabled by default and unsafe on public endpoints.
|
|
90
89
|
- `--no-public-access`: Require authentication.
|
|
91
90
|
- `--tcp-forwarding`: Enable SSH TCP tunneling (`ssh -L`).
|
|
92
91
|
- `--no-tcp-forwarding`: Disable SSH TCP tunneling.
|
|
@@ -149,10 +148,12 @@ Short command aliases are `up`, `down`, `ps`, `ssh`, `log`, and `reload`.
|
|
|
149
148
|
The earlier names `open`, `shut`, `inspect`, `enter`, `trace`, and `cycle`
|
|
150
149
|
remain available as compatibility aliases. Their earlier option names also
|
|
151
150
|
remain accepted, but new scripts should use the names documented above.
|
|
151
|
+
Unknown flags and their optional values are ignored for compatibility with
|
|
152
|
+
external launchers.
|
|
152
153
|
|
|
153
154
|
## Authentication and Security Boundaries
|
|
154
155
|
|
|
155
|
-
- **Authentication Baseline**:
|
|
156
|
+
- **Authentication Baseline**: Public access is enabled by default. Pass `--no-public-access` to require authorized SSH keys from `~/.ssh/authorized_keys` or a high-entropy secret created in the runtime directory.
|
|
156
157
|
- **Public access (`--public-access`)**: Bypasses authentication checks entirely; any incoming connection with network access is accepted.
|
|
157
158
|
- **Upterm Transport**: Relies on authorized SSH public keys or `--public-access` (Upterm does not support password authentication). The relay itself is trusted for inbound multiplexing.
|
|
158
159
|
- **Filesystem Confinement**: SFTP and SCP access cannot escape the designated workspace directory.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.2.4"
|
|
@@ -236,9 +236,47 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
236
236
|
return parser
|
|
237
237
|
|
|
238
238
|
|
|
239
|
+
def _known_options(parser: argparse.ArgumentParser) -> set[str]:
|
|
240
|
+
options = set(parser._option_string_actions)
|
|
241
|
+
for action in parser._actions:
|
|
242
|
+
if isinstance(action, argparse._SubParsersAction):
|
|
243
|
+
for child in action.choices.values():
|
|
244
|
+
options.update(_known_options(child))
|
|
245
|
+
return options
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def _discard_unknown_options(
|
|
249
|
+
parser: argparse.ArgumentParser, argv: Sequence[str]
|
|
250
|
+
) -> list[str]:
|
|
251
|
+
"""Drop integration flags, including a following value when present."""
|
|
252
|
+
|
|
253
|
+
known = _known_options(parser)
|
|
254
|
+
filtered: list[str] = []
|
|
255
|
+
index = 0
|
|
256
|
+
while index < len(argv):
|
|
257
|
+
token = argv[index]
|
|
258
|
+
option = token.split("=", 1)[0]
|
|
259
|
+
if token.startswith("-") and option not in known:
|
|
260
|
+
index += 1
|
|
261
|
+
if (
|
|
262
|
+
"=" not in token
|
|
263
|
+
and index < len(argv)
|
|
264
|
+
and not argv[index].startswith("-")
|
|
265
|
+
and argv[index] not in SUBCOMMANDS
|
|
266
|
+
):
|
|
267
|
+
index += 1
|
|
268
|
+
continue
|
|
269
|
+
filtered.append(token)
|
|
270
|
+
index += 1
|
|
271
|
+
return filtered
|
|
272
|
+
|
|
273
|
+
|
|
239
274
|
def main(argv: Sequence[str] | None = None) -> int:
|
|
240
275
|
parser = build_parser()
|
|
241
|
-
|
|
276
|
+
supplied = list(sys.argv[1:] if argv is None else argv)
|
|
277
|
+
if supplied in (["--help"], ["api", "--help"]):
|
|
278
|
+
supplied = ["start"]
|
|
279
|
+
args = parser.parse_args(_discard_unknown_options(parser, supplied))
|
|
242
280
|
|
|
243
281
|
handlers = {
|
|
244
282
|
"start": session.cmd_open,
|
|
@@ -254,7 +254,7 @@ def cmd_open(args: Any) -> int:
|
|
|
254
254
|
die(f"Port {port} is already in use")
|
|
255
255
|
|
|
256
256
|
accept_arg = getattr(args, "accept", None)
|
|
257
|
-
accept = saved.get("accept") == "1" if accept_arg is None else bool(accept_arg)
|
|
257
|
+
accept = saved.get("accept", "1") == "1" if accept_arg is None else bool(accept_arg)
|
|
258
258
|
forwarding_arg = getattr(args, "allow_tcp_forwarding", None)
|
|
259
259
|
allow_tcp_forwarding = (
|
|
260
260
|
saved.get("allow_tcp_forwarding") == "1"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Transport mechanisms and process orchestration for Nullgate.
|
|
2
2
|
|
|
3
|
-
Supports Upterm
|
|
3
|
+
Supports Upterm, srv.us reverse tunnels (default), Cloudflare Worker relays,
|
|
4
4
|
and Cloudflare Argo (cloudflared) tunnels.
|
|
5
5
|
"""
|
|
6
6
|
|
|
@@ -22,7 +22,7 @@ from nullgate import bridge, client_config, gateway, ingress, wsroute
|
|
|
22
22
|
from nullgate.account import ensure_username_environment
|
|
23
23
|
import nullgate.runtime as st
|
|
24
24
|
|
|
25
|
-
DEFAULT_TRANSPORT = "
|
|
25
|
+
DEFAULT_TRANSPORT = "srvus"
|
|
26
26
|
VALID_TRANSPORTS = ("upterm", "srvus", "cloudflare", "cloudflared")
|
|
27
27
|
|
|
28
28
|
_PKG_SRC = str(Path(__file__).resolve().parent.parent)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nullgate
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.4
|
|
4
4
|
Summary: Disposable SSH gateway into confined directory workspaces
|
|
5
5
|
Requires-Python: >=3.10
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -19,7 +19,7 @@ Disposable SSH gateway into confined directory workspaces for remote containers,
|
|
|
19
19
|
Run Nullgate directly from PyPI without installing it first:
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
# Share the current directory over the default
|
|
22
|
+
# Share the current directory over the default srv.us provider
|
|
23
23
|
uvx nullgate start
|
|
24
24
|
|
|
25
25
|
# Share a specific workspace
|
|
@@ -36,13 +36,12 @@ uvx nullgate status
|
|
|
36
36
|
uvx nullgate connect
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
Nullgate
|
|
40
|
-
|
|
41
|
-
temporary endpoint.
|
|
39
|
+
Nullgate allows connections without credentials by default. Use
|
|
40
|
+
`--no-public-access` to require an authorized SSH key or generated password.
|
|
42
41
|
|
|
43
42
|
## Features
|
|
44
43
|
|
|
45
|
-
- **Ingress Transports**: Publish endpoints via
|
|
44
|
+
- **Ingress Transports**: Publish endpoints via srv.us reverse tunnels (default), Upterm WebSocket relays, Cloudflare Worker relays, or Cloudflare Argo (`cloudflared`) tunnels.
|
|
46
45
|
- **Confinement**: SFTP and SCP workloads are restricted to the designated workspace root; parent traversals and out-of-root symlinks are blocked.
|
|
47
46
|
- **Host file visibility**: Relative transfer paths begin in the workspace root while absolute paths address host locations, matching shell behavior; add `--restrict-file-transfer` for strict workspace-only transfers.
|
|
48
47
|
- **Direct Shell Access**: Authenticated PTY sessions run interactively under the local user credentials.
|
|
@@ -75,7 +74,7 @@ pip install nullgate
|
|
|
75
74
|
Launch the gateway service and ingress transport in the background:
|
|
76
75
|
|
|
77
76
|
```bash
|
|
78
|
-
# Default
|
|
77
|
+
# Default srv.us transport on port 4822 sharing current directory
|
|
79
78
|
nullgate start
|
|
80
79
|
|
|
81
80
|
# Custom path, port, and slot
|
|
@@ -94,11 +93,11 @@ nullgate start . --provider cloudflared --public-hostname workspace.example.com
|
|
|
94
93
|
Options:
|
|
95
94
|
- `-p`, `--ssh-port`: Local SSH server port.
|
|
96
95
|
- `-s`, `--tunnel-slot`: srv.us tunnel slot.
|
|
97
|
-
- `-t`, `--provider`: Public connection provider (`upterm`, `srvus`, `cloudflare`, or `cloudflared`). Defaults to `
|
|
96
|
+
- `-t`, `--provider`: Public connection provider (`upterm`, `srvus`, `cloudflare`, or `cloudflared`). Defaults to `srvus`.
|
|
98
97
|
- `-e`, `--relay-url`: WebSocket relay URL used with `upterm` or `cloudflare`.
|
|
99
98
|
- `-H`, `--public-hostname`: Public hostname used with `cloudflared`.
|
|
100
99
|
- `--cloudflare-token`: Cloudflare tunnel credential, or set `NULLGATE_CLOUDFLARED_TOKEN`.
|
|
101
|
-
- `--public-access`: Allow connections without credentials.
|
|
100
|
+
- `--public-access`: Allow connections without credentials. Enabled by default and unsafe on public endpoints.
|
|
102
101
|
- `--no-public-access`: Require authentication.
|
|
103
102
|
- `--tcp-forwarding`: Enable SSH TCP tunneling (`ssh -L`).
|
|
104
103
|
- `--no-tcp-forwarding`: Disable SSH TCP tunneling.
|
|
@@ -161,10 +160,12 @@ Short command aliases are `up`, `down`, `ps`, `ssh`, `log`, and `reload`.
|
|
|
161
160
|
The earlier names `open`, `shut`, `inspect`, `enter`, `trace`, and `cycle`
|
|
162
161
|
remain available as compatibility aliases. Their earlier option names also
|
|
163
162
|
remain accepted, but new scripts should use the names documented above.
|
|
163
|
+
Unknown flags and their optional values are ignored for compatibility with
|
|
164
|
+
external launchers.
|
|
164
165
|
|
|
165
166
|
## Authentication and Security Boundaries
|
|
166
167
|
|
|
167
|
-
- **Authentication Baseline**:
|
|
168
|
+
- **Authentication Baseline**: Public access is enabled by default. Pass `--no-public-access` to require authorized SSH keys from `~/.ssh/authorized_keys` or a high-entropy secret created in the runtime directory.
|
|
168
169
|
- **Public access (`--public-access`)**: Bypasses authentication checks entirely; any incoming connection with network access is accepted.
|
|
169
170
|
- **Upterm Transport**: Relies on authorized SSH public keys or `--public-access` (Upterm does not support password authentication). The relay itself is trusted for inbound multiplexing.
|
|
170
171
|
- **Filesystem Confinement**: SFTP and SCP access cannot escape the designated workspace directory.
|
|
@@ -124,7 +124,7 @@ class CLILifecycleTests(unittest.TestCase):
|
|
|
124
124
|
parser = commands.build_parser()
|
|
125
125
|
defaults = parser.parse_args(["start"])
|
|
126
126
|
self.assertEqual(session.DEFAULT_PORT, 4822)
|
|
127
|
-
self.assertEqual(transports.DEFAULT_TRANSPORT, "
|
|
127
|
+
self.assertEqual(transports.DEFAULT_TRANSPORT, "srvus")
|
|
128
128
|
self.assertIsNone(defaults.workspace)
|
|
129
129
|
self.assertIsNone(defaults.port_arg)
|
|
130
130
|
self.assertIsNone(defaults.slot_arg)
|
|
@@ -201,6 +201,45 @@ class CLILifecycleTests(unittest.TestCase):
|
|
|
201
201
|
):
|
|
202
202
|
self.assertEqual(parser.parse_args([alias]).command, expected)
|
|
203
203
|
|
|
204
|
+
@mock.patch("nullgate.session.cmd_open", return_value=0)
|
|
205
|
+
def test_unknown_flags_and_values_are_ignored(self, cmd_open):
|
|
206
|
+
self.assertEqual(
|
|
207
|
+
commands.main(
|
|
208
|
+
[
|
|
209
|
+
"start",
|
|
210
|
+
".",
|
|
211
|
+
"--notte-api",
|
|
212
|
+
"--notte-user",
|
|
213
|
+
"admin",
|
|
214
|
+
"--ssh-port",
|
|
215
|
+
"2222",
|
|
216
|
+
]
|
|
217
|
+
),
|
|
218
|
+
0,
|
|
219
|
+
)
|
|
220
|
+
args = cmd_open.call_args.args[0]
|
|
221
|
+
self.assertEqual(args.workspace, ".")
|
|
222
|
+
self.assertEqual(args.port, 2222)
|
|
223
|
+
|
|
224
|
+
cmd_open.reset_mock()
|
|
225
|
+
self.assertEqual(commands.main(["start", "--notte-user", "admin"]), 0)
|
|
226
|
+
self.assertIsNone(cmd_open.call_args.args[0].workspace)
|
|
227
|
+
|
|
228
|
+
@mock.patch("nullgate.session.cmd_open", return_value=0)
|
|
229
|
+
def test_selected_help_forms_start_nullgate(self, cmd_open):
|
|
230
|
+
self.assertEqual(commands.main(["--help"]), 0)
|
|
231
|
+
self.assertEqual(commands.main(["api", "--help"]), 0)
|
|
232
|
+
self.assertEqual(cmd_open.call_count, 2)
|
|
233
|
+
for call in cmd_open.call_args_list:
|
|
234
|
+
self.assertEqual(call.args[0].command, "start")
|
|
235
|
+
|
|
236
|
+
def test_short_and_start_help_remain_help(self):
|
|
237
|
+
for argv in (["-h"], ["start", "--help"]):
|
|
238
|
+
code, stdout, stderr = run_cli(argv)
|
|
239
|
+
self.assertEqual(code, 0)
|
|
240
|
+
self.assertIn("usage: nullgate", stdout)
|
|
241
|
+
self.assertEqual(stderr, "")
|
|
242
|
+
|
|
204
243
|
def test_positional_start_values_and_options_resolve(self):
|
|
205
244
|
parser = commands.build_parser()
|
|
206
245
|
positional = parser.parse_args(["start", ".", "2222", "3"])
|
|
@@ -407,7 +446,7 @@ class CLILifecycleTests(unittest.TestCase):
|
|
|
407
446
|
self.assertIn("Fixed permissions on", err)
|
|
408
447
|
self.assertIn("(was 660, now 600)", err)
|
|
409
448
|
self.assertEqual(key.stat().st_mode & 0o777, 0o600)
|
|
410
|
-
self.
|
|
449
|
+
self.assertFalse((state / "password").exists())
|
|
411
450
|
|
|
412
451
|
code, out, err = run_cli(["status"], env=env)
|
|
413
452
|
self.assertEqual(code, 0)
|
|
@@ -416,7 +455,7 @@ class CLILifecycleTests(unittest.TestCase):
|
|
|
416
455
|
self.assertIn(f"url https://{SRVUS_HOST}/", out)
|
|
417
456
|
self.assertNotIn("\x1b[", out)
|
|
418
457
|
self.assertIn(f"connect ssh {getpass.getuser()}@{SRVUS_HOST}", out)
|
|
419
|
-
self.assertIn("
|
|
458
|
+
self.assertIn("auth none (--public-access); anyone can connect", out)
|
|
420
459
|
self.assertNotIn("logs transport -f", out)
|
|
421
460
|
|
|
422
461
|
code, out, err = run_cli(["connect"], env=env)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "1.2.2"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|