mrok 0.2.3__py3-none-any.whl → 0.4.0__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.
Files changed (56) hide show
  1. mrok/agent/devtools/__init__.py +0 -0
  2. mrok/agent/devtools/__main__.py +34 -0
  3. mrok/agent/devtools/inspector/__init__.py +0 -0
  4. mrok/agent/devtools/inspector/__main__.py +25 -0
  5. mrok/agent/devtools/inspector/app.py +556 -0
  6. mrok/agent/devtools/inspector/server.py +18 -0
  7. mrok/agent/sidecar/app.py +9 -10
  8. mrok/agent/sidecar/main.py +35 -16
  9. mrok/agent/ziticorn.py +27 -18
  10. mrok/cli/commands/__init__.py +2 -1
  11. mrok/cli/commands/admin/list/instances.py +24 -4
  12. mrok/cli/commands/admin/register/extensions.py +2 -2
  13. mrok/cli/commands/admin/register/instances.py +3 -3
  14. mrok/cli/commands/admin/unregister/extensions.py +2 -2
  15. mrok/cli/commands/admin/unregister/instances.py +2 -2
  16. mrok/cli/commands/agent/__init__.py +2 -0
  17. mrok/cli/commands/agent/dev/__init__.py +7 -0
  18. mrok/cli/commands/agent/dev/console.py +25 -0
  19. mrok/cli/commands/agent/dev/web.py +37 -0
  20. mrok/cli/commands/agent/run/asgi.py +35 -16
  21. mrok/cli/commands/agent/run/sidecar.py +29 -13
  22. mrok/cli/commands/agent/utils.py +5 -0
  23. mrok/cli/commands/controller/run.py +1 -5
  24. mrok/cli/commands/proxy/__init__.py +6 -0
  25. mrok/cli/commands/proxy/run.py +49 -0
  26. mrok/cli/utils.py +5 -0
  27. mrok/conf.py +6 -0
  28. mrok/controller/auth.py +2 -2
  29. mrok/controller/routes/extensions.py +9 -7
  30. mrok/datastructures.py +159 -0
  31. mrok/http/config.py +3 -6
  32. mrok/http/constants.py +22 -0
  33. mrok/http/forwarder.py +62 -23
  34. mrok/http/lifespan.py +29 -0
  35. mrok/http/middlewares.py +143 -0
  36. mrok/http/types.py +43 -0
  37. mrok/http/utils.py +90 -0
  38. mrok/logging.py +22 -0
  39. mrok/master.py +269 -0
  40. mrok/metrics.py +139 -0
  41. mrok/proxy/__init__.py +3 -0
  42. mrok/proxy/app.py +73 -0
  43. mrok/proxy/dataclasses.py +12 -0
  44. mrok/proxy/main.py +58 -0
  45. mrok/proxy/streams.py +124 -0
  46. mrok/proxy/types.py +12 -0
  47. mrok/proxy/ziti.py +173 -0
  48. mrok/ziti/identities.py +50 -20
  49. mrok/ziti/services.py +8 -8
  50. {mrok-0.2.3.dist-info → mrok-0.4.0.dist-info}/METADATA +7 -1
  51. mrok-0.4.0.dist-info/RECORD +92 -0
  52. {mrok-0.2.3.dist-info → mrok-0.4.0.dist-info}/WHEEL +1 -1
  53. mrok/http/master.py +0 -132
  54. mrok-0.2.3.dist-info/RECORD +0 -66
  55. {mrok-0.2.3.dist-info → mrok-0.4.0.dist-info}/entry_points.txt +0 -0
  56. {mrok-0.2.3.dist-info → mrok-0.4.0.dist-info}/licenses/LICENSE.txt +0 -0
@@ -1,27 +1,46 @@
1
- import asyncio
2
- import contextlib
3
- from functools import partial
1
+ import logging
4
2
  from pathlib import Path
5
3
 
6
4
  from mrok.agent.sidecar.app import ForwardApp
