From 5d567e4b152ec8f111d7608f1c9455e3ca6276f3 Mon Sep 17 00:00:00 2001 From: jessebot Date: Tue, 18 Jun 2024 01:28:23 +0200 Subject: [PATCH 01/14] first attempt at supporting trustedKeyServers for matrix --- pyproject.toml | 2 +- smol_k8s_lab/config/default_config.yaml | 6 ++++++ smol_k8s_lab/k8s_apps/social/matrix.py | 23 ++++++++++++++++++++++- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 0d81a7063..9e47fa687 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "smol_k8s_lab" -version = "5.6.2" +version = "5.7.0" description = "CLI and TUI to quickly install slimmer Kubernetes distros and then manage apps declaratively using Argo CD" authors = ["Jesse Hitch ", "Max Roby "] diff --git a/smol_k8s_lab/config/default_config.yaml b/smol_k8s_lab/config/default_config.yaml index 05f1ac345..9dde4ebc0 100644 --- a/smol_k8s_lab/config/default_config.yaml +++ b/smol_k8s_lab/config/default_config.yaml @@ -924,6 +924,12 @@ apps: smtp_password: value_from: env: MATRIX_SMTP_PASSWORD + # expects a list like this: + # + # - server_name: "matrix.dog.friend" + # verify_keys: + # "ed25519:a_abcd": "somekeyherethatisnotactuallythis" + trusted_key_servers: [] backups: # cronjob syntax schedule to run matrix pvc backups pvc_schedule: 10 0 * * * diff --git a/smol_k8s_lab/k8s_apps/social/matrix.py b/smol_k8s_lab/k8s_apps/social/matrix.py index 060682be6..d10b10078 100644 --- a/smol_k8s_lab/k8s_apps/social/matrix.py +++ b/smol_k8s_lab/k8s_apps/social/matrix.py @@ -65,8 +65,12 @@ def configure_matrix(argocd: ArgoCD, # initial secrets to deploy this app from scratch if init_enabled and not app_installed: + argocd.k8s.create_namespace(matrix_namespace) + init_values = init.get('values', {}) + # if there's trusted key servers, create a secret for them + trust_key_servers = init_values.get("trust_key_servers", []) backup_vals = process_backup_vals(cfg['backups'], 'matrix', argocd) @@ -136,10 +140,16 @@ def configure_matrix(argocd: ArgoCD, mas_client_secret, mas_admin_token, syncv3_secret, + trust_key_servers, bitwarden) # else create these as Kubernetes secrets elif not bitwarden and not restore_enabled: + argocd.k8s.create_secret("trusted-key-servers", + matrix_namespace, + trust_key_servers, + "trustedKeyServers") + # postgresql credentials argocd.k8s.create_secret( 'matrix-pgsql-credentials', @@ -337,12 +347,21 @@ def setup_bitwarden_items(argocd: ArgoCD, mas_client_secret: str, mas_admin_token: str, syncv3_secret: str, + trusted_key_servers: str|list|dict, bitwarden: BwCLI): """ setup all the required secrets as items in bitwarden """ sub_header("Creating matrix secrets in Bitwarden") + if trusted_key_servers: + trusted_key_servers_id = bitwarden.create_login( + name='matrix-trusted-key-servers', + item_url=matrix_hostname, + user="nousername", + password=trusted_key_servers + ) + # S3 credentials if "http" not in s3_endpoint: s3_endpoint = "https://" + s3_endpoint @@ -512,7 +531,9 @@ def setup_bitwarden_items(argocd: ArgoCD, 'matrix_oidc_credentials_bitwarden_id': oidc_id, 'matrix_authentication_service_bitwarden_id': mas_id, 'matrix_idp_name': idp_name, - 'matrix_idp_id': idp_id}) + 'matrix_idp_id': idp_id, + 'matrix_trusted_key_servers_bitwarden_id': trusted_key_servers_id} + ) # reload the bitwarden ESO provider try: From a2bb33091cf7885fec0469f64f81dd17ddbe6cf1 Mon Sep 17 00:00:00 2001 From: jessebot Date: Wed, 19 Jun 2024 08:43:40 +0200 Subject: [PATCH 02/14] initial TUI and docs work to allow trusted key servers --- docs/k8s_apps/matrix.md | 33 +++- .../tui/app_widgets/app_inputs_confg.py | 144 +++++++++++++++++- smol_k8s_lab/tui/app_widgets/input_widgets.py | 4 +- smol_k8s_lab/tui/css/apps_config.tcss | 11 +- smol_k8s_lab/tui/css/apps_init_config.tcss | 36 +++++ smol_k8s_lab/tui/css/base.tcss | 15 ++ smol_k8s_lab/tui/util.py | 36 ++++- 7 files changed, 259 insertions(+), 20 deletions(-) diff --git a/docs/k8s_apps/matrix.md b/docs/k8s_apps/matrix.md index e13127c0b..b1917fe87 100644 --- a/docs/k8s_apps/matrix.md +++ b/docs/k8s_apps/matrix.md @@ -26,7 +26,7 @@ !!! Note - We recently added support for [sliding sync](https://github.com/) and [matrix authentication service](https://github.com/). + We recently added support for [sliding sync](https://github.com/) and [matrix authentication service](https://github.com/). To use these, please use `matrix/app_of_apps_beta/` for `apps.matrix.argo.path`. ## Required Values @@ -38,17 +38,29 @@ The main variables you need to worry about when setting up matrix are your `host - element_hostname - federation_hostname +**If using Matrix authentication Service and Sliding Sync**: + +- auth_hostname +- sliding_sync_hostname + These are all storage related and you can leave them at the defaults for small servers: +**Signing key storage**: - signing_key_pvc_enabled - signing_key_storage - signing_key_access_mode + +**Media storage**: - media_pvc_enabled - media_storage - media_access_mode + +**Synapse config storage**: - synapse_config_pvc_enabled - synapse_config_storage - synapse_config_access_mode + +**S3 storage**: - s3_provider - s3_bucket - s3_endpoint @@ -63,9 +75,26 @@ These are all one time values that you need to provide, related entirely to mail - smtp_user - smtp_host - See below for providing smtp_password without putting it in plain text. +If you want to federate, you also need to provide: +- [trusted_key_servers](https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html?highlight=trusted#trusted_key_servers) + +You can provide a list of maps like this for trusted_key_servers: + +```yaml +apps: + matrix: + init: + values: + - server_name: matrix.friend.com + verify_keys: + ed25519:auto: abcdefghijklmnopqrstuvwxyzabcdefghijklmopqr +``` + +The trusted_key_servers option currently displays in the TUI, but is not editable via the TUI yet. + + #### Sensitive values Sensitive values can be provided via environment variables using a `value_from` map on any value under `init.values` or `backups`. Example of providing the SMTP password: diff --git a/smol_k8s_lab/tui/app_widgets/app_inputs_confg.py b/smol_k8s_lab/tui/app_widgets/app_inputs_confg.py index 4bf9a574c..574f961b1 100644 --- a/smol_k8s_lab/tui/app_widgets/app_inputs_confg.py +++ b/smol_k8s_lab/tui/app_widgets/app_inputs_confg.py @@ -3,7 +3,7 @@ ArgoCDProjectConfig) from smol_k8s_lab.tui.app_widgets.input_widgets import SmolK8sLabInputsWidget from smol_k8s_lab.tui.app_widgets.backup_and_restore import BackupWidget, RestoreApp -from smol_k8s_lab.tui.util import placeholder_grammar, create_sanitized_list +from smol_k8s_lab.tui.util import placeholder_grammar, create_sanitized_list, input_field # external libraries from ruamel.yaml import CommentedSeq @@ -129,7 +129,9 @@ class InitValues(Static): def __init__(self, app_name: str, init_dict: dict) -> None: self.app_name = app_name self.init_enabled = init_dict['enabled'] - self.init_values = init_dict.get('values', None) + self.init_values = init_dict.get('values', {}) + if app_name == "matrix": + self.trusted_keys_srvr = self.init_values.get('trusted_key_servers', []) super().__init__() @@ -162,11 +164,12 @@ def compose(self) -> ComposeResult: if self.init_values: # these are special values that are only set up via # smol-k8s-lab and do not live in a secret on the k8s cluster - init_vals = SmolK8sLabInputsWidget( + init_vals = SmolK8sLabInputsWidget( app_name=self.app_name, title="Init Values", id=f"{cid}-init-values-collapsible", - inputs=self.init_values) + inputs=self.init_values + ) init_vals.tooltip = ( "Init values for special one-time setup of " @@ -175,6 +178,17 @@ def compose(self) -> ComposeResult: ) yield init_vals + def on_mount(self): + """ + add trusted servers if they exist + """ + # matrix is special as we take special keys + if self.app_name == "matrix": + if self.trusted_keys_srvr and isinstance(self.trusted_keys_srvr, list): + self.get_widget_by_id(f"{self.app_name}-init-inputs").mount( + TrustedKeyServersWidget(self.app_name, self.trusted_keys_srvr) + ) + @on(Switch.Changed) def show_or_hide_init_inputs(self, event: Switch.Changed) -> None: """ @@ -192,6 +206,128 @@ def show_or_hide_init_inputs(self, event: Switch.Changed) -> None: self.app.write_yaml() +class TrustedKeyServersWidget(Static): + """ + widget to take special smol-k8s-lab + """ + CSS_PATH = "../css/apps_init_config.tcss" + + def __init__(self, app_name: str, trusted_key_servers: dict) -> None: + self.app_name = app_name + self.trusted_keys_srvr = trusted_key_servers + + super().__init__() + + def compose(self) -> ComposeResult: + yield Container( + id=f"{self.app_name}-trusted-key-widget-grid", + classes=f"{self.app_name}" + ) + + def on_mount(self): + container = self.get_widget_by_id(f"{self.app_name}-trusted-key-widget-grid") + self.generate_trusted_key_server_rows(container) + + + def generate_trusted_key_server_rows(self, container: Container): + """ + generate trusted key servers rows + """ + container.mount(Label("Trusted Key Servers [dim](Optional)[/dim]", + classes="trusted-key-servers-label")) + + for key_server in self.trusted_keys_srvr: + server_name = key_server['server_name'] + hyphen_srvr_name = server_name.replace(".", "-") + server_input = input_field( + "server name", + server_name, + "server_name", + "Trusted key server hostname", + "Trusted key server for federating with synapse (your matrix server)", + stacked=True + ) + + # we mount this all at once later down + verify_rows = [] + + # for security, you can have a key for each + verify_keys = key_server.get("verify_keys", {}) + if verify_keys: + for key, value in verify_keys.items(): + hyphen_key = key.replace(":","-") + key_field = input_field( + key, + value, + key, + "Verify key value", + "Verify key value", + sensitive=True, + stacked=True + ) + + button = Button("๐Ÿšฎ", + id=f"{hyphen_key}-trash-button", + classes="verify-key-row-delete-button") + verify_key_row = Grid(key_field, + button, + classes="verify-key-row", + id=f"{hyphen_key}-row") + verify_rows.append(verify_key_row) + + # verify grid should be to the right to of the trusted key server name + verify_keys_grid = Grid( + *verify_rows, + id=f"{hyphen_srvr_name}-verify-keys-container" + ) + else: + # verify grid should be to the right to of the trusted key server name + verify_keys_grid = Grid( + Button("โž• verify key", + id=f"{hyphen_srvr_name}-add-verify-key", + classes="add-new-verify-key-button"), + id=f"{hyphen_srvr_name}-verify-keys-container" + ) + + # mount the key server row into the main init container + container.mount( + Grid(server_input, + verify_keys_grid, + id=f"{hyphen_srvr_name}-key-server-row", + classes="trusted-key-servers") + ) + + @on(Button.Pressed) + def on_button_pressed(self, event: Button.Pressed): + """ + handle button presses + """ + if "trash-button" in event.button.id: + button_row = event.button.parent + key_row = button_row.parent + server_row = key_row.parent + hyphen_srvr_name = server_row.id.replace("-verify-keys-container","") + + # remove the key row + button_row.remove() + # add a new button + key_row.mount(Button("โž• verify key", + id=f"{hyphen_srvr_name}-add-verify-key", + classes="add-new-verify-key-button")) + self.notify( + "\nThis button doesn't actually work yet, but will soon. " + "Right now, it just does UI magic. In the " + "meantime, edit your yaml config directly under the " + "apps.matrix.init.values section :)", + title="๐Ÿ˜ผ Nope. (but soon)") + elif "-add-verify-key" in event.button.id: + self.notify( + "\nThis button doesn't work yet, but will soon. In the " + "meantime, edit your yaml config directly under the " + "apps.matrix.init.values section :)", + title="๐Ÿ˜ผ Nope. (but soon)") + + class AppsetSecretValues(Static): """ widget to take secret key values to pass to argocd appset secret plugin helm diff --git a/smol_k8s_lab/tui/app_widgets/input_widgets.py b/smol_k8s_lab/tui/app_widgets/input_widgets.py index 54b4aeb59..962e15d41 100644 --- a/smol_k8s_lab/tui/app_widgets/input_widgets.py +++ b/smol_k8s_lab/tui/app_widgets/input_widgets.py @@ -226,7 +226,9 @@ def on_mount(self) -> None: if self.inputs: for key, value in self.inputs.items(): - grid.mount(self.generate_row(key, value)) + # ignore this particular key + if key != "trusted_key_servers": + grid.mount(self.generate_row(key, value)) if self.add_fields_button: grid.mount(Button("โž• new field")) diff --git a/smol_k8s_lab/tui/css/apps_config.tcss b/smol_k8s_lab/tui/css/apps_config.tcss index 084ef015c..84cb9e212 100644 --- a/smol_k8s_lab/tui/css/apps_config.tcss +++ b/smol_k8s_lab/tui/css/apps_config.tcss @@ -18,11 +18,11 @@ $navy: rgb(35,35,54); #apps-config-container { layout: grid; grid-size: 2; - grid-columns: 0.5fr 1fr; - grid-rows: 1.55fr 0.35fr; + grid-columns: 0.5fr 1.1fr; + grid-rows: 1.5fr 0.4fr; grid-gutter: 1; - width: 90%; - height: 92%; + width: 94%; + height: 93%; align: center middle; scrollbar-background: $dark_gray; scrollbar-background-active: $dark_gray; @@ -58,7 +58,7 @@ $navy: rgb(35,35,54); /* matches the app selection list and the left button container */ #left-apps-container { - grid-rows: 1fr 0.2fr; + grid-rows: 1fr 0.25fr; align: center top; grid-gutter: 1; } @@ -86,7 +86,6 @@ $navy: rgb(35,35,54); border-subtitle-color: $sky_blue; border: round $cornflower; background: $navy 60%; - margin-right: 1; link-background-hover: $navy; link-color-hover: $orange; scrollbar-background: $dark_gray; diff --git a/smol_k8s_lab/tui/css/apps_init_config.tcss b/smol_k8s_lab/tui/css/apps_init_config.tcss index d77beb3c5..e81887083 100644 --- a/smol_k8s_lab/tui/css/apps_init_config.tcss +++ b/smol_k8s_lab/tui/css/apps_init_config.tcss @@ -55,3 +55,39 @@ SmolK8sLabCollapsibleInputsWidget { height: auto; padding-top: 1; } + +/* trusted key servers label */ +.trusted-key-servers-label { + height: 3; + width: 100%; + content-align: left middle; + padding-left: 1; + color: $light_cornflower; + background: $blue_gray 20%; +} + + +/* all trusted key server rows */ +.trusted-key-servers { + padding: 1; + height: 8; + grid-size: 2; +} + +/* the right side of */ +.verify-key-row { + grid-size: 2; + grid-columns: 1fr 0.25fr; + grid-rows: 0.25fr 1fr; +} + +.add-new-verify-key-button { + margin-top: 3; + margin-left: 5; + width: 6; +} + +.verify-key-row-delete-button { + margin-top: 3; + width: 5; +} diff --git a/smol_k8s_lab/tui/css/base.tcss b/smol_k8s_lab/tui/css/base.tcss index ae2498f20..ea2a8283a 100644 --- a/smol_k8s_lab/tui/css/base.tcss +++ b/smol_k8s_lab/tui/css/base.tcss @@ -315,6 +315,13 @@ DataTable { content-align: left middle; } +/* Input stacked with in label on top of input row */ +.input-stacked-row { + grid-size: 1; + align: center middle; + content-align: center middle; +} + /* Input in "label: input" row */ .input-row-input { align: left middle; @@ -328,3 +335,11 @@ DataTable { color: $bluish_white; } +.input-row-stacked-label { + align: center middle; + content-align: center middle; + padding-top: 1; + padding-bottom: 1; + padding-left: 1; + color: $bluish_white; +} diff --git a/smol_k8s_lab/tui/util.py b/smol_k8s_lab/tui/util.py index db0304cf6..e72a59fc2 100644 --- a/smol_k8s_lab/tui/util.py +++ b/smol_k8s_lab/tui/util.py @@ -276,17 +276,32 @@ def input_field(label: str, placeholder: str, tooltip: str = "", validate_empty: bool = False, - extra_row_class: str = "") -> Horizontal: + extra_row_class: str = "", + stacked: bool = False, + sensitive: bool = False) -> Horizontal: """ returns an input label and field within a Horizontal container """ - input_label = Label(label.replace("_", " ") + ":", classes="input-row-label") + # create a label for the input field + if stacked: + label_name = label + label_classes = "input-row-stacked-label" + else: + label_name = label.replace("_", " ") + ":" + label_classes = "input-row-label" + input_label = Label(label_name, classes=label_classes) input_label.tooltip = tooltip + # create input field + i_id = label.replace("_","-").replace(" ","-").replace(".","-").replace(":","-") input_dict = {"placeholder": placeholder, "classes": "input-row-input", - "id": label.replace("_","-").replace(" ", "-"), + "id": i_id, "name": name} + + if sensitive: + input_dict["password"] = True + if initial_value: input_dict["value"] = initial_value else: @@ -298,9 +313,16 @@ def input_field(label: str, input = Input(**input_dict) input.tooltip = tooltip - if extra_row_class: - classes = f"input-row {extra_row_class}" + # input row classes + if stacked: + input_row_classes = "input-stacked-row" else: - classes = "input-row" + input_row_classes = "input-row" + if extra_row_class: + input_row_classes += f" {extra_row_class}" - return Horizontal(input_label, input, classes=classes) + # return either a Horizontal container or a Grid container + if stacked: + return Grid(input_label, input, classes=input_row_classes) + else: + return Horizontal(input_label, input, classes=input_row_classes) From 8b1e3fe4a4de4c00b697ee03af92f9eafce2528d Mon Sep 17 00:00:00 2001 From: jessebot Date: Wed, 19 Jun 2024 11:34:08 +0200 Subject: [PATCH 03/14] move trusted key servers widget to it's own file --- .../tui/app_widgets/app_inputs_confg.py | 125 +-------------- .../tui/app_widgets/trusted_key_servers.py | 149 ++++++++++++++++++ 2 files changed, 151 insertions(+), 123 deletions(-) create mode 100644 smol_k8s_lab/tui/app_widgets/trusted_key_servers.py diff --git a/smol_k8s_lab/tui/app_widgets/app_inputs_confg.py b/smol_k8s_lab/tui/app_widgets/app_inputs_confg.py index 574f961b1..a1c465312 100644 --- a/smol_k8s_lab/tui/app_widgets/app_inputs_confg.py +++ b/smol_k8s_lab/tui/app_widgets/app_inputs_confg.py @@ -3,7 +3,8 @@ ArgoCDProjectConfig) from smol_k8s_lab.tui.app_widgets.input_widgets import SmolK8sLabInputsWidget from smol_k8s_lab.tui.app_widgets.backup_and_restore import BackupWidget, RestoreApp -from smol_k8s_lab.tui.util import placeholder_grammar, create_sanitized_list, input_field +from smol_k8s_lab.tui.app_widgets.trusted_key_servers import TrustedKeyServersWidget +from smol_k8s_lab.tui.util import placeholder_grammar, create_sanitized_list # external libraries from ruamel.yaml import CommentedSeq @@ -206,128 +207,6 @@ def show_or_hide_init_inputs(self, event: Switch.Changed) -> None: self.app.write_yaml() -class TrustedKeyServersWidget(Static): - """ - widget to take special smol-k8s-lab - """ - CSS_PATH = "../css/apps_init_config.tcss" - - def __init__(self, app_name: str, trusted_key_servers: dict) -> None: - self.app_name = app_name - self.trusted_keys_srvr = trusted_key_servers - - super().__init__() - - def compose(self) -> ComposeResult: - yield Container( - id=f"{self.app_name}-trusted-key-widget-grid", - classes=f"{self.app_name}" - ) - - def on_mount(self): - container = self.get_widget_by_id(f"{self.app_name}-trusted-key-widget-grid") - self.generate_trusted_key_server_rows(container) - - - def generate_trusted_key_server_rows(self, container: Container): - """ - generate trusted key servers rows - """ - container.mount(Label("Trusted Key Servers [dim](Optional)[/dim]", - classes="trusted-key-servers-label")) - - for key_server in self.trusted_keys_srvr: - server_name = key_server['server_name'] - hyphen_srvr_name = server_name.replace(".", "-") - server_input = input_field( - "server name", - server_name, - "server_name", - "Trusted key server hostname", - "Trusted key server for federating with synapse (your matrix server)", - stacked=True - ) - - # we mount this all at once later down - verify_rows = [] - - # for security, you can have a key for each - verify_keys = key_server.get("verify_keys", {}) - if verify_keys: - for key, value in verify_keys.items(): - hyphen_key = key.replace(":","-") - key_field = input_field( - key, - value, - key, - "Verify key value", - "Verify key value", - sensitive=True, - stacked=True - ) - - button = Button("๐Ÿšฎ", - id=f"{hyphen_key}-trash-button", - classes="verify-key-row-delete-button") - verify_key_row = Grid(key_field, - button, - classes="verify-key-row", - id=f"{hyphen_key}-row") - verify_rows.append(verify_key_row) - - # verify grid should be to the right to of the trusted key server name - verify_keys_grid = Grid( - *verify_rows, - id=f"{hyphen_srvr_name}-verify-keys-container" - ) - else: - # verify grid should be to the right to of the trusted key server name - verify_keys_grid = Grid( - Button("โž• verify key", - id=f"{hyphen_srvr_name}-add-verify-key", - classes="add-new-verify-key-button"), - id=f"{hyphen_srvr_name}-verify-keys-container" - ) - - # mount the key server row into the main init container - container.mount( - Grid(server_input, - verify_keys_grid, - id=f"{hyphen_srvr_name}-key-server-row", - classes="trusted-key-servers") - ) - - @on(Button.Pressed) - def on_button_pressed(self, event: Button.Pressed): - """ - handle button presses - """ - if "trash-button" in event.button.id: - button_row = event.button.parent - key_row = button_row.parent - server_row = key_row.parent - hyphen_srvr_name = server_row.id.replace("-verify-keys-container","") - - # remove the key row - button_row.remove() - # add a new button - key_row.mount(Button("โž• verify key", - id=f"{hyphen_srvr_name}-add-verify-key", - classes="add-new-verify-key-button")) - self.notify( - "\nThis button doesn't actually work yet, but will soon. " - "Right now, it just does UI magic. In the " - "meantime, edit your yaml config directly under the " - "apps.matrix.init.values section :)", - title="๐Ÿ˜ผ Nope. (but soon)") - elif "-add-verify-key" in event.button.id: - self.notify( - "\nThis button doesn't work yet, but will soon. In the " - "meantime, edit your yaml config directly under the " - "apps.matrix.init.values section :)", - title="๐Ÿ˜ผ Nope. (but soon)") - - class AppsetSecretValues(Static): """ widget to take secret key values to pass to argocd appset secret plugin helm diff --git a/smol_k8s_lab/tui/app_widgets/trusted_key_servers.py b/smol_k8s_lab/tui/app_widgets/trusted_key_servers.py new file mode 100644 index 000000000..2deaeb4e1 --- /dev/null +++ b/smol_k8s_lab/tui/app_widgets/trusted_key_servers.py @@ -0,0 +1,149 @@ +# smol-k8s-lab libraries +from smol_k8s_lab.tui.util import input_field + +# external libraries +from textual import on +from textual.app import ComposeResult +from textual.binding import Binding +from textual.containers import Container, Grid +from textual.screen import ModalScreen +from textual.widgets import Label, Button, Static + +class TrustedKeyServersWidget(Static): + """ + widget to take special smol-k8s-lab + """ + CSS_PATH = "../css/apps_init_config.tcss" + + def __init__(self, app_name: str, trusted_key_servers: dict) -> None: + self.app_name = app_name + self.trusted_keys_srvr = trusted_key_servers + + super().__init__() + + def compose(self) -> ComposeResult: + yield Container( + id=f"{self.app_name}-trusted-key-widget-grid", + classes=f"{self.app_name}" + ) + + def on_mount(self): + container = self.get_widget_by_id(f"{self.app_name}-trusted-key-widget-grid") + self.generate_trusted_key_server_rows(container) + + + def generate_trusted_key_server_rows(self, container: Container): + """ + generate trusted key servers rows + """ + container.mount(Label("Trusted Key Servers [dim](Optional)[/dim]", + classes="trusted-key-servers-label")) + + for key_server in self.trusted_keys_srvr: + server_name = key_server['server_name'] + hyphen_srvr_name = server_name.replace(".", "-") + server_input = input_field( + "server name", + server_name, + "server_name", + "Trusted key server hostname", + "Trusted key server for federating with synapse (your matrix server)", + stacked=True + ) + + # we mount this all at once later down + verify_rows = [] + + # for security, you can have a key for each + verify_keys = key_server.get("verify_keys", {}) + if verify_keys: + for key, value in verify_keys.items(): + verify_rows.append(self.create_verify_key_row(key, value)) + + # verify grid should be to the right to of the trusted key server name + verify_keys_grid = Grid( + *verify_rows, + id=f"{hyphen_srvr_name}-verify-keys-container" + ) + else: + # verify grid should be to the right to of the trusted key server name + verify_keys_grid = Grid( + Button("โž• verify key", + id=f"{hyphen_srvr_name}-add-verify-key", + classes="add-new-verify-key-button"), + id=f"{hyphen_srvr_name}-verify-keys-container" + ) + + # mount the key server row into the main init container + container.mount( + Grid(server_input, + verify_keys_grid, + id=f"{hyphen_srvr_name}-key-server-row", + classes="trusted-key-servers") + ) + + def create_verify_key_row(self, key: str, value: str): + """ + create a verified key row for a given trusted key server + """ + + hyphen_key = key.replace(":","-") + key_field = input_field( + key, + value, + key, + "Verify key value", + "Verify key value", + sensitive=True, + stacked=True + ) + + button = Button("๐Ÿšฎ", + id=f"{hyphen_key}-trash-button", + classes="verify-key-row-delete-button") + verify_key_row = Grid(key_field, + button, + classes="verify-key-row", + id=f"{hyphen_key}-row") + return verify_key_row + + @on(Button.Pressed) + def on_button_pressed(self, event: Button.Pressed): + """ + handle button presses + """ + if "trash-button" in event.button.id: + button_row = event.button.parent + key_row = button_row.parent + server_row = key_row.parent + hyphen_srvr_name = server_row.id.replace("-verify-keys-container","") + + # remove the key row + button_row.remove() + # add a new button + key_row.mount(Button("โž• verify key", + id=f"{hyphen_srvr_name}-add-verify-key", + classes="add-new-verify-key-button")) + self.notify( + "\nThis button doesn't actually work yet, but will soon. " + "Right now, it just does UI magic. In the " + "meantime, edit your yaml config directly under the " + "apps.matrix.init.values section :)", + title="๐Ÿ˜ผ Nope. (but soon)") + elif "-add-verify-key" in event.button.id: + self.notify( + "\nThis button doesn't work yet, but will soon. In the " + "meantime, edit your yaml config directly under the " + "apps.matrix.init.values section :)", + title="๐Ÿ˜ผ Nope. (but soon)") + + +class AddModifyTrustedKeysModalScreen(ModalScreen): + """ + modal screen with inputs to modify + """ + CSS_PATH = ["../css/base_modal.tcss", + "../css/modify_globals_modal.tcss"] + + def __init__(self) -> None: + super().__init__() From 92416dcc317b8f8a63b64a8c7b3049cdfd51f6e8 Mon Sep 17 00:00:00 2001 From: jessebot Date: Wed, 19 Jun 2024 11:43:34 +0200 Subject: [PATCH 04/14] if no trusted keys, use not applicable as the id --- smol_k8s_lab/k8s_apps/social/matrix.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/smol_k8s_lab/k8s_apps/social/matrix.py b/smol_k8s_lab/k8s_apps/social/matrix.py index d10b10078..704c9a32a 100644 --- a/smol_k8s_lab/k8s_apps/social/matrix.py +++ b/smol_k8s_lab/k8s_apps/social/matrix.py @@ -361,6 +361,8 @@ def setup_bitwarden_items(argocd: ArgoCD, user="nousername", password=trusted_key_servers ) + else: + trusted_key_servers_id = "not applicable" # S3 credentials if "http" not in s3_endpoint: From 3e4528e17296ebe4042d3e0501f2cf1e8a5d27e4 Mon Sep 17 00:00:00 2001 From: jessebot Date: Wed, 19 Jun 2024 11:58:35 +0200 Subject: [PATCH 05/14] trusted_key_servers_id was added to the refresh_bweso function for matrix --- smol_k8s_lab/k8s_apps/social/matrix.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/smol_k8s_lab/k8s_apps/social/matrix.py b/smol_k8s_lab/k8s_apps/social/matrix.py index 704c9a32a..9b31db28e 100644 --- a/smol_k8s_lab/k8s_apps/social/matrix.py +++ b/smol_k8s_lab/k8s_apps/social/matrix.py @@ -302,6 +302,14 @@ def refresh_bweso(argocd: ArgoCD, matrix_hostname: str, bitwarden: BwCLI): log.info("No matrix sync id found") sync_id = "Not Applicable" + try: + trusted_key_servers_id = bitwarden.get_item( + f'matrix-trusted-key-servers-{matrix_hostname}', False + )[0]['id'] + except TypeError: + log.info("No matrix trusted key servers id found") + trusted_key_servers_id = "not applicable" + # identity provider name and id are nested in the oidc item fields for field in oidc_id['fields']: if field['name'] == 'idp_id': @@ -322,6 +330,7 @@ def refresh_bweso(argocd: ArgoCD, matrix_hostname: str, bitwarden: BwCLI): 'matrix_authentication_service_bitwarden_id': mas_id, 'matrix_sliding_sync_postgres_credentials_bitwarden_id': sync_db_id, 'matrix_oidc_credentials_bitwarden_id': oidc_id['id'], + 'matrix_trusted_key_servers_bitwarden_id': trusted_key_servers_id, 'matrix_idp_name': idp_name, 'matrix_idp_id': idp_id}) From 122b28ea3c051b0b1c2015b0d8a6b9687d6bc24c Mon Sep 17 00:00:00 2001 From: jessebot Date: Wed, 19 Jun 2024 14:00:37 +0200 Subject: [PATCH 06/14] save trusted keys as json string --- smol_k8s_lab/k8s_apps/social/matrix.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/smol_k8s_lab/k8s_apps/social/matrix.py b/smol_k8s_lab/k8s_apps/social/matrix.py index 9b31db28e..62c7a0d7a 100644 --- a/smol_k8s_lab/k8s_apps/social/matrix.py +++ b/smol_k8s_lab/k8s_apps/social/matrix.py @@ -12,6 +12,7 @@ from smol_k8s_lab.utils.passwords import create_password # external libraries +from json import dumps import logging as log from ulid import ULID @@ -70,7 +71,7 @@ def configure_matrix(argocd: ArgoCD, init_values = init.get('values', {}) # if there's trusted key servers, create a secret for them - trust_key_servers = init_values.get("trust_key_servers", []) + trusted_key_servers = init_values.get("trusted_key_servers", []) backup_vals = process_backup_vals(cfg['backups'], 'matrix', argocd) @@ -140,15 +141,15 @@ def configure_matrix(argocd: ArgoCD, mas_client_secret, mas_admin_token, syncv3_secret, - trust_key_servers, + trusted_key_servers, bitwarden) # else create these as Kubernetes secrets elif not bitwarden and not restore_enabled: - argocd.k8s.create_secret("trusted-key-servers", - matrix_namespace, - trust_key_servers, - "trustedKeyServers") + argocd.k8s.create_secret(name="trusted-key-servers", + namespace=matrix_namespace, + str_data={"trustedKeyServers": dumps(trusted_key_servers)}, + ) # postgresql credentials argocd.k8s.create_secret( @@ -368,7 +369,7 @@ def setup_bitwarden_items(argocd: ArgoCD, name='matrix-trusted-key-servers', item_url=matrix_hostname, user="nousername", - password=trusted_key_servers + password=dumps(trusted_key_servers), ) else: trusted_key_servers_id = "not applicable" From 8ccd8d2b1b98fe28e0fd526ddaca670a9bc9b3bf Mon Sep 17 00:00:00 2001 From: jessebot Date: Wed, 19 Jun 2024 15:11:49 +0200 Subject: [PATCH 07/14] create trusted key secret directly --- smol_k8s_lab/k8s_apps/social/matrix.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/smol_k8s_lab/k8s_apps/social/matrix.py b/smol_k8s_lab/k8s_apps/social/matrix.py index 62c7a0d7a..da5c96ecc 100644 --- a/smol_k8s_lab/k8s_apps/social/matrix.py +++ b/smol_k8s_lab/k8s_apps/social/matrix.py @@ -118,6 +118,13 @@ def configure_matrix(argocd: ArgoCD, else: zitadel_hostname = "" + if trusted_key_servers: + argocd.k8s.create_secret(name="trusted-key-servers", + namespace=matrix_namespace, + str_data=trusted_key_servers, + inline_key="trustedKeyServers" + ) + # if the user has bitwarden enabled if bitwarden and not restore_enabled: setup_bitwarden_items(argocd, @@ -146,11 +153,6 @@ def configure_matrix(argocd: ArgoCD, # else create these as Kubernetes secrets elif not bitwarden and not restore_enabled: - argocd.k8s.create_secret(name="trusted-key-servers", - namespace=matrix_namespace, - str_data={"trustedKeyServers": dumps(trusted_key_servers)}, - ) - # postgresql credentials argocd.k8s.create_secret( 'matrix-pgsql-credentials', @@ -369,7 +371,7 @@ def setup_bitwarden_items(argocd: ArgoCD, name='matrix-trusted-key-servers', item_url=matrix_hostname, user="nousername", - password=dumps(trusted_key_servers), + password=trusted_key_servers ) else: trusted_key_servers_id = "not applicable" From fa87137048e2f09eaa220c5f5a4c1e67959e9f15 Mon Sep 17 00:00:00 2001 From: jessebot Date: Thu, 20 Jun 2024 09:18:16 +0200 Subject: [PATCH 08/14] move where we create trusted key servers secret for matrix --- smol_k8s_lab/k8s_apps/social/matrix.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/smol_k8s_lab/k8s_apps/social/matrix.py b/smol_k8s_lab/k8s_apps/social/matrix.py index da5c96ecc..209402ac6 100644 --- a/smol_k8s_lab/k8s_apps/social/matrix.py +++ b/smol_k8s_lab/k8s_apps/social/matrix.py @@ -118,13 +118,6 @@ def configure_matrix(argocd: ArgoCD, else: zitadel_hostname = "" - if trusted_key_servers: - argocd.k8s.create_secret(name="trusted-key-servers", - namespace=matrix_namespace, - str_data=trusted_key_servers, - inline_key="trustedKeyServers" - ) - # if the user has bitwarden enabled if bitwarden and not restore_enabled: setup_bitwarden_items(argocd, @@ -212,6 +205,15 @@ def configure_matrix(argocd: ArgoCD, 'account_management_url': zitadel.hostname} ) + if init_enabled: + # if init is enabled, always create trusted_key_servers secret + if trusted_key_servers: + argocd.k8s.create_secret(name="trusted-key-servers", + namespace=matrix_namespace, + str_data=trusted_key_servers, + inline_key="trustedKeyServers" + ) + if not app_installed: # if the user is restoring, the process is a little different if init_enabled and restore_enabled: From 403514c53e0e66070913bd1aae77811d50d20136 Mon Sep 17 00:00:00 2001 From: jessebot Date: Thu, 20 Jun 2024 09:25:22 +0200 Subject: [PATCH 09/14] clean up more trusted key servers code to not use bitwarden right now --- smol_k8s_lab/k8s_apps/social/matrix.py | 44 ++++++++++++-------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/smol_k8s_lab/k8s_apps/social/matrix.py b/smol_k8s_lab/k8s_apps/social/matrix.py index 209402ac6..ac1f50551 100644 --- a/smol_k8s_lab/k8s_apps/social/matrix.py +++ b/smol_k8s_lab/k8s_apps/social/matrix.py @@ -70,9 +70,6 @@ def configure_matrix(argocd: ArgoCD, init_values = init.get('values', {}) - # if there's trusted key servers, create a secret for them - trusted_key_servers = init_values.get("trusted_key_servers", []) - backup_vals = process_backup_vals(cfg['backups'], 'matrix', argocd) # configure s3 credentials @@ -141,7 +138,6 @@ def configure_matrix(argocd: ArgoCD, mas_client_secret, mas_admin_token, syncv3_secret, - trusted_key_servers, bitwarden) # else create these as Kubernetes secrets @@ -206,6 +202,9 @@ def configure_matrix(argocd: ArgoCD, ) if init_enabled: + # if there's trusted key servers, create a secret for them + trusted_key_servers = init_values.get("trusted_key_servers", []) + # if init is enabled, always create trusted_key_servers secret if trusted_key_servers: argocd.k8s.create_secret(name="trusted-key-servers", @@ -307,13 +306,13 @@ def refresh_bweso(argocd: ArgoCD, matrix_hostname: str, bitwarden: BwCLI): log.info("No matrix sync id found") sync_id = "Not Applicable" - try: - trusted_key_servers_id = bitwarden.get_item( - f'matrix-trusted-key-servers-{matrix_hostname}', False - )[0]['id'] - except TypeError: - log.info("No matrix trusted key servers id found") - trusted_key_servers_id = "not applicable" + # try: + # trusted_key_servers_id = bitwarden.get_item( + # f'matrix-trusted-key-servers-{matrix_hostname}', False + # )[0]['id'] + # except TypeError: + # log.info("No matrix trusted key servers id found") + # trusted_key_servers_id = "not applicable" # identity provider name and id are nested in the oidc item fields for field in oidc_id['fields']: @@ -322,6 +321,7 @@ def refresh_bweso(argocd: ArgoCD, matrix_hostname: str, bitwarden: BwCLI): if field['name'] == 'idp_name': idp_name = field['value'] + # 'matrix_trusted_key_servers_bitwarden_id': trusted_key_servers_id, argocd.update_appset_secret( {'matrix_registration_credentials_bitwarden_id': reg_id, 'matrix_smtp_credentials_bitwarden_id': smtp_id, @@ -335,7 +335,6 @@ def refresh_bweso(argocd: ArgoCD, matrix_hostname: str, bitwarden: BwCLI): 'matrix_authentication_service_bitwarden_id': mas_id, 'matrix_sliding_sync_postgres_credentials_bitwarden_id': sync_db_id, 'matrix_oidc_credentials_bitwarden_id': oidc_id['id'], - 'matrix_trusted_key_servers_bitwarden_id': trusted_key_servers_id, 'matrix_idp_name': idp_name, 'matrix_idp_id': idp_id}) @@ -361,22 +360,21 @@ def setup_bitwarden_items(argocd: ArgoCD, mas_client_secret: str, mas_admin_token: str, syncv3_secret: str, - trusted_key_servers: str|list|dict, bitwarden: BwCLI): """ setup all the required secrets as items in bitwarden """ sub_header("Creating matrix secrets in Bitwarden") - if trusted_key_servers: - trusted_key_servers_id = bitwarden.create_login( - name='matrix-trusted-key-servers', - item_url=matrix_hostname, - user="nousername", - password=trusted_key_servers - ) - else: - trusted_key_servers_id = "not applicable" + # if trusted_key_servers: + # trusted_key_servers_id = bitwarden.create_login( + # name='matrix-trusted-key-servers', + # item_url=matrix_hostname, + # user="nousername", + # password=trusted_key_servers + # ) + # else: + # trusted_key_servers_id = "not applicable" # S3 credentials if "http" not in s3_endpoint: @@ -533,6 +531,7 @@ def setup_bitwarden_items(argocd: ArgoCD, )[0]['id'] # update the matrix values for the argocd appset + # 'matrix_trusted_key_servers_bitwarden_id': trusted_key_servers_id} argocd.update_appset_secret( {'matrix_registration_credentials_bitwarden_id': reg_id, 'matrix_smtp_credentials_bitwarden_id': smtp_id, @@ -548,7 +547,6 @@ def setup_bitwarden_items(argocd: ArgoCD, 'matrix_authentication_service_bitwarden_id': mas_id, 'matrix_idp_name': idp_name, 'matrix_idp_id': idp_id, - 'matrix_trusted_key_servers_bitwarden_id': trusted_key_servers_id} ) # reload the bitwarden ESO provider From 84c569212b881d4cec875d1c6888ae00809eb861 Mon Sep 17 00:00:00 2001 From: jessebot Date: Thu, 20 Jun 2024 09:26:40 +0200 Subject: [PATCH 10/14] fix missing closing parenthesis --- smol_k8s_lab/k8s_apps/social/matrix.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/smol_k8s_lab/k8s_apps/social/matrix.py b/smol_k8s_lab/k8s_apps/social/matrix.py index ac1f50551..2f7f8fbce 100644 --- a/smol_k8s_lab/k8s_apps/social/matrix.py +++ b/smol_k8s_lab/k8s_apps/social/matrix.py @@ -12,7 +12,6 @@ from smol_k8s_lab.utils.passwords import create_password # external libraries -from json import dumps import logging as log from ulid import ULID @@ -546,7 +545,7 @@ def setup_bitwarden_items(argocd: ArgoCD, 'matrix_oidc_credentials_bitwarden_id': oidc_id, 'matrix_authentication_service_bitwarden_id': mas_id, 'matrix_idp_name': idp_name, - 'matrix_idp_id': idp_id, + 'matrix_idp_id': idp_id} ) # reload the bitwarden ESO provider From 22ab12d91148c2817f5104298782f54b7a6c85d8 Mon Sep 17 00:00:00 2001 From: jessebot Date: Thu, 20 Jun 2024 09:39:43 +0200 Subject: [PATCH 11/14] clean up more trusted key servers stuff --- smol_k8s_lab/k8s_apps/social/matrix.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/smol_k8s_lab/k8s_apps/social/matrix.py b/smol_k8s_lab/k8s_apps/social/matrix.py index 2f7f8fbce..613023d82 100644 --- a/smol_k8s_lab/k8s_apps/social/matrix.py +++ b/smol_k8s_lab/k8s_apps/social/matrix.py @@ -39,6 +39,7 @@ def configure_matrix(argocd: ArgoCD, # verify if initialization is enabled init = cfg.get('init', {'enabled': True, 'restore': {'enabled': False}}) init_enabled = init.get('enabled', True) + init_values = init.get('values', {}) # check if we're restoring and get values for that restore_dict = init.get('restore', {"enabled": False}) @@ -67,8 +68,6 @@ def configure_matrix(argocd: ArgoCD, if init_enabled and not app_installed: argocd.k8s.create_namespace(matrix_namespace) - init_values = init.get('values', {}) - backup_vals = process_backup_vals(cfg['backups'], 'matrix', argocd) # configure s3 credentials From d86616cfe4ccf79cf400d99617d93b7a91e2dc30 Mon Sep 17 00:00:00 2001 From: jessebot Date: Thu, 20 Jun 2024 10:34:28 +0200 Subject: [PATCH 12/14] fix secret to be {"trusted_key_servers": trusted_key_servers} --- smol_k8s_lab/k8s_apps/social/matrix.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/smol_k8s_lab/k8s_apps/social/matrix.py b/smol_k8s_lab/k8s_apps/social/matrix.py index 613023d82..c34e9b1df 100644 --- a/smol_k8s_lab/k8s_apps/social/matrix.py +++ b/smol_k8s_lab/k8s_apps/social/matrix.py @@ -207,7 +207,7 @@ def configure_matrix(argocd: ArgoCD, if trusted_key_servers: argocd.k8s.create_secret(name="trusted-key-servers", namespace=matrix_namespace, - str_data=trusted_key_servers, + str_data={"trusted_key_servers": trusted_key_servers}, inline_key="trustedKeyServers" ) From 59d6cf0c0c8f5f195eab8fc73226aa29ca584333 Mon Sep 17 00:00:00 2001 From: jessebot Date: Thu, 20 Jun 2024 13:36:08 +0200 Subject: [PATCH 13/14] update textual to 0.70 which closes #266 --- poetry.lock | 140 ++++++++++++++++++++++--------------------------- pyproject.toml | 2 +- 2 files changed, 65 insertions(+), 77 deletions(-) diff --git a/poetry.lock b/poetry.lock index 6256f465c..a5bbe0af5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1011,18 +1011,18 @@ dev = ["flake8", "mypy", "pdoc3"] [[package]] name = "filelock" -version = "3.15.1" +version = "3.15.3" description = "A platform independent file lock." optional = false python-versions = ">=3.8" files = [ - {file = "filelock-3.15.1-py3-none-any.whl", hash = "sha256:71b3102950e91dfc1bb4209b64be4dc8854f40e5f534428d8684f953ac847fac"}, - {file = "filelock-3.15.1.tar.gz", hash = "sha256:58a2549afdf9e02e10720eaa4d4470f56386d7a6f72edd7d0596337af8ed7ad8"}, + {file = "filelock-3.15.3-py3-none-any.whl", hash = "sha256:0151273e5b5d6cf753a61ec83b3a9b7d8821c39ae9af9d7ecf2f9e2f17404103"}, + {file = "filelock-3.15.3.tar.gz", hash = "sha256:e1199bf5194a2277273dacd50269f0d87d0682088a3c561c15674ea9005d8635"}, ] [package.extras] docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-asyncio (>=0.21)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-asyncio (>=0.21)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)", "virtualenv (>=20.26.2)"] typing = ["typing-extensions (>=4.8)"] [[package]] @@ -3187,27 +3187,28 @@ files = [ [[package]] name = "psutil" -version = "5.9.8" +version = "6.0.0" description = "Cross-platform lib for process and system monitoring in Python." optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" -files = [ - {file = "psutil-5.9.8-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:26bd09967ae00920df88e0352a91cff1a78f8d69b3ecabbfe733610c0af486c8"}, - {file = "psutil-5.9.8-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:05806de88103b25903dff19bb6692bd2e714ccf9e668d050d144012055cbca73"}, - {file = "psutil-5.9.8-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:611052c4bc70432ec770d5d54f64206aa7203a101ec273a0cd82418c86503bb7"}, - {file = "psutil-5.9.8-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:50187900d73c1381ba1454cf40308c2bf6f34268518b3f36a9b663ca87e65e36"}, - {file = "psutil-5.9.8-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:02615ed8c5ea222323408ceba16c60e99c3f91639b07da6373fb7e6539abc56d"}, - {file = "psutil-5.9.8-cp27-none-win32.whl", hash = "sha256:36f435891adb138ed3c9e58c6af3e2e6ca9ac2f365efe1f9cfef2794e6c93b4e"}, - {file = "psutil-5.9.8-cp27-none-win_amd64.whl", hash = "sha256:bd1184ceb3f87651a67b2708d4c3338e9b10c5df903f2e3776b62303b26cb631"}, - {file = "psutil-5.9.8-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:aee678c8720623dc456fa20659af736241f575d79429a0e5e9cf88ae0605cc81"}, - {file = "psutil-5.9.8-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8cb6403ce6d8e047495a701dc7c5bd788add903f8986d523e3e20b98b733e421"}, - {file = "psutil-5.9.8-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d06016f7f8625a1825ba3732081d77c94589dca78b7a3fc072194851e88461a4"}, - {file = "psutil-5.9.8-cp36-cp36m-win32.whl", hash = "sha256:7d79560ad97af658a0f6adfef8b834b53f64746d45b403f225b85c5c2c140eee"}, - {file = "psutil-5.9.8-cp36-cp36m-win_amd64.whl", hash = "sha256:27cc40c3493bb10de1be4b3f07cae4c010ce715290a5be22b98493509c6299e2"}, - {file = "psutil-5.9.8-cp37-abi3-win32.whl", hash = "sha256:bc56c2a1b0d15aa3eaa5a60c9f3f8e3e565303b465dbf57a1b730e7a2b9844e0"}, - {file = "psutil-5.9.8-cp37-abi3-win_amd64.whl", hash = "sha256:8db4c1b57507eef143a15a6884ca10f7c73876cdf5d51e713151c1236a0e68cf"}, - {file = "psutil-5.9.8-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:d16bbddf0693323b8c6123dd804100241da461e41d6e332fb0ba6058f630f8c8"}, - {file = "psutil-5.9.8.tar.gz", hash = "sha256:6be126e3225486dff286a8fb9a06246a5253f4c7c53b475ea5f5ac934e64194c"}, +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +files = [ + {file = "psutil-6.0.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a021da3e881cd935e64a3d0a20983bda0bb4cf80e4f74fa9bfcb1bc5785360c6"}, + {file = "psutil-6.0.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:1287c2b95f1c0a364d23bc6f2ea2365a8d4d9b726a3be7294296ff7ba97c17f0"}, + {file = "psutil-6.0.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:a9a3dbfb4de4f18174528d87cc352d1f788b7496991cca33c6996f40c9e3c92c"}, + {file = "psutil-6.0.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:6ec7588fb3ddaec7344a825afe298db83fe01bfaaab39155fa84cf1c0d6b13c3"}, + {file = "psutil-6.0.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:1e7c870afcb7d91fdea2b37c24aeb08f98b6d67257a5cb0a8bc3ac68d0f1a68c"}, + {file = "psutil-6.0.0-cp27-none-win32.whl", hash = "sha256:02b69001f44cc73c1c5279d02b30a817e339ceb258ad75997325e0e6169d8b35"}, + {file = "psutil-6.0.0-cp27-none-win_amd64.whl", hash = "sha256:21f1fb635deccd510f69f485b87433460a603919b45e2a324ad65b0cc74f8fb1"}, + {file = "psutil-6.0.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c588a7e9b1173b6e866756dde596fd4cad94f9399daf99ad8c3258b3cb2b47a0"}, + {file = "psutil-6.0.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ed2440ada7ef7d0d608f20ad89a04ec47d2d3ab7190896cd62ca5fc4fe08bf0"}, + {file = "psutil-6.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fd9a97c8e94059b0ef54a7d4baf13b405011176c3b6ff257c247cae0d560ecd"}, + {file = "psutil-6.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2e8d0054fc88153ca0544f5c4d554d42e33df2e009c4ff42284ac9ebdef4132"}, + {file = "psutil-6.0.0-cp36-cp36m-win32.whl", hash = "sha256:fc8c9510cde0146432bbdb433322861ee8c3efbf8589865c8bf8d21cb30c4d14"}, + {file = "psutil-6.0.0-cp36-cp36m-win_amd64.whl", hash = "sha256:34859b8d8f423b86e4385ff3665d3f4d94be3cdf48221fbe476e883514fdb71c"}, + {file = "psutil-6.0.0-cp37-abi3-win32.whl", hash = "sha256:a495580d6bae27291324fe60cea0b5a7c23fa36a7cd35035a16d93bdcf076b9d"}, + {file = "psutil-6.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:33ea5e1c975250a720b3a6609c490db40dae5d83a4eb315170c4fe0d8b1f34b3"}, + {file = "psutil-6.0.0-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:ffe7fc9b6b36beadc8c322f84e1caff51e8703b88eee1da46d1e3a6ae11b4fd0"}, + {file = "psutil-6.0.0.tar.gz", hash = "sha256:8faae4f310b6d969fa26ca0545338b21f73c6b15db7c4a8d934a5482faa818f2"}, ] [package.extras] @@ -3539,13 +3540,13 @@ extra = ["pygments (>=2.12)"] [[package]] name = "pynndescent" -version = "0.5.12" +version = "0.5.13" description = "Nearest Neighbor Descent" optional = false python-versions = "*" files = [ - {file = "pynndescent-0.5.12-py3-none-any.whl", hash = "sha256:9023dc5fea520a4e84d0633ae735db97d2509da927bfa86c897e61f3315473c7"}, - {file = "pynndescent-0.5.12.tar.gz", hash = "sha256:0736291fcbbedfd5e0a3a280f71a63f8eb2f8bd9670d4c0b51ac1b4d081adf70"}, + {file = "pynndescent-0.5.13-py3-none-any.whl", hash = "sha256:69aabb8f394bc631b6ac475a1c7f3994c54adf3f51cd63b2730fefba5771b949"}, + {file = "pynndescent-0.5.13.tar.gz", hash = "sha256:d74254c0ee0a1eeec84597d5fe89fedcf778593eeabe32c2f97412934a9800fb"}, ] [package.dependencies] @@ -3692,13 +3693,13 @@ six = ">=1.5" [[package]] name = "python-ulid" -version = "2.6.0" +version = "2.7.0" description = "Universally unique lexicographically sortable identifier" optional = false python-versions = ">=3.9" files = [ - {file = "python_ulid-2.6.0-py3-none-any.whl", hash = "sha256:b47cc7a427b82f7526af96385d7702685df808e9b4922523dd5988a3ba98a89d"}, - {file = "python_ulid-2.6.0.tar.gz", hash = "sha256:904e19093dd6578a5ce01a8274e3e228d556d47be3bda328da2d3601c5240c4f"}, + {file = "python_ulid-2.7.0-py3-none-any.whl", hash = "sha256:c81658e382f69bad8c6d365155c4ae21843ae4226b94f72c12d7adcbb545a251"}, + {file = "python_ulid-2.7.0.tar.gz", hash = "sha256:18eb595885140851a490a95b0da4447911ff69fa9f434732067b97f6956f9fe9"}, ] [package.extras] @@ -4250,18 +4251,18 @@ test = ["array-api-strict", "asv", "gmpy2", "hypothesis (>=6.30)", "mpmath", "po [[package]] name = "setuptools" -version = "70.0.0" +version = "70.1.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-70.0.0-py3-none-any.whl", hash = "sha256:54faa7f2e8d2d11bcd2c07bed282eef1046b5c080d1c32add737d7b5817b1ad4"}, - {file = "setuptools-70.0.0.tar.gz", hash = "sha256:f211a66637b8fa059bb28183da127d4e86396c991a942b028c6650d4319c3fd0"}, + {file = "setuptools-70.1.0-py3-none-any.whl", hash = "sha256:d9b8b771455a97c8a9f3ab3448ebe0b29b5e105f1228bba41028be116985a267"}, + {file = "setuptools-70.1.0.tar.gz", hash = "sha256:01a1e793faa5bd89abc851fa15d0a0db26f160890c7102cd8dce643e886b47f5"}, ] [package.extras] docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mypy (==1.9)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.1)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.10.0)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.1)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] [[package]] name = "shellingham" @@ -4657,13 +4658,13 @@ files = [ [[package]] name = "textual" -version = "0.69.0" +version = "0.70.0" description = "Modern Text User Interface framework" optional = false python-versions = "<4.0,>=3.8" files = [ - {file = "textual-0.69.0-py3-none-any.whl", hash = "sha256:51d19a5eaeb00e6dabc7b1ef3d8de558dc78e55a3b273c8cf8273b3db574a651"}, - {file = "textual-0.69.0.tar.gz", hash = "sha256:73736996f468f20efdc8854482db02bf8799586430a39bc0a7c97f91043081b0"}, + {file = "textual-0.70.0-py3-none-any.whl", hash = "sha256:774bf45782193760ca273b915fd685cada37d0836237d61dc57d5bcdbe2c7ddb"}, + {file = "textual-0.70.0.tar.gz", hash = "sha256:9ca3f615b5cf442246325e40ef8255424c42b4241d3c62f9c0f96951bab82b1e"}, ] [package.dependencies] @@ -4694,45 +4695,32 @@ typing-extensions = ">=4.4.0,<5.0.0" [[package]] name = "thinc" -version = "8.2.4" +version = "8.2.5" description = "A refreshing functional take on deep learning, compatible with your favorite libraries" optional = false python-versions = ">=3.6" files = [ - {file = "thinc-8.2.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:aaae34c28ebc7a0ba980e6c774f148e272375ff7d4ef6ae2977698edae052e52"}, - {file = "thinc-8.2.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7a6c807cb75a22a17e5333377aff203dabf10daa457ce9e78b19f499a44dd816"}, - {file = "thinc-8.2.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b53c092ab30abb9a3b46ef72a8a6af76db42822b550eff778b0decf95af572c4"}, - {file = "thinc-8.2.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5724ea71dbdbb0d0168471884b9b6909bedaccfda01524c5e775a6fbc39d1bc7"}, - {file = "thinc-8.2.4-cp310-cp310-win_amd64.whl", hash = "sha256:bb14e49ddb15770201682eda8381db6393f76580c1eb72d45e77e1202598116e"}, - {file = "thinc-8.2.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ccc58e47bc285e9afbf92ed6104f555abfa285a4b92198d955d344c4c1942607"}, - {file = "thinc-8.2.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:baa4af044bfcaf9df6a02d6c6d6e96c960da540478a522daabfbde8923df3554"}, - {file = "thinc-8.2.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b0e34bf322516a039e45c1da72eb82bcc97eb1f7c232b66b88f0c86f15a1202"}, - {file = "thinc-8.2.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ebc8ab48d19cd69ad9a0de2bbe49b7c20a91150faeb119638bea4c502c52b77f"}, - {file = "thinc-8.2.4-cp311-cp311-win_amd64.whl", hash = "sha256:9f8c6c006b7cbe3ebb543c224159b004b52a8ff8922615577656e1458ee4bbf0"}, - {file = "thinc-8.2.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:997a1a399af074b34e25695f37ad48f8437e7c150705891f4db89aeb430df35a"}, - {file = "thinc-8.2.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8e28ba753cdf925ac25b52ea6c4baf5104c6ed6874d9e3dfe768ff98d5118db1"}, - {file = "thinc-8.2.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5c3874361a1d3c469dd7c9054d4d16b7afcf791e9c47705766d690685fe702d"}, - {file = "thinc-8.2.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4a22e76e4651fb6b209cfba2e1c167e8537286ae35fb87769a17af491f995b5"}, - {file = "thinc-8.2.4-cp312-cp312-win_amd64.whl", hash = "sha256:ebfd9d79d2bdadec551cb9ca8c7fdeacb56db642158c56cdb039de47e9aad995"}, - {file = "thinc-8.2.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f46f0f58f3bc02beeee5977a991335b845cb15bf1836ee8d8d15b613805c0016"}, - {file = "thinc-8.2.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d879df0997959f9d7087b0e392e72e120bde5613eb8a7c1c453370c48284e7f"}, - {file = "thinc-8.2.4-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:795a7a1a03767a40d1e2a19fcf25c552a8d8765c78c1837514cabf5fe98817b9"}, - {file = "thinc-8.2.4-cp36-cp36m-win_amd64.whl", hash = "sha256:a276287e55b0ec50c7e8f1acef28f5353c59234af1efc54a19516328f50a6f68"}, - {file = "thinc-8.2.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:21a5cb6633b4af8b49a18a3088cdcbc59756ce6a4202574f4151dd4df18bab49"}, - {file = "thinc-8.2.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8ca9fcddc3852b733e4754f37bb4d20693192171f1e3e9714b00abe5d74fffeb"}, - {file = "thinc-8.2.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd67e210a4a67781c9864ef45e27ec009c1f4234c737c4a2d0964aeebd3d39a1"}, - {file = "thinc-8.2.4-cp37-cp37m-win_amd64.whl", hash = "sha256:37ea70230bc4a149905e21ba620ad78ec5362b3cf8f9d1233523d6ec03a3b8e5"}, - {file = "thinc-8.2.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5586115b2f3c1c9ecc8f9dbed4a26a46d44c40e8f6be0e58e63fb673271cd0d9"}, - {file = "thinc-8.2.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:334097a26742ff6552a2b1ff347207b8ce4048a70756e33849bab07122f13403"}, - {file = "thinc-8.2.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a124684987554170c043ae9c497c5ebbd619a9cf2053462ff6b7e359541fbafd"}, - {file = "thinc-8.2.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e8f9e147b41a1e02c232d5cc4b2a333b47a245d9e87dbcd1b3f11636332a1ae5"}, - {file = "thinc-8.2.4-cp38-cp38-win_amd64.whl", hash = "sha256:58b172d3546ecd14d257e2f37e7b9784941caa919544604137810a5477f87c99"}, - {file = "thinc-8.2.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:03ab79a1734db519bd355d1c7eb41a2425d4d5c1ad4f416ea4e09cd42b8854a8"}, - {file = "thinc-8.2.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c466289b6fb40f477e32f99647e03256d0b1d775707778dac07973fd352c5220"}, - {file = "thinc-8.2.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cbffb3d284c9a54cf8bfee606e47028a27a2d11b0b1e2b83137cc03169e8a8f1"}, - {file = "thinc-8.2.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abeb742352a106359ac76f048c0f4af745c59c75e02b68cc4d62cde20fcca0c5"}, - {file = "thinc-8.2.4-cp39-cp39-win_amd64.whl", hash = "sha256:ed514b3edb185c5531fcfd77a7b0a43c196a269f1e157a025d8138076ba6328d"}, - {file = "thinc-8.2.4.tar.gz", hash = "sha256:9383b39f286291519ebbb6454bab76404992599b0cbdfaec56b2f985023186a7"}, + {file = "thinc-8.2.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dc267f6aad80a681a85f50383afe91da9e2bec56fefdda86bfa2e4f529bef191"}, + {file = "thinc-8.2.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d80f1e497971c9fa0938f5cc8fe607bbe87356b405fb7bbc3ff9f32fb4eed3bb"}, + {file = "thinc-8.2.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0933adbd3e65e30d3bef903e77a368bc8a41bed34b0d18df6d4fc0536908e21f"}, + {file = "thinc-8.2.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54bac2ba23b208fdaf267cd6113d26a5ecbb3b0e0c6015dff784ae6a9c5e78ca"}, + {file = "thinc-8.2.5-cp310-cp310-win_amd64.whl", hash = "sha256:399260197ef3f8d9600315fc5b5a1d5940400fceb0361de642e9fe3506d82385"}, + {file = "thinc-8.2.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a75c0de3340afed594beda293661de145f3842873df56d9989bc338148f13fab"}, + {file = "thinc-8.2.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6b166d1a22003ee03bc236370fff2884744c1fb758a6209a2512d305773d07d7"}, + {file = "thinc-8.2.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34db8a023b9f70645fdf06c510584ba6d8b97ec53c1e094f42d95652bf8c875f"}, + {file = "thinc-8.2.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8901b30db1071ea8d5e4437429c8632535bf5ed87938ce3bb5057bed9f15aed8"}, + {file = "thinc-8.2.5-cp311-cp311-win_amd64.whl", hash = "sha256:8ef5d46d62e31f2450224ab22391a606cf427b13e20cfc570f70422e2f333872"}, + {file = "thinc-8.2.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9fc26697e2358c71a5fe243d52e98ae67ee1a3b314eead5031845b6d1c0d121c"}, + {file = "thinc-8.2.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8e299d4dc41107385d6d14d8604a060825798a031cabe2b894b22f9d75d9eaad"}, + {file = "thinc-8.2.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8a8f2f249f2be9a5ce2a81a6efe7503b68be7b57e47ad54ab28204e1f0c723b"}, + {file = "thinc-8.2.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87e729f33c76ec6df9b375989743252ab880d79f3a2b4175169b21dece90f102"}, + {file = "thinc-8.2.5-cp312-cp312-win_amd64.whl", hash = "sha256:c5f750ea2dd32ca6d46947025dacfc0f6037340c4e5f7adb9af84c75f65aa7d8"}, + {file = "thinc-8.2.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bb97e2f699a3df16112ef5460cbfb0c9189a5fbc0e76bcf170ed7d995bdce367"}, + {file = "thinc-8.2.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5c78fb218273894168d1ca2dd3a20f28dba5a7fa698c4f2a2fc425eda2086cfc"}, + {file = "thinc-8.2.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdc27da534807a2addd1c3d2a3d19f99e3eb67fdbce81c21f4e4c8bfa94ac15b"}, + {file = "thinc-8.2.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b884e56eaeb9e5c7bfeb1c8810a3cbad19a599b33b9f3152b90b67f468471ac"}, + {file = "thinc-8.2.5-cp39-cp39-win_amd64.whl", hash = "sha256:df2138cf379061017ecb8bf609a8857e7904709ef0a9a2252783c16f67a2b749"}, + {file = "thinc-8.2.5.tar.gz", hash = "sha256:c2963791c934cc7fbd8f9b942d571cac79892ad11630bfca690a868c32752b75"}, ] [package.dependencies] @@ -4741,7 +4729,7 @@ catalogue = ">=2.0.4,<2.1.0" confection = ">=0.0.1,<1.0.0" cymem = ">=2.0.2,<2.1.0" murmurhash = ">=1.0.2,<1.1.0" -numpy = {version = ">=1.19.0", markers = "python_version >= \"3.9\""} +numpy = {version = ">=1.19.0,<2.0.0", markers = "python_version >= \"3.9\""} packaging = ">=20.0" preshed = ">=3.0.2,<3.1.0" pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<3.0.0" @@ -5224,13 +5212,13 @@ tbb = ["tbb (>=2019.0)"] [[package]] name = "urllib3" -version = "2.2.1" +version = "2.2.2" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.8" files = [ - {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, - {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, + {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"}, + {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"}, ] [package.extras] @@ -5548,4 +5536,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = ">=3.11,<3.13" -content-hash = "81a4dc5b53abc32913b12ed1a7da345984c3ad920681666ba996b3ccbdc8625a" +content-hash = "922f6331de798d7b3b2e6f51409c52988e648ccbd7950e4cc0445180cc90e2be" diff --git a/pyproject.toml b/pyproject.toml index 9e47fa687..4a2c74d08 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,7 +43,7 @@ requests = "^2.32" rich = "^13.0" ruamel-yaml = "^0.18" ruamel-yaml-string = "^0.1" -textual = "^0.69.0" +textual = "^0.70" xdg-base-dirs = "^6.0" pygame = "^2.5" python-ulid = "^2.6" From 1bfcb983801f7b334ae73628d54fc837bc1ac1fe Mon Sep 17 00:00:00 2001 From: jessebot Date: Thu, 20 Jun 2024 13:43:43 +0200 Subject: [PATCH 14/14] update help screenshot --- docs/assets/images/screenshots/help_text.svg | 120 +++++++++---------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/docs/assets/images/screenshots/help_text.svg b/docs/assets/images/screenshots/help_text.svg index 2939acf5f..04d86a745 100644 --- a/docs/assets/images/screenshots/help_text.svg +++ b/docs/assets/images/screenshots/help_text.svg @@ -19,131 +19,131 @@ font-weight: 700; } - .terminal-1958449836-matrix { + .terminal-1696830123-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-1958449836-title { + .terminal-1696830123-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-1958449836-r1 { fill: #c5c8c6 } -.terminal-1958449836-r2 { fill: #5f87ff } -.terminal-1958449836-r3 { fill: #5f87af;font-style: italic; } -.terminal-1958449836-r4 { fill: #5f87af } -.terminal-1958449836-r5 { fill: #8787ff } -.terminal-1958449836-r6 { fill: #afafff } -.terminal-1958449836-r7 { fill: #87afff } -.terminal-1958449836-r8 { fill: #afafff;font-weight: bold } -.terminal-1958449836-r9 { fill: #868887 } -.terminal-1958449836-r10 { fill: #6179a9 } -.terminal-1958449836-r11 { fill: #6161a9 } -.terminal-1958449836-r12 { fill: #7979a9;font-weight: bold } -.terminal-1958449836-r13 { fill: #4961a9 } + .terminal-1696830123-r1 { fill: #c5c8c6 } +.terminal-1696830123-r2 { fill: #5f87ff } +.terminal-1696830123-r3 { fill: #5f87af;font-style: italic; } +.terminal-1696830123-r4 { fill: #5f87af } +.terminal-1696830123-r5 { fill: #8787ff } +.terminal-1696830123-r6 { fill: #afafff } +.terminal-1696830123-r7 { fill: #87afff } +.terminal-1696830123-r8 { fill: #afafff;font-weight: bold } +.terminal-1696830123-r9 { fill: #868887 } +.terminal-1696830123-r10 { fill: #6179a9 } +.terminal-1696830123-r11 { fill: #6161a9 } +.terminal-1696830123-r12 { fill: #7979a9;font-weight: bold } +.terminal-1696830123-r13 { fill: #4961a9 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - term + term - + - -                           ๐Ÿงธsmol k8s lab - -Install slim Kubernetes distros + plus all your apps via Argo CD. - -Usage:smol-k8s-lab[OPTIONS] - -โ•ญโ”€ ส• แต”แดฅแต”ส” Options โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ -โ”‚โ”‚ -โ”‚-c--config CONFIG_FILEFull path and name of the YAML config file to parse.            โ”‚ -โ”‚Defaults to $XDG_CONFIG_HOME/smol-k8s-lab/config.yamlโ”‚ -โ”‚โ”‚ -โ”‚-D--delete CLUSTER_NAMEDelete an existing cluster by name.                             โ”‚ -โ”‚โ”‚ -โ”‚-i--interactiveโš™๏ธ Interactively configures smol-k8s-labโ”‚ -โ”‚โ”‚ -โ”‚-v--versionPrint the version of smol-k8s-lab (v5.6.2)                      โ”‚ -โ”‚โ”‚ -โ”‚-f--final_cmdRun command immediately after smol-k8s-lab before main cli phaseโ”‚ -โ”‚โ”‚ -โ”‚-h--helpShow this message and exit.                                     โ”‚ -โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ™ฅ docs: https://small-hack.github.io/smol-k8s-labโ”€โ•ฏ + +                           ๐Ÿงธsmol k8s lab + +Install slim Kubernetes distros + plus all your apps via Argo CD. + +Usage:smol-k8s-lab[OPTIONS] + +โ•ญโ”€ ส• แต”แดฅแต”ส” Options โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ +โ”‚โ”‚ +โ”‚-c--config CONFIG_FILEFull path and name of the YAML config file to parse.            โ”‚ +โ”‚Defaults to $XDG_CONFIG_HOME/smol-k8s-lab/config.yamlโ”‚ +โ”‚โ”‚ +โ”‚-D--delete CLUSTER_NAMEDelete an existing cluster by name.                             โ”‚ +โ”‚โ”‚ +โ”‚-i--interactiveโš™๏ธ Interactively configures smol-k8s-labโ”‚ +โ”‚โ”‚ +โ”‚-v--versionPrint the version of smol-k8s-lab (v5.7.0)                      โ”‚ +โ”‚โ”‚ +โ”‚-f--final_cmdRun command immediately after smol-k8s-lab before main cli phaseโ”‚ +โ”‚โ”‚ +โ”‚-h--helpShow this message and exit.                                     โ”‚ +โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ™ฅ docs: https://small-hack.github.io/smol-k8s-labโ”€โ•ฏ