diff --git a/.gitignore b/.gitignore index aa901749a0..72ef9ffe2b 100644 --- a/.gitignore +++ b/.gitignore @@ -33,7 +33,7 @@ shell.nix build.nix .direnv -# ignore deploments +# ignore deployments do-jupyterhub jupyterhub-aws gcp-jupyterhub diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3fd8676936..79f863d558 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,7 +22,7 @@ ci: repos: # general - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: - id: end-of-file-fixer exclude: "^docs-sphinx/cli.html" @@ -37,12 +37,12 @@ repos: exclude: "^src/_nebari/template/" - repo: https://github.com/crate-ci/typos - rev: v1.30.0 + rev: v1 hooks: - id: typos - repo: https://github.com/codespell-project/codespell - rev: v2.4.1 + rev: v2.4.2 hooks: - id: codespell args: @@ -54,20 +54,20 @@ repos: - tomli # python - - repo: https://github.com/psf/black - rev: 25.1.0 + - repo: https://github.com/psf/black-pre-commit-mirror + rev: 26.5.1 hooks: - id: black args: ["--line-length=88", "--exclude=/src/_nebari/template/"] - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.9.9 + rev: v0.15.20 hooks: - id: ruff args: ["--fix"] - repo: https://github.com/pycqa/isort - rev: 6.0.1 + rev: 9.0.0a3 hooks: - id: isort name: isort @@ -77,7 +77,7 @@ repos: # terraform - repo: https://github.com/antonbabenko/pre-commit-terraform - rev: v1.97.4 + rev: v1.108.0 hooks: - id: terraform_fmt args: diff --git a/src/_nebari/deploy.py b/src/_nebari/deploy.py index 4478e65f75..3bd78c5e60 100644 --- a/src/_nebari/deploy.py +++ b/src/_nebari/deploy.py @@ -17,9 +17,7 @@ def deploy_configuration( disable_checks: bool = False, ) -> Dict[str, Any]: if config.prevent_deploy: - raise ValueError( - textwrap.dedent( - """ + raise ValueError(textwrap.dedent(""" Deployment prevented due to the prevent_deploy setting in your nebari-config.yaml file. You could remove that field to deploy your Nebari, but please do NOT do so without fully understanding why that value was set in the first place. @@ -29,9 +27,7 @@ def deploy_configuration( PLEASE get in touch with Nebari development team at https://github.com/nebari-dev/nebari for assistance in proceeding. Your data may be at risk without our guidance. - """ - ) - ) + """)) if config.domain is None: logger.info( diff --git a/src/_nebari/provider/cicd/linter.py b/src/_nebari/provider/cicd/linter.py index 45cdb9f6a9..98703b5c9d 100644 --- a/src/_nebari/provider/cicd/linter.py +++ b/src/_nebari/provider/cicd/linter.py @@ -36,13 +36,11 @@ def generate_lint_message(config): # lint/validate nebari-config.yaml all_pass, messages, validate_code = nebari_validate(config) - pass_lint = textwrap.dedent( - """ + pass_lint = textwrap.dedent(""" This is an automatic response from the Nebari linter. I just wanted to let you know that I linted your `nebari-config.yaml` in your PR and I didn't find any problems. - """ - ) + """) # it should be better to parse this messages first bad_lint = ( @@ -56,12 +54,10 @@ def generate_lint_message(config): if not pr_config: status = "no configuration file" - message = textwrap.dedent( - """ + message = textwrap.dedent(""" This is an automatic response from the Nebari linter. I was trying to look for the `nebari-config.yaml` file to lint for you, but couldn't find any... - """ - ) + """) elif all_pass: status = "Success" diff --git a/src/_nebari/upgrade.py b/src/_nebari/upgrade.py index 0d05e96c6e..8bac5965ad 100644 --- a/src/_nebari/upgrade.py +++ b/src/_nebari/upgrade.py @@ -1331,8 +1331,7 @@ def _version_specific_upgrade( provider_full_name = provider_enum_name_map[provider] if not config.get(provider_full_name, {}).get("node_groups", {}): try: - text = textwrap.dedent( - f""" + text = textwrap.dedent(f""" The default node groups for GCP have been changed to cost efficient e2 family nodes reducing the running cost of Nebari on GCP by ~50%. This change will affect your current deployment, and will result in ~15 minutes of downtime during the upgrade step as the node groups are switched out, but shouldn't result in data loss. @@ -1343,8 +1342,7 @@ def _version_specific_upgrade( Would you like to upgrade to the cost effective node groups [purple]{config_filename}[/purple]? If not, select "N" and the old default node groups will be added to the nebari config file. - """ - ) + """) continue_ = kwargs.get("attempt_fixes", False) or Confirm.ask( text, default=True, @@ -1370,8 +1368,7 @@ def _version_specific_upgrade( except KeyError: pass else: - text = textwrap.dedent( - """ + text = textwrap.dedent(""" The default node groups for GCP have been changed to cost efficient e2 family nodes reducing the running cost of Nebari on GCP by ~50%. Consider upgrading your node group instance types to the new default configuration. @@ -1380,8 +1377,7 @@ def _version_specific_upgrade( As always, make sure to backup data before upgrading. See https://www.nebari.dev/docs/how-tos/manual-backup for more information. The new default node groups instances are: - """ - ) + """) text += json.dumps( { "general": {"instance": "e2-highmem-4"}, @@ -1467,8 +1463,7 @@ def _version_specific_upgrade( rich.print("\n ⚠️ Upgrade Warning ⚠️") - text = textwrap.dedent( - """ + text = textwrap.dedent(""" Please ensure no users are currently logged in prior to deploying this update. @@ -1489,8 +1484,7 @@ def _version_specific_upgrade( mounted. For more details check our [green][link=https://www.nebari.dev/docs/references/release/]release notes[/link][/green]. - """ - ) + """) rich.print(text) keycloak_admin = None @@ -1522,15 +1516,11 @@ def _version_specific_upgrade( ) except ValueError as e: if "invalid_grant" in str(e): - rich.print( - textwrap.dedent( - """ + rich.print(textwrap.dedent(""" [red bold]Failed to connect to the Keycloak server.[/red bold]\n [yellow]Please set the [bold]KEYCLOAK_ADMIN_USERNAME[/bold] and [bold]KEYCLOAK_ADMIN_PASSWORD[/bold] environment variables with the Keycloak root credentials and try again.[/yellow] - """ - ) - ) + """)) exit() else: # Handle other exceptions @@ -1633,8 +1623,7 @@ def _version_specific_upgrade( ): rich.print("\n ⚠️ Upgrade Warning ⚠️") - text = textwrap.dedent( - """ + text = textwrap.dedent(""" In this release, we have updated our maximum supported Kubernetes version from 1.29 to 1.31. Please note that Nebari will NOT automatically upgrade your running Kubernetes version as part of the redeployment process. @@ -1645,8 +1634,7 @@ def _version_specific_upgrade( For more information on upgrading Kubernetes for your specific cloud provider, please visit: https://www.nebari.dev/docs/how-tos/kubernetes-version-upgrade - """ - ) + """) rich.print(text) # If the Nebari provider is Azure, we must handle a major version upgrade @@ -1657,9 +1645,7 @@ def _version_specific_upgrade( if config.get("provider", "") == "azure": rich.print("\n ⚠️ Azure Provider Upgrade Notice ⚠️") - rich.print( - textwrap.dedent( - """ + rich.print(textwrap.dedent(""" In this Nebari release, the Azure Terraform provider has been upgraded from version 3.97.1 to 4.7.0. This major update includes internal schema changes for certain resources, most notably the `azurerm_storage_account`. @@ -1670,9 +1656,7 @@ def _version_specific_upgrade( For detailed information on the Azure provider 4.x changes, please visit: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/guides/4.0-upgrade-guide - """ - ) - ) + """)) # Prompt user for confirmation continue_ = kwargs.get("attempt_fixes", False) or Confirm.ask( @@ -1753,8 +1737,7 @@ def _version_specific_upgrade( ]: rich.print("\n ⚠️ Node Taints Update ⚠️") - text = textwrap.dedent( - """ + text = textwrap.dedent(""" Starting with Nebari version 2025.4.1, node taints will be automatically applied to all non-general node groups by default. Node taints help ensure that specific workloads run only on designated nodes, improving resource utilization and isolation. This change will include: @@ -1764,8 +1747,7 @@ def _version_specific_upgrade( If you prefer not to use node taints, you can opt out by adding `taints: []` to each node group definition in your nebari-config.yaml file. - """ - ) + """) rich.print(text) provider_full_name = provider_enum_name_map.get(provider) @@ -2074,9 +2056,7 @@ def _version_specific_upgrade( namespace = config.get("namespace", "dev") rich.print("\n ⚠️ CRITICAL UPGRADE WARNING ⚠️") - rich.print( - textwrap.dedent( - f""" + rich.print(textwrap.dedent(f""" This version includes a major [bold red]Keycloak upgrade[/bold red] from the [green]keycloak[/green] chart (15.0.2) to the [green]keycloakx[/green] chart (7.1.3). This upgrade changes the underlying architecture from JBoss/WildFly to Quarkus. @@ -2092,9 +2072,7 @@ def _version_specific_upgrade( After this upgrade step completes, you will need to run: [cyan]nebari deploy -c {config_filename}[/cyan] to apply the changes - """ - ) - ) + """)) # Get all available contexts contexts, active_context = kubernetes.config.list_kube_config_contexts() diff --git a/tests/tests_unit/test_cli_keycloak.py b/tests/tests_unit/test_cli_keycloak.py index 42198df69d..b1eb0e741a 100644 --- a/tests/tests_unit/test_cli_keycloak.py +++ b/tests/tests_unit/test_cli_keycloak.py @@ -124,8 +124,7 @@ def parse_yaml(stdout_str: str, headers: list): def test_parse_table(): - table_str = dedent( - """ Keycloak Users (Count: 3) + table_str = dedent(""" Keycloak Users (Count: 3) ┏━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ┃ Username ┃ Email ┃ Groups ┃ ┡━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━┩ @@ -133,8 +132,7 @@ def test_parse_table(): │ test-admin │ test-admin@example.com │ ['admin'] │ │ test-nogroup │ test-nogroup@example.com │ [] │ └──────────────┴──────────────────────────┴──────────────────────────┘ - """ - ) + """) expected = [ { "username": "test-dev", @@ -160,14 +158,12 @@ def test_parse_table(): def test_parse_yaml(): - yaml_str = dedent( - """ + yaml_str = dedent(""" - name: test roles: - allow-test-to-pass - other-role - """ - ) + """) expected = [ { "name": "test", diff --git a/tests/tests_unit/test_cli_upgrade.py b/tests/tests_unit/test_cli_upgrade.py index 364b51b23b..8ac1edae0e 100644 --- a/tests/tests_unit/test_cli_upgrade.py +++ b/tests/tests_unit/test_cli_upgrade.py @@ -173,8 +173,7 @@ def test_cli_upgrade_image_tags(monkeypatch: pytest.MonkeyPatch): end_version, # # number of "y" inputs directly corresponds to how many matching images are found in yaml inputs=["y", "y", "y", "y", "y", "y", "y"], - addl_config=yaml.safe_load( - f""" + addl_config=yaml.safe_load(f""" default_images: jupyterhub: quay.io/nebari/nebari-jupyterhub:{start_version} jupyterlab: quay.io/nebari/nebari-jupyterlab:{start_version} @@ -196,8 +195,7 @@ def test_cli_upgrade_image_tags(monkeypatch: pytest.MonkeyPatch): dask_worker: test: image: quay.io/nebari/nebari-dask-worker:{start_version} -""" - ), +"""), ) for _, v in upgraded["default_images"].items(): @@ -240,15 +238,13 @@ def test_cli_upgrade_fail_on_downgrade(): tmp_file = Path(tmp).resolve() / "nebari-config.yaml" assert tmp_file.exists() is False - nebari_config = yaml.safe_load( - f""" + nebari_config = yaml.safe_load(f""" project_name: test provider: local domain: test.example.com namespace: dev nebari_version: {start_version} - """ - ) + """) with open(tmp_file.resolve(), "w") as f: yaml.dump(nebari_config, f) @@ -279,15 +275,13 @@ def test_cli_upgrade_does_nothing_on_same_version(): tmp_file = Path(tmp).resolve() / "nebari-config.yaml" assert tmp_file.exists() is False - nebari_config = yaml.safe_load( - f""" + nebari_config = yaml.safe_load(f""" project_name: test provider: local domain: test.example.com namespace: dev nebari_version: {start_version} - """ - ) + """) with open(tmp_file.resolve(), "w") as f: yaml.dump(nebari_config, f) @@ -323,8 +317,7 @@ def callback(tmp_file: Path, _result: Any): start_version, end_version, addl_args=["--attempt-fixes"], - addl_config=yaml.safe_load( - """ + addl_config=yaml.safe_load(""" security: authentication: type: custom @@ -338,8 +331,7 @@ def callback(tmp_file: Path, _result: Any): default_images: conda_store: "" dask_gateway: "" -""" - ), +"""), callback=callback, ) @@ -361,8 +353,7 @@ def test_cli_upgrade_to_0_4_0_fails_for_custom_auth_without_attempt_fixes(): tmp_file = Path(tmp).resolve() / "nebari-config.yaml" assert tmp_file.exists() is False - nebari_config = yaml.safe_load( - f""" + nebari_config = yaml.safe_load(f""" project_name: test provider: local domain: test.example.com @@ -371,8 +362,7 @@ def test_cli_upgrade_to_0_4_0_fails_for_custom_auth_without_attempt_fixes(): security: authentication: type: custom - """ - ) + """) with open(tmp_file.resolve(), "w") as f: yaml.dump(nebari_config, f) @@ -399,14 +389,12 @@ def test_cli_upgrade_to_2023_10_1_cdsdashboard_removed(monkeypatch: pytest.Monke start_version = "2023.7.2" end_version = "2023.10.1" - addl_config = yaml.safe_load( - """ + addl_config = yaml.safe_load(""" cdsdashboards: enabled: true cds_hide_user_named_servers: true cds_hide_user_dashboard_servers: false - """ - ) + """) upgraded = assert_nebari_upgrade_success( monkeypatch, @@ -473,8 +461,7 @@ def mock_input_ask(prompt, *args, **kwargs): tmp_file = Path(tmp).resolve() / "nebari-config.yaml" assert tmp_file.exists() is False - nebari_config = yaml.safe_load( - f""" + nebari_config = yaml.safe_load(f""" project_name: test provider: {provider} domain: test.example.com @@ -487,8 +474,7 @@ def mock_input_ask(prompt, *args, **kwargs): {get_provider_config_block_name(provider)}: region: {MOCK_CLOUD_REGIONS.get(provider, {})[0]} kubernetes_version: {kubernetes_configs[provider][k8s_status]} - """ - ) + """) with open(tmp_file.resolve(), "w") as f: yaml.dump(nebari_config, f) @@ -543,15 +529,13 @@ def assert_nebari_upgrade_success( # merge basic config with any test case specific values provided nebari_config = { - **yaml.safe_load( - f""" + **yaml.safe_load(f""" project_name: test provider: {provider} domain: test.example.com namespace: dev nebari_version: {start_version} - """ - ), + """), **addl_config, } diff --git a/tests/tests_unit/test_cli_validate.py b/tests/tests_unit/test_cli_validate.py index b12d3cfea0..9bae125cb2 100644 --- a/tests/tests_unit/test_cli_validate.py +++ b/tests/tests_unit/test_cli_validate.py @@ -93,15 +93,13 @@ def test_cli_validate_from_env(): tmp_file = Path(tmp).resolve() / "nebari-config.yaml" assert tmp_file.exists() is False - nebari_config = yaml.safe_load( - """ + nebari_config = yaml.safe_load(""" provider: aws project_name: test amazon_web_services: region: us-east-1 kubernetes_version: '1.19' - """ - ) + """) with open(tmp_file.resolve(), "w") as f: yaml.dump(nebari_config, f) @@ -167,12 +165,10 @@ def test_cli_validate_error_from_env( assert tmp_file.exists() is False nebari_config = { - **yaml.safe_load( - f""" + **yaml.safe_load(f""" provider: {provider} project_name: test - """ - ), + """), **addl_config, } @@ -265,12 +261,10 @@ def test_cli_validate_error_missing_cloud_env( assert tmp_file.exists() is False nebari_config = { - **yaml.safe_load( - f""" + **yaml.safe_load(f""" provider: {provider} project_name: test - """ - ), + """), **addl_config, }