7
- from mrok.http.config import MrokBackendConfig
8
- from mrok.http.master import Master
9
- from mrok.http.server import MrokServer
5
+ from mrok.master import MasterBase
10
6
 
7
+ logger = logging.getLogger("mrok.proxy")
11
8
 
12
- def run_sidecar(identity_file: str, target_addr: str | Path | tuple[str, int]):
13
- config = MrokBackendConfig(ForwardApp(target_addr), identity_file)
14
- server = MrokServer(config)
15
- with contextlib.suppress(KeyboardInterrupt, asyncio.CancelledError):
16
- server.run()
9
+
10
+ class SidecarAgent(MasterBase):
11
+ def __init__(
12
+ self,
13
+ identity_file: str,
14
+ target_addr: str | Path | tuple[str, int],
15
+ workers: int = 4,
16
+ publishers_port: int = 50000,
17
+ subscribers_port: int = 50001,
18
+ ):
19
+ super().__init__(
20
+ identity_file,
21
+ workers,
22
+ False,
23
+ publishers_port,
24
+ subscribers_port,
25
+ )
26
+ self.target_address = target_addr
27
+
28
+ def get_asgi_app(self):
29
+ return ForwardApp(self.target_address)
17
30
 
18
31
 
19
32
  def run(
20
33
  identity_file: str,
21
34
  target_addr: str | Path | tuple[str, int],
22
- workers=4,
23
- reload=False,
35
+ workers: int = 4,
36
+ publishers_port: int = 50000,
37
+ subscribers_port: int = 50001,
24
38
  ):
25
- start_fn = partial(run_sidecar, identity_file, target_addr)
26
- master = Master(start_fn, workers=workers, reload=reload)
27
- master.run()
39
+ agent = SidecarAgent(
40
+ identity_file,
41
+ target_addr,
42
+ workers=workers,
43
+ publishers_port=publishers_port,
44
+ subscribers_port=subscribers_port,
45
+ )
46
+ agent.run()
mrok/agent/ziticorn.py CHANGED
@@ -1,29 +1,38 @@
1
- import asyncio
2
- import contextlib
3
- import os
4
- from functools import partial
1
+ from mrok.http.types import ASGIApp
2
+ from mrok.master import MasterBase
5
3
 
6
- from mrok.http.config import ASGIApplication, MrokBackendConfig
7
- from mrok.http.master import Master
8
- from mrok.http.server import MrokServer
9
4
 
5
+ class ZiticornAgent(MasterBase):
6
+ def __init__(
7
+ self,
8
+ app: ASGIApp | str,
9
+ identity_file: str,
10
+ workers: int = 4,
11
+ reload: bool = False,
12
+ publishers_port: int = 50000,
13
+ subscribers_port: int = 50001,
14
+ ):
15
+ super().__init__(identity_file, workers, reload, publishers_port, subscribers_port)
16
+ self.app = app
10
17
 
11
- def run_ziticorn(app: ASGIApplication | str, identity_file: str):
12
- import sys
13
-
14
- sys.path.insert(0, os.getcwd())
15
- config = MrokBackendConfig(app, identity_file)
16
- server = MrokServer(config)
17
- with contextlib.suppress(KeyboardInterrupt, asyncio.CancelledError):
18
- server.run()
18
+ def get_asgi_app(self):
19
+ return self.app
19
20
 
20
21
 
21
22
  def run(
22
- app: ASGIApplication | str,
23
+ app: ASGIApp | str,
23
24
  identity_file: str,
24
25
  workers: int = 4,
25
26
  reload: bool = False,
27
+ publishers_port: int = 50000,
28
+ subscribers_port: int = 50001,
26
29
  ):
27
- start_fn = partial(run_ziticorn, app, identity_file)
28
- master = Master(start_fn, workers=workers, reload=reload)
30
+ master = ZiticornAgent(
31
+ app,
32
+ identity_file,
33
+ workers=workers,
34
+ reload=reload,
35
+ publishers_port=publishers_port,
36
+ subscribers_port=subscribers_port,
37
+ )
29
38
  master.run()
