From c83142347cf161bfaf2ec2bdce6a50f7dd91f219 Mon Sep 17 00:00:00 2001 From: Ishu Singh Date: Tue, 1 Oct 2024 21:44:34 +0530 Subject: [PATCH 1/5] Fix Handle KeyboardInterrupt in CLI when getting run plan #1626 --- src/dstack/_internal/cli/commands/apply.py | 50 ++++++++++++---------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/src/dstack/_internal/cli/commands/apply.py b/src/dstack/_internal/cli/commands/apply.py index 674f1f7f1e..5cbd598e36 100644 --- a/src/dstack/_internal/cli/commands/apply.py +++ b/src/dstack/_internal/cli/commands/apply.py @@ -50,27 +50,31 @@ def _register(self): ) def _command(self, args: argparse.Namespace): - if args.help is not NOTSET: - if args.help is not None: - configurator_class = get_apply_configurator_class( - ApplyConfigurationType(args.help) - ) - else: - configurator_class = BaseApplyConfigurator - configurator_class.register_args(self._parser) - self._parser.print_help() - return + try: + if args.help is not NOTSET: + if args.help is not None: + configurator_class = get_apply_configurator_class( + ApplyConfigurationType(args.help) + ) + else: + configurator_class = BaseApplyConfigurator + configurator_class.register_args(self._parser) + self._parser.print_help() + return - super()._command(args) - configuration_path, configuration = load_apply_configuration(args.configuration_file) - configurator_class = get_apply_configurator_class(configuration.type) - configurator = configurator_class(api_client=self.api) - configurator_parser = configurator.get_parser() - known, unknown = configurator_parser.parse_known_args(args.unknown) - configurator.apply_configuration( - conf=configuration, - configuration_path=configuration_path, - command_args=args, - configurator_args=known, - unknown_args=unknown, - ) + super()._command(args) + configuration_path, configuration = load_apply_configuration(args.configuration_file) + configurator_class = get_apply_configurator_class(configuration.type) + configurator = configurator_class(api_client=self.api) + configurator_parser = configurator.get_parser() + known, unknown = configurator_parser.parse_known_args(args.unknown) + configurator.apply_configuration( + conf=configuration, + configuration_path=configuration_path, + command_args=args, + configurator_args=known, + unknown_args=unknown, + ) + except KeyboardInterrupt: + print("\nOperation interrupted by user. Exiting...") + exit(0) From 9e4bb238f35a7b75dd40030031cd0f65dd0346c4 Mon Sep 17 00:00:00 2001 From: Ishu Singh Date: Tue, 1 Oct 2024 22:30:41 +0530 Subject: [PATCH 2/5] Allow using all existing regions unless a specific set of regions is configured #1573 --- .../server/services/backends/configurators/runpod.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dstack/_internal/server/services/backends/configurators/runpod.py b/src/dstack/_internal/server/services/backends/configurators/runpod.py index 953c49b6b4..cc04dfa8e0 100644 --- a/src/dstack/_internal/server/services/backends/configurators/runpod.py +++ b/src/dstack/_internal/server/services/backends/configurators/runpod.py @@ -45,7 +45,7 @@ def get_config_values(self, config: RunpodConfigInfoWithCredsPartial) -> RunpodC return config_values self._validate_runpod_api_key(config.creds.api_key) config_values.regions = self._get_regions_element( - selected=config.regions or [DEFAULT_REGION] + selected=config.regions or REGIONS # Use all regions by default ) return config_values @@ -53,7 +53,7 @@ def create_backend( self, project: ProjectModel, config: RunpodConfigInfoWithCreds ) -> BackendModel: if config.regions is None: - config.regions = REGIONS + config.regions = REGIONS # Use all regions by default return BackendModel( project_id=project.id, type=self.TYPE.value, From 0e6a9383d8e6813f2540a81a87aca32a1428039c Mon Sep 17 00:00:00 2001 From: Ishu Date: Tue, 1 Oct 2024 23:14:57 +0530 Subject: [PATCH 3/5] Delete src/dstack/_internal/cli/commands/apply.py --- src/dstack/_internal/cli/commands/apply.py | 80 ---------------------- 1 file changed, 80 deletions(-) delete mode 100644 src/dstack/_internal/cli/commands/apply.py diff --git a/src/dstack/_internal/cli/commands/apply.py b/src/dstack/_internal/cli/commands/apply.py deleted file mode 100644 index 5cbd598e36..0000000000 --- a/src/dstack/_internal/cli/commands/apply.py +++ /dev/null @@ -1,80 +0,0 @@ -import argparse -from pathlib import Path - -from dstack._internal.cli.commands import APIBaseCommand -from dstack._internal.cli.services.configurators import ( - get_apply_configurator_class, - load_apply_configuration, -) -from dstack._internal.cli.services.configurators.base import BaseApplyConfigurator -from dstack._internal.core.models.configurations import ApplyConfigurationType - -NOTSET = object() - - -class ApplyCommand(APIBaseCommand): - NAME = "apply" - DESCRIPTION = "Apply a configuration" - DEFAULT_HELP = False - - def _register(self): - super()._register() - self._parser.add_argument( - "-h", - "--help", - nargs="?", - type=ApplyConfigurationType, - default=NOTSET, - help="Show this help message and exit.", - dest="help", - metavar="TYPE", - ) - self._parser.add_argument( - "-f", - "--file", - type=Path, - metavar="FILE", - help="The path to the configuration file. Defaults to [code]$PWD/.dstack.yml[/]", - dest="configuration_file", - ) - self._parser.add_argument( - "--force", - help="Force apply when no changes detected", - action="store_true", - ) - self._parser.add_argument( - "-y", - "--yes", - help="Do not ask for confirmation", - action="store_true", - ) - - def _command(self, args: argparse.Namespace): - try: - if args.help is not NOTSET: - if args.help is not None: - configurator_class = get_apply_configurator_class( - ApplyConfigurationType(args.help) - ) - else: - configurator_class = BaseApplyConfigurator - configurator_class.register_args(self._parser) - self._parser.print_help() - return - - super()._command(args) - configuration_path, configuration = load_apply_configuration(args.configuration_file) - configurator_class = get_apply_configurator_class(configuration.type) - configurator = configurator_class(api_client=self.api) - configurator_parser = configurator.get_parser() - known, unknown = configurator_parser.parse_known_args(args.unknown) - configurator.apply_configuration( - conf=configuration, - configuration_path=configuration_path, - command_args=args, - configurator_args=known, - unknown_args=unknown, - ) - except KeyboardInterrupt: - print("\nOperation interrupted by user. Exiting...") - exit(0) From 1cd4641cc2a4a91f7e28ab502e7906e0ea242b96 Mon Sep 17 00:00:00 2001 From: Ishu Singh Date: Tue, 1 Oct 2024 23:18:00 +0530 Subject: [PATCH 4/5] Revert "Delete src/dstack/_internal/cli/commands/apply.py" This reverts commit 0e6a9383d8e6813f2540a81a87aca32a1428039c. --- src/dstack/_internal/cli/commands/apply.py | 80 ++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 src/dstack/_internal/cli/commands/apply.py diff --git a/src/dstack/_internal/cli/commands/apply.py b/src/dstack/_internal/cli/commands/apply.py new file mode 100644 index 0000000000..5cbd598e36 --- /dev/null +++ b/src/dstack/_internal/cli/commands/apply.py @@ -0,0 +1,80 @@ +import argparse +from pathlib import Path + +from dstack._internal.cli.commands import APIBaseCommand +from dstack._internal.cli.services.configurators import ( + get_apply_configurator_class, + load_apply_configuration, +) +from dstack._internal.cli.services.configurators.base import BaseApplyConfigurator +from dstack._internal.core.models.configurations import ApplyConfigurationType + +NOTSET = object() + + +class ApplyCommand(APIBaseCommand): + NAME = "apply" + DESCRIPTION = "Apply a configuration" + DEFAULT_HELP = False + + def _register(self): + super()._register() + self._parser.add_argument( + "-h", + "--help", + nargs="?", + type=ApplyConfigurationType, + default=NOTSET, + help="Show this help message and exit.", + dest="help", + metavar="TYPE", + ) + self._parser.add_argument( + "-f", + "--file", + type=Path, + metavar="FILE", + help="The path to the configuration file. Defaults to [code]$PWD/.dstack.yml[/]", + dest="configuration_file", + ) + self._parser.add_argument( + "--force", + help="Force apply when no changes detected", + action="store_true", + ) + self._parser.add_argument( + "-y", + "--yes", + help="Do not ask for confirmation", + action="store_true", + ) + + def _command(self, args: argparse.Namespace): + try: + if args.help is not NOTSET: + if args.help is not None: + configurator_class = get_apply_configurator_class( + ApplyConfigurationType(args.help) + ) + else: + configurator_class = BaseApplyConfigurator + configurator_class.register_args(self._parser) + self._parser.print_help() + return + + super()._command(args) + configuration_path, configuration = load_apply_configuration(args.configuration_file) + configurator_class = get_apply_configurator_class(configuration.type) + configurator = configurator_class(api_client=self.api) + configurator_parser = configurator.get_parser() + known, unknown = configurator_parser.parse_known_args(args.unknown) + configurator.apply_configuration( + conf=configuration, + configuration_path=configuration_path, + command_args=args, + configurator_args=known, + unknown_args=unknown, + ) + except KeyboardInterrupt: + print("\nOperation interrupted by user. Exiting...") + exit(0) From 6bc2fcae27cf136c4cc0bf49eb9c0fb9d93cf444 Mon Sep 17 00:00:00 2001 From: Ishu Singh Date: Wed, 2 Oct 2024 14:59:51 +0530 Subject: [PATCH 5/5] Fix use all available runpod regions by default --- .../server/services/backends/configurators/runpod.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/dstack/_internal/server/services/backends/configurators/runpod.py b/src/dstack/_internal/server/services/backends/configurators/runpod.py index cc04dfa8e0..ada61bc43d 100644 --- a/src/dstack/_internal/server/services/backends/configurators/runpod.py +++ b/src/dstack/_internal/server/services/backends/configurators/runpod.py @@ -24,13 +24,19 @@ REGIONS = [ "CA-MTL-1", + "CA-MTL-2", + "CA-MTL-3", "EU-NL-1", "EU-RO-1", "EU-SE-1", "EUR-IS-1", "EUR-IS-2", - "EUR-NO-1", + "US-CA-1", + "US-GA-1", + "US-GA-2", + "US-KS-2", "US-OR-1", + "US-TX-3", ] DEFAULT_REGION = "CA-MTL-1" @@ -45,7 +51,7 @@ def get_config_values(self, config: RunpodConfigInfoWithCredsPartial) -> RunpodC return config_values self._validate_runpod_api_key(config.creds.api_key) config_values.regions = self._get_regions_element( - selected=config.regions or REGIONS # Use all regions by default + selected=config.regions or [DEFAULT_REGION] ) return config_values @@ -53,7 +59,7 @@ def create_backend( self, project: ProjectModel, config: RunpodConfigInfoWithCreds ) -> BackendModel: if config.regions is None: - config.regions = REGIONS # Use all regions by default + config.regions = REGIONS return BackendModel( project_id=project.id, type=self.TYPE.value,