From 03dd163266ce4c8496ce08f1c3d40e44a92f2efb Mon Sep 17 00:00:00 2001 From: msm Date: Thu, 24 Jul 2025 13:52:00 +0000 Subject: [PATCH 1/4] Update karton list command --- .github/workflows/test.yml | 3 ++- README.md | 20 ++++++++++++++++++++ karton/core/main.py | 28 ++++++++++++++++++++++------ 3 files changed, 44 insertions(+), 7 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5b71ba8a..29bbb9fe 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,11 +13,12 @@ jobs: - uses: CERT-Polska/lint-python-action@v2 with: source: karton/ + python-version: 3.12 unittest: runs-on: ubuntu-latest strategy: matrix: - minor: [9, 10, 11, 12] + minor: [10, 11, 12, 13] steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 diff --git a/README.md b/README.md index 7a496ee9..608ef676 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,26 @@ if __name__ == "__main__": GenericUnpacker.main() ``` +## Command line + +This package also provies a command-line utility called "karton". You can use it for simple management tasks (but it's not designed as a fully capable management tool). + +``` +$ karton configure # create a new configuration file + +$ karton list -s # list current binds +karton name version karton +------------------------------------------------------------------------ +karton.yaramatcher 1.2.0 5.3.0 +karton.autoit-ripper 1.2.1 5.3.3 +karton.mwdb-reporter 1.3.0 5.3.2 + +$ karton logs # start streaming all system logs + +$ karton delete karton.something # remove unused bind (will be GCed by system during the next operation) +``` + + ## Karton systems Some Karton systems are universal and useful to everyone. We decided to share them with the community. diff --git a/karton/core/main.py b/karton/core/main.py index bfa69519..3424aa0b 100644 --- a/karton/core/main.py +++ b/karton/core/main.py @@ -144,10 +144,20 @@ def configuration_wizard(config_filename: str) -> None: log.info("Saved the new configuration file in %s", os.path.abspath(config_filename)) -def print_bind_list(config: Config) -> None: +def print_bind_list(config: Config, short: bool) -> None: backend = KartonBackend(config=config) - for bind in backend.get_binds(): - print(bind) + + if short: + # Print a human-readable table-like version + print(f"{'karton name':50} {'version':10} {'karton':10}") + print("-" * 72) + for bind in backend.get_binds(): + print( + f"{bind.identity:50} {bind.service_version or "-":10} {bind.version:10}" + ) + else: + for bind in backend.get_binds(): + print(bind) def delete_bind(config: Config, karton_name: str) -> None: @@ -180,7 +190,7 @@ def process(self, task): def main() -> None: - parser = argparse.ArgumentParser(description="Your red pill to the karton-verse") + parser = argparse.ArgumentParser(description="Karton-core management utility") parser.add_argument("--version", action="version", version=__version__) parser.add_argument("-c", "--config-file", help="Alternative configuration path") parser.add_argument( @@ -189,7 +199,13 @@ def main() -> None: subparsers = parser.add_subparsers(dest="command", help="sub-command help") - subparsers.add_parser("list", help="List active karton binds") + list_parser = subparsers.add_parser("list", help="List active karton binds") + list_parser.add_argument( + "-s", + "--short", + help='Print names and versions only (human readable)"', + action="store_true", + ) logs_parser = subparsers.add_parser("logs", help="Start streaming logs") logs_parser.add_argument( @@ -253,7 +269,7 @@ def main() -> None: return if args.command == "list": - print_bind_list(config) + print_bind_list(config, args.short) elif args.command == "delete": karton_name = args.identity print( From 3edb09a3907244e0536f864049641bf2ca603226 Mon Sep 17 00:00:00 2001 From: msm Date: Fri, 25 Jul 2025 13:14:13 +0000 Subject: [PATCH 2/4] Rename the command-line parameter --- karton/core/main.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/karton/core/main.py b/karton/core/main.py index 3424aa0b..43341cba 100644 --- a/karton/core/main.py +++ b/karton/core/main.py @@ -201,9 +201,9 @@ def main() -> None: list_parser = subparsers.add_parser("list", help="List active karton binds") list_parser.add_argument( - "-s", - "--short", - help='Print names and versions only (human readable)"', + "-h", + "--human", + help='Short, human readable output, with names and versions only."', action="store_true", ) From f62cb66ca7ab2dea8923471e1d48666010770764 Mon Sep 17 00:00:00 2001 From: msm Date: Mon, 28 Jul 2025 13:35:51 +0000 Subject: [PATCH 3/4] Update the output format --- karton/core/main.py | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/karton/core/main.py b/karton/core/main.py index 43341cba..9a543281 100644 --- a/karton/core/main.py +++ b/karton/core/main.py @@ -23,6 +23,7 @@ def process_log(self, event: Dict[str, Any]) -> Any: level = event.get("levelname") name = event.get("name") msg = event.get("message") + print(event) print(f"[{level}] {name}: {msg}") @@ -144,10 +145,10 @@ def configuration_wizard(config_filename: str) -> None: log.info("Saved the new configuration file in %s", os.path.abspath(config_filename)) -def print_bind_list(config: Config, short: bool) -> None: +def print_bind_list(config: Config, output_format: str) -> None: backend = KartonBackend(config=config) - if short: + if output_format == "table": # Print a human-readable table-like version print(f"{'karton name':50} {'version':10} {'karton':10}") print("-" * 72) @@ -155,9 +156,12 @@ def print_bind_list(config: Config, short: bool) -> None: print( f"{bind.identity:50} {bind.service_version or "-":10} {bind.version:10}" ) - else: + elif output_format == "json": + # Use JSONL, each line is a JSON representing next bind for bind in backend.get_binds(): - print(bind) + print(backend.serialize_bind(bind)) + else: + raise RuntimeError(f"Invalid output format: {output_format}") def delete_bind(config: Config, karton_name: str) -> None: @@ -201,10 +205,11 @@ def main() -> None: list_parser = subparsers.add_parser("list", help="List active karton binds") list_parser.add_argument( - "-h", - "--human", - help='Short, human readable output, with names and versions only."', - action="store_true", + "-o", + "--output", + help="Short, human readable output, with names and versions only.", + default="table", + choices=("table", "json"), ) logs_parser = subparsers.add_parser("logs", help="Start streaming logs") @@ -269,7 +274,7 @@ def main() -> None: return if args.command == "list": - print_bind_list(config, args.short) + print_bind_list(config, args.output) elif args.command == "delete": karton_name = args.identity print( From 93f53bf8c2928f52f068801964a9607fa5c6f11a Mon Sep 17 00:00:00 2001 From: msm Date: Mon, 28 Jul 2025 13:42:16 +0000 Subject: [PATCH 4/4] Well this one was unnecessasry --- karton/core/main.py | 1 - 1 file changed, 1 deletion(-) diff --git a/karton/core/main.py b/karton/core/main.py index 9a543281..cbf68a14 100644 --- a/karton/core/main.py +++ b/karton/core/main.py @@ -23,7 +23,6 @@ def process_log(self, event: Dict[str, Any]) -> Any: level = event.get("levelname") name = event.get("name") msg = event.get("message") - print(event) print(f"[{level}] {name}: {msg}")