@@ -1,7 +1,8 @@
1
- from mrok.cli.commands import admin, agent, controller
1
+ from mrok.cli.commands import admin, agent, controller, proxy
2
2
 
3
3
  __all__ = [
4
4
  "admin",
5
5
  "agent",
6
6
  "controller",
7
+ "proxy",
7
8
  ]
@@ -21,7 +21,11 @@ from mrok.ziti.constants import (
21
21
 
22
22
 
23
23
  async def get_instances(
24
- settings: Settings, detailed: bool, extension: str | None = None, tags: list[str] | None = None
24
+ settings: Settings,
25
+ detailed: bool,
26
+ extension: str | None = None,
27
+ tags: list[str] | None = None,
28
+ online_only: bool = False,
25
29
  ) -> list[dict]:
26
30
  async with ZitiManagementAPI(settings) as api:
27
31
  tags = tags or []
@@ -29,6 +33,9 @@ async def get_instances(
29
33
  identities = [
30
34
  identity async for identity in api.identities(params={"filter": tags_to_filter(tags)})
31
35
  ]
36
+ if online_only:
37
+ identities = list(filter(lambda i: i["hasEdgeRouterConnection"], identities))
38
+
32
39
  if detailed or extension:
33
40
  for identity in identities:
34
41
  identity["services"] = [
@@ -60,10 +67,11 @@ async def get_instances(
60
67
  def render_tsv(instances: list[dict], detailed: bool) -> None:
61
68
  console = get_console()
62
69
  if detailed:
63
- console.print("id\tname\tservices\tpolicies\ttags\tcreated\tupdated")
70
+ console.print("id\tname\tstatus\tservices\tpolicies\ttags\tcreated\tupdated")
64
71
  for instance in instances:
65
72
  console.print(
66
73
  f"{instance['id']}\t{instance['name']}\t"
74
+ f"{'online' if instance['hasEdgeRouterConnection'] else 'offline'}\t"
67
75
  f"{extract_names(instance['services'], ', ')}\t"
68
76
  f"{extract_names(instance['policies'], ', ')}\t"
69
77
  f"{format_tags(instance['tags'], ', ')}\t"
@@ -71,10 +79,11 @@ def render_tsv(instances: list[dict], detailed: bool) -> None:
71
79
  f"{format_timestamp(instance['updatedAt'])}"
72
80
  )
73
81
  else:
74
- console.print("id\tname\ttags\tcreated")
82
+ console.print("id\tname\tstatus\ttags\tcreated")
75
83
  for instance in instances:
76
84
  console.print(
77
85
  f"{instance['id']}\t{instance['name']}\t"
86
+ f"{'online' if instance['hasEdgeRouterConnection'] else 'offline'}\t"
78
87
  f"{format_tags(instance['tags'], ', ')}\t"
79
88
  f"{format_timestamp(instance['createdAt'])}\t"
80
89
  )
@@ -90,6 +99,7 @@ def render_table(instances: list[dict], detailed: bool) -> None:
90
99
  )
91
100
  table.add_column("Id", style="green")
92
101
  table.add_column("Name", style="bold cyan")
102
+ table.add_column("Status", justify="center")
93
103
  if detailed:
94
104
  table.add_column("Associated services")
95
105
  table.add_column("Associated service policies")
@@ -102,6 +112,7 @@ def render_table(instances: list[dict], detailed: bool) -> None:
102
112
  row = [
103
113
  instance["id"],
104
114
  instance["name"],
115
+ "🟢" if instance["hasEdgeRouterConnection"] else "⚪",
105
116
  ]
106
117
  if detailed:
107
118
  row += [
@@ -142,6 +153,15 @@ def register(app: typer.Typer) -> None:
142
153
  show_default=True,
143
154
  ),
144
155
  ] = None,
156
+ online_only: Annotated[
157
+ bool,
158
+ typer.Option(
159
+ "--online-only",
160
+ "-o",
161
+ help="Show only connected instances",
162
+ show_default=True,
163
+ ),
164
+ ] = False,
145
165
  detailed: bool = typer.Option(
146
166
  False,
147
167
  "--detailed",
@@ -155,7 +175,7 @@ def register(app: typer.Typer) -> None:
155
175
  ),
156
176
  ):
157
177
  """List instances in OpenZiti (identities)."""
158
- instances = asyncio.run(get_instances(ctx.obj, detailed, extension, tags))
178
+ instances = asyncio.run(get_instances(ctx.obj, detailed, extension, tags, online_only))
159
179
 
160
180
  if len(instances) == 0:
161
181
  get_console().print("No instances found.")
@@ -8,14 +8,14 @@ from rich import print
8
8
  from mrok.cli.commands.admin.utils import parse_tags
9
9
  from mrok.conf import Settings
10
10
  from mrok.ziti.api import ZitiManagementAPI
11
- from mrok.ziti.services import register_extension
11
+ from mrok.ziti.services import register_service
12
12
 
13
13
  RE_EXTENSION_ID = re.compile(r"(?i)EXT-\d{4}-\d{4}")
14
14
 
15
15
 
16
16
  async def do_register(settings: Settings, extension_id: str, tags: list[str] | None):
17
17
  async with ZitiManagementAPI(settings) as api:
18
- await register_extension(settings, api, extension_id, tags=parse_tags(tags))
18
+ await register_service(settings, api, extension_id, tags=parse_tags(tags))
19
19
 
20
20
 
21
21
  def validate_extension_id(extension_id: str) -> str:
@@ -9,7 +9,7 @@ import typer
9
9
  from mrok.cli.commands.admin.utils import parse_tags
10
10
  from mrok.conf import Settings
11
11
  from mrok.ziti.api import ZitiClientAPI, ZitiManagementAPI
12
- from mrok.ziti.identities import register_instance
12
+ from mrok.ziti.identities import register_identity
13
13
 
14
14
  RE_EXTENSION_ID = re.compile(r"(?i)EXT-\d{4}-\d{4}")
15
15
 
@@ -18,8 +18,8 @@ async def do_register(
18
18
  settings: Settings, extension_id: str, instance_id: str, tags: list[str] | None
19
19
  ):
20
20
  async with ZitiManagementAPI(settings) as mgmt_api, ZitiClientAPI(settings) as client_api:
21
- return await register_instance(
22
- mgmt_api, client_api, extension_id, instance_id, tags=parse_tags(tags)
21
+ return await register_identity(
22
+ settings, mgmt_api, client_api, extension_id, instance_id, tags=parse_tags(tags)
23
23
  )
24
24
 
25
25
 
@@ -5,14 +5,14 @@ import typer
5
5
 
6
6
  from mrok.conf import Settings
7
7
  from mrok.ziti.api import ZitiManagementAPI
8
- from mrok.ziti.services import unregister_extension
8
+ from mrok.ziti.services import unregister_service
9
9
 
10
10
  RE_EXTENSION_ID = re.compile(r"(?i)EXT-\d{4}-\d{4}")
11
11
 
12
12
 
13
13
  async def do_unregister(settings: Settings, extension_id: str):
14
14
  async with ZitiManagementAPI(settings) as api:
15
- await unregister_extension(settings, api, extension_id)
15
+ await unregister_service(settings, api, extension_id)
16
16
 
17
17
 
18
18
  def validate_extension_id(extension_id: str):
@@ -5,14 +5,14 @@ import typer
5
5
 
6
6
  from mrok.conf import Settings
7
7
  from mrok.ziti.api import ZitiManagementAPI
8
- from mrok.ziti.identities import unregister_instance
8
+ from mrok.ziti.identities import unregister_identity
9
9
 
10
10
  RE_EXTENSION_ID = re.compile(r"(?i)EXT-\d{4}-\d{4}")
11
11
 
12
12
 
13
13
  async def do_unregister(settings: Settings, extension_id: str, instance_id: str):
14
14
  async with ZitiManagementAPI(settings) as api:
15
- await unregister_instance(api, extension_id, instance_id)
15
+ await unregister_identity(settings, api, extension_id, instance_id)
16
16
 
17
17
 
18
18
  def validate_extension_id(extension_id: str):
@@ -1,6 +1,8 @@
1
1
  import typer
2
2
 
3
+ from mrok.cli.commands.agent.dev import app as dev_app
3
4
  from mrok.cli.commands.agent.run import app as run_app
4
5
 
5
6
  app = typer.Typer(help="mrok agent commands.")
6
7
  app.add_typer(run_app)
8
+ app.add_typer(dev_app)
@@ -0,0 +1,7 @@
1
+ import typer
2
+
3
+ from mrok.cli.commands.agent.dev import console, web
4
+
5
+ app = typer.Typer(name="dev", help="Dev tools for mrok agent.")
6
+ console.register(app)
7
+ web.register(app)
@@ -0,0 +1,25 @@
1
+ from typing import Annotated
2
+
3
+ import typer
4
+
5
+ from mrok.agent.devtools.inspector.app import InspectorApp
6
+
7
+
8
+ def register(app: typer.Typer) -> None:
9
+ @app.command("console")
10
+ def run_dev_console(
11
+ subscriber_port: Annotated[
12
+ int,
13
+ typer.Option(
14
+ "--subscriber-port",
15
+ "-s",
16
+ help=(
17
+ "TCP port where the mrok inspector console application "
18
+ "should connect to subscribe to request/response messages."
19
+ ),
20
+ show_default=True,
21
+ ),
22
+ ] = 50001,
23
+ ):
24
+ app = InspectorApp(subscriber_port)
25
+ app.run()
@@ -0,0 +1,37 @@
1
+ from typing import Annotated
2
+
3
+ import typer
4
+
5
+ from mrok.agent.devtools.inspector.server import InspectorServer
6
+
7
+
8
+ def register(app: typer.Typer) -> None:
9
+ @app.command("web")
10
+ def run_web_console(
11
+ port: Annotated[
12
+ int,
13
+ typer.Option(
14
+ "--port",
15
+ "-p",
16
+ help="TCP port where the mrok inspector web application will listen for requests.",
17
+ show_default=True,
18
+ ),
19
+ ] = 7777,
20
+ subscriber_port: Annotated[
21
+ int,
22
+ typer.Option(
23
+ "--subscriber-port",
24
+ "-s",
25
+ help=(
26
+ "TCP port where the mrok inspector web application "
27
+ "should connect to subscribe to request/response messages."
28
+ ),
29
+ show_default=True,
30
+ ),
31
+ ] = 50001,
32
+ ):
33
+ server = InspectorServer(
34
+ port=port,
35
+ subscriber_port=subscriber_port,
36
+ )
37
+ server.serve()
@@ -1,16 +1,10 @@
1
- import multiprocessing
2
1
  from pathlib import Path
3
2
  from typing import Annotated
4
3
 
5
4
  import typer
6
5
 
7
- # from app.logging import get_logging_config
8
6
  from mrok.agent import ziticorn
9
-
10
-
11
- def number_of_workers():
12
- return (multiprocessing.cpu_count() * 2) + 1
13
-
7
+ from mrok.cli.utils import number_of_workers
14
8
 
15
9
  default_workers = number_of_workers()
16
10
 
@@ -18,14 +12,8 @@ default_workers = number_of_workers()
18
12
  def register(app: typer.Typer) -> None:
19
13
  @app.command("asgi")
20
14
  def run_asgi(
21
- app: str = typer.Argument(
22
- ...,
23
- help="ASGI application",
24
- ),
25
- identity_file: Path = typer.Argument(
26
- ...,
27
- help="Identity json file",
28
- ),
15
+ app: Annotated[str, typer.Argument(..., help="ASGI application")],
16
+ identity_file: Annotated[Path, typer.Argument(..., help="Identity json file")],
29
17
  workers: Annotated[
30
18
  int,
31
19
  typer.Option(
@@ -44,6 +32,37 @@ def register(app: typer.Typer) -> None:
44
32
  show_default=True,
45
33
  ),
46
34
  ] = False,
35
+ publishers_port: Annotated[
36
+ int,
37
+ typer.Option(
38
+ "--publishers-port",
39
+ "-p",
40
+ help=(
41
+ "TCP port where the mrok agent "
42
+ "should connect to publish to request/response messages."
43
+ ),
44
+ show_default=True,
45
+ ),
46
+ ] = 50000,
47
+ subscribers_port: Annotated[
48
+ int,
49
+ typer.Option(
50
+ "--subscribers-port",
51
+ "-s",
52
+ help=(
53
+ "TCP port where the mrok agent should listen for incoming subscribers "
54
+ "connections for request/response messages."
55
+ ),
56
+ show_default=True,
57
+ ),
58
+ ] = 50001,
47
59
  ):
48
60
  """Run an ASGI application exposing it through OpenZiti network."""
49
- ziticorn.run(app, str(identity_file), workers=workers, reload=reload)
61
+ ziticorn.run(
62
+ app,
63
+ str(identity_file),
64
+ workers=workers,
65
+ reload=reload,
66
+ publishers_port=publishers_port,
67
+ subscribers_port=subscribers_port,
68
+ )
@@ -1,15 +1,10 @@
1
- import multiprocessing
2
1
  from pathlib import Path
3
2
  from typing import Annotated
4
3
 
5
4
  import typer
6
5
 
7
6
  from mrok.agent import sidecar
8
-
9
-
10
- def number_of_workers():
11
- return (multiprocessing.cpu_count() * 2) + 1
12
-
7
+ from mrok.cli.utils import number_of_workers
13
8
 
14
9
  default_workers = number_of_workers()
15
10
 
@@ -34,15 +29,30 @@ def register(app: typer.Typer) -> None:
34
29
  show_default=True,
35
30
  ),
36
31
  ] = default_workers,
37
- reload: Annotated[
38
- bool,
32
+ publishers_port: Annotated[
33
+ int,
34
+ typer.Option(
35
+ "--publishers-port",
36
+ "-p",
37
+ help=(
38
+ "TCP port where the mrok agent "
39
+ "should connect to publish to request/response messages."
40
+ ),
41
+ show_default=True,
42
+ ),
43
+ ] = 50000,
44
+ subscribers_port: Annotated[
45
+ int,
39
46
  typer.Option(
40
- "--reload",
41
- "-r",
42
- help="Enable auto-reload. Default: False",
47
+ "--subscribers-port",
48
+ "-s",
49
+ help=(
50
+ "TCP port where the mrok agent should listen for incoming subscribers "
51
+ "connections for request/response messages."
52
+ ),
43
53
  show_default=True,
44
54
  ),
45
- ] = False,
55
+ ] = 50001,
46
56
  ):
47
57
  """Run a Sidecar Proxy to expose a web application through OpenZiti."""
48
58
  if ":" in str(target):
@@ -51,4 +61,10 @@ def register(app: typer.Typer) -> None:
51
61
  else:
52
62
  target_addr = str(target) # type: ignore
53
63
 
54
- sidecar.run(str(identity_file), target_addr, workers=workers, reload=reload)
64
+ sidecar.run(
65
+ str(identity_file),
66
+ target_addr,
67
+ workers=workers,
68
+ publishers_port=publishers_port,
69
+ subscribers_port=subscribers_port,
70
+ )
@@ -0,0 +1,5 @@
1
+ import multiprocessing
2
+
3
+
4
+ def number_of_workers() -> int:
5
+ return (multiprocessing.cpu_count() * 2) + 1
@@ -1,18 +1,14 @@
1
- import multiprocessing
2
1
  from collections.abc import Callable
3
2
  from typing import Annotated, Any
4
3
 
5
4
  import typer
6
5
  from gunicorn.app.base import BaseApplication
7
6
 
7
+ from mrok.cli.utils import number_of_workers
8
8
  from mrok.controller.app import app as asgi_app
9
9
  from mrok.logging import get_logging_config
10
10
 
11
11
 
12
- def number_of_workers():
13
- return (multiprocessing.cpu_count() * 2) + 1
14
-
15
-
16
12
  class StandaloneApplication(BaseApplication): # pragma: no cover
17
13
  def __init__(self, application: Callable, options: dict[str, Any] | None = None):
18
14
  self.options = options or {}
@@ -0,0 +1,6 @@
1
+ import typer
2
+
3
+ from mrok.cli.commands.proxy import run
4
+
5
+ app = typer.Typer(help="mrok proxy commands.")
6
+ run.register(app)
@@ -0,0 +1,49 @@
1
+ from pathlib import Path
2
+ from typing import Annotated
3
+
4
+ import typer
5
+
6
+ from mrok import proxy
7
+ from mrok.cli.utils import number_of_workers
8
+
9
+ default_workers = number_of_workers()
10
+
11
+
12
+ def register(app: typer.Typer) -> None:
13
+ @app.command("run")
14
+ def run_proxy(
15
+ ctx: typer.Context,
16
+ identity_file: Path = typer.Argument(
17
+ ...,
18
+ help="Identity json file",
19
+ ),
20
+ host: Annotated[
21
+ str,
22
+ typer.Option(
23
+ "--host",
24
+ "-h",
25
+ help="Host to bind to. Default: 127.0.0.1",
26
+ show_default=True,
27
+ ),
28
+ ] = "127.0.0.1",
29
+ port: Annotated[
30
+ int,
31
+ typer.Option(
32
+ "--port",
33
+ "-P",
34
+ help="Port to bind to. Default: 8000",
35
+ show_default=True,
36
+ ),
37
+ ] = 8000,
38
+ workers: Annotated[
39
+ int,
40
+ typer.Option(
41
+ "--workers",
42
+ "-w",
43
+ help=f"Number of workers. Default: {default_workers}",
44
+ show_default=True,
45
+ ),
46
+ ] = default_workers,
47
+ ):
48
+ """Run the mrok proxy with Gunicorn and Uvicorn workers."""
49
+ proxy.run(identity_file, host, port, workers)
mrok/cli/utils.py ADDED
@@ -0,0 +1,5 @@
1
+ import multiprocessing
2
+
3
+
4
+ def number_of_workers() -> int:
5
+ return (multiprocessing.cpu_count() * 2) + 1
mrok/conf.py CHANGED
@@ -15,6 +15,12 @@ DEFAULT_SETTINGS = {
15
15
  "ssl_verify": False,
16
16
  },
17
17
  "PAGINATION": {"limit": 50},
18
+ "SIDECAR": {
19
+ "textual_port": 4040,
20
+ "store_port": 5051,
21
+ "store_size": 1000,
22
+ "textual_command": "python mrok/agent/sidecar/inspector.py",
23
+ },
18
24
  }
19
25
 
20
26
  _settings = None
mrok/controller/auth.py CHANGED
@@ -80,8 +80,8 @@ async def authenticate(
80
80
  )
81
81
  return payload
82
82
  except jwt.InvalidKeyError as e:
83
- logger.error(f"Invalid jwt token: {e}")
83
+ logger.error(f"Invalid jwt token: {e} ({credentials.credentials})")
84
84
  raise UNAUTHORIZED_EXCEPTION
85
85
  except jwt.InvalidTokenError as e:
86
- logger.error(f"Invalid jwt token: {e}")
86
+ logger.error(f"Invalid jwt token: {e} ({credentials.credentials})")
87
87
  raise UNAUTHORIZED_EXCEPTION