lightning-sdk 0.1.58__py3-none-any.whl → 0.2.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. lightning_sdk/__init__.py +5 -3
  2. lightning_sdk/api/deployment_api.py +23 -11
  3. lightning_sdk/api/job_api.py +42 -7
  4. lightning_sdk/api/lit_container_api.py +23 -3
  5. lightning_sdk/api/mmt_api.py +46 -8
  6. lightning_sdk/api/pipeline_api.py +50 -0
  7. lightning_sdk/api/teamspace_api.py +2 -2
  8. lightning_sdk/api/utils.py +15 -5
  9. lightning_sdk/cli/ai_hub.py +30 -65
  10. lightning_sdk/cli/coloring.py +60 -0
  11. lightning_sdk/cli/configure.py +25 -40
  12. lightning_sdk/cli/connect.py +7 -20
  13. lightning_sdk/cli/create.py +83 -0
  14. lightning_sdk/cli/delete.py +72 -75
  15. lightning_sdk/cli/docker.py +22 -0
  16. lightning_sdk/cli/download.py +78 -113
  17. lightning_sdk/cli/entrypoint.py +44 -65
  18. lightning_sdk/cli/generate.py +28 -43
  19. lightning_sdk/cli/inspect.py +22 -50
  20. lightning_sdk/cli/list.py +281 -222
  21. lightning_sdk/cli/mmts_menu.py +1 -1
  22. lightning_sdk/cli/open.py +62 -0
  23. lightning_sdk/cli/run.py +430 -263
  24. lightning_sdk/cli/serve.py +128 -191
  25. lightning_sdk/cli/start.py +55 -36
  26. lightning_sdk/cli/stop.py +97 -55
  27. lightning_sdk/cli/switch.py +53 -36
  28. lightning_sdk/cli/upload.py +318 -255
  29. lightning_sdk/deployment/__init__.py +2 -0
  30. lightning_sdk/deployment/deployment.py +33 -8
  31. lightning_sdk/lightning_cloud/openapi/__init__.py +23 -0
  32. lightning_sdk/lightning_cloud/openapi/api/__init__.py +1 -0
  33. lightning_sdk/lightning_cloud/openapi/api/assistants_service_api.py +10 -6
  34. lightning_sdk/lightning_cloud/openapi/api/jobs_service_api.py +355 -4
  35. lightning_sdk/lightning_cloud/openapi/api/lit_logger_service_api.py +4 -4
  36. lightning_sdk/lightning_cloud/openapi/api/lit_registry_service_api.py +14 -2
  37. lightning_sdk/lightning_cloud/openapi/api/pipelines_service_api.py +674 -0
  38. lightning_sdk/lightning_cloud/openapi/api/storage_service_api.py +303 -4
  39. lightning_sdk/lightning_cloud/openapi/models/__init__.py +22 -0
  40. lightning_sdk/lightning_cloud/openapi/models/agents_id_body.py +17 -69
  41. lightning_sdk/lightning_cloud/openapi/models/cluster_id_capacityreservations_body.py +27 -1
  42. lightning_sdk/lightning_cloud/openapi/models/create.py +27 -1
  43. lightning_sdk/lightning_cloud/openapi/models/create_deployment_request_defines_a_spec_for_the_job_that_allows_for_autoscaling_jobs.py +53 -1
  44. lightning_sdk/lightning_cloud/openapi/models/deployments_id_body.py +105 -1
  45. lightning_sdk/lightning_cloud/openapi/models/id_visibility_body1.py +1 -27
  46. lightning_sdk/lightning_cloud/openapi/models/id_visibility_body2.py +149 -0
  47. lightning_sdk/lightning_cloud/openapi/models/org_id_memberships_body.py +27 -1
  48. lightning_sdk/lightning_cloud/openapi/models/orgs_id_body.py +157 -1
  49. lightning_sdk/lightning_cloud/openapi/models/pipelines_id_body.py +461 -0
  50. lightning_sdk/lightning_cloud/openapi/models/project_id_pipelines_body.py +227 -0
  51. lightning_sdk/lightning_cloud/openapi/models/projects_id_body.py +157 -1
  52. lightning_sdk/lightning_cloud/openapi/models/slurm_jobs_body.py +79 -1
  53. lightning_sdk/lightning_cloud/openapi/models/uploads_upload_id_body.py +1 -27
  54. lightning_sdk/lightning_cloud/openapi/models/uploads_upload_id_body1.py +175 -0
  55. lightning_sdk/lightning_cloud/openapi/models/v1_agent_job.py +79 -1
  56. lightning_sdk/lightning_cloud/openapi/models/v1_assistant.py +17 -69
  57. lightning_sdk/lightning_cloud/openapi/models/v1_capacity_block_offering.py +27 -1
  58. lightning_sdk/lightning_cloud/openapi/models/v1_cloud_space_artifact_event_type.py +1 -1
  59. lightning_sdk/lightning_cloud/openapi/models/v1_cluster_accelerator.py +131 -1
  60. lightning_sdk/lightning_cloud/openapi/models/v1_cluster_capacity_reservation.py +79 -1
  61. lightning_sdk/lightning_cloud/openapi/models/v1_cluster_security_options.py +27 -1
  62. lightning_sdk/lightning_cloud/openapi/models/v1_complete_upload_temporary_artifact_request.py +175 -0
  63. lightning_sdk/lightning_cloud/openapi/models/v1_create_deployment_request.py +461 -0
  64. lightning_sdk/lightning_cloud/openapi/models/v1_create_deployment_template_request.py +27 -1
  65. lightning_sdk/lightning_cloud/openapi/models/v1_create_job_request.py +201 -0
  66. lightning_sdk/lightning_cloud/openapi/models/v1_create_managed_endpoint_response.py +149 -0
  67. lightning_sdk/lightning_cloud/openapi/models/v1_create_multi_machine_job_request.py +253 -0
  68. lightning_sdk/lightning_cloud/openapi/models/v1_data_connection.py +27 -1
  69. lightning_sdk/lightning_cloud/openapi/models/v1_delete_pipeline_response.py +149 -0
  70. lightning_sdk/lightning_cloud/openapi/models/v1_deployment.py +105 -1
  71. lightning_sdk/lightning_cloud/openapi/models/v1_deployment_details.py +175 -0
  72. lightning_sdk/lightning_cloud/openapi/models/v1_deployment_template.py +53 -1
  73. lightning_sdk/lightning_cloud/openapi/models/v1_filestore_data_connection.py +201 -0
  74. lightning_sdk/lightning_cloud/openapi/models/v1_filesystem_job.py +53 -1
  75. lightning_sdk/lightning_cloud/openapi/models/v1_filesystem_mmt.py +53 -1
  76. lightning_sdk/lightning_cloud/openapi/models/v1_find_capacity_block_offering_response.py +29 -3
  77. lightning_sdk/lightning_cloud/openapi/models/v1_job.py +133 -3
  78. lightning_sdk/lightning_cloud/openapi/models/v1_job_artifacts_type.py +103 -0
  79. lightning_sdk/lightning_cloud/openapi/models/v1_job_spec.py +53 -1
  80. lightning_sdk/lightning_cloud/openapi/models/v1_job_timing.py +27 -1
  81. lightning_sdk/lightning_cloud/openapi/models/v1_list_pipelines_response.py +123 -0
  82. lightning_sdk/lightning_cloud/openapi/models/v1_lit_registry_artifact.py +27 -1
  83. lightning_sdk/lightning_cloud/openapi/models/v1_lit_repository.py +29 -1
  84. lightning_sdk/lightning_cloud/openapi/models/v1_managed_model.py +27 -1
  85. lightning_sdk/lightning_cloud/openapi/models/v1_multi_machine_job.py +27 -1
  86. lightning_sdk/lightning_cloud/openapi/models/v1_multi_machine_job_state.py +2 -0
  87. lightning_sdk/lightning_cloud/openapi/models/v1_organization.py +209 -1
  88. lightning_sdk/lightning_cloud/openapi/models/v1_pipeline.py +513 -0
  89. lightning_sdk/lightning_cloud/openapi/models/v1_pipeline_schedule.py +149 -0
  90. lightning_sdk/lightning_cloud/openapi/models/v1_pipeline_step.py +253 -0
  91. lightning_sdk/lightning_cloud/openapi/models/v1_pipeline_step_status.py +331 -0
  92. lightning_sdk/lightning_cloud/openapi/models/v1_pipeline_step_type.py +104 -0
  93. lightning_sdk/lightning_cloud/openapi/models/v1_project_settings.py +157 -1
  94. lightning_sdk/lightning_cloud/openapi/models/v1_restart_timing.py +27 -1
  95. lightning_sdk/lightning_cloud/openapi/models/v1_rule_resource.py +1 -0
  96. lightning_sdk/lightning_cloud/openapi/models/v1_shared_filesystem.py +201 -0
  97. lightning_sdk/lightning_cloud/openapi/models/v1_slurm_job.py +27 -1
  98. lightning_sdk/lightning_cloud/openapi/models/v1_update_job_visibility_response.py +97 -0
  99. lightning_sdk/lightning_cloud/openapi/models/v1_upload_temporary_artifact_request.py +123 -0
  100. lightning_sdk/lightning_cloud/openapi/models/v1_user_features.py +95 -355
  101. lightning_sdk/lightning_cloud/openapi/models/validate.py +27 -1
  102. lightning_sdk/lightning_cloud/rest_client.py +4 -2
  103. lightning_sdk/machine.py +25 -1
  104. lightning_sdk/models.py +18 -12
  105. lightning_sdk/pipeline/__init__.py +4 -0
  106. lightning_sdk/pipeline/pipeline.py +109 -0
  107. lightning_sdk/pipeline/types.py +268 -0
  108. lightning_sdk/pipeline/utils.py +69 -0
  109. lightning_sdk/plugin.py +9 -10
  110. lightning_sdk/serve.py +134 -0
  111. lightning_sdk/services/utilities.py +2 -2
  112. lightning_sdk/studio.py +5 -1
  113. lightning_sdk/teamspace.py +1 -1
  114. lightning_sdk/utils/resolve.py +12 -1
  115. {lightning_sdk-0.1.58.dist-info → lightning_sdk-0.2.1.dist-info}/METADATA +6 -8
  116. {lightning_sdk-0.1.58.dist-info → lightning_sdk-0.2.1.dist-info}/RECORD +120 -88
  117. lightning_sdk/cli/legacy.py +0 -135
  118. {lightning_sdk-0.1.58.dist-info → lightning_sdk-0.2.1.dist-info}/LICENSE +0 -0
  119. {lightning_sdk-0.1.58.dist-info → lightning_sdk-0.2.1.dist-info}/WHEEL +0 -0
  120. {lightning_sdk-0.1.58.dist-info → lightning_sdk-0.2.1.dist-info}/entry_points.txt +0 -0
  121. {lightning_sdk-0.1.58.dist-info → lightning_sdk-0.2.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,60 @@
1
+ from typing import Optional, Sequence, Tuple
2
+
3
+ from click.formatting import HelpFormatter, term_len, wrap_text
4
+ from click.termui import style
5
+
6
+
7
+ class CustomHelpFormatter(HelpFormatter):
8
+ _primary = "magenta"
9
+ _secondary = "cyan"
10
+
11
+ def write_heading(self, heading: str) -> None:
12
+ # Style the heading (command name) in cyan
13
+ return super().write_heading(style(heading, fg=self._primary, bold=True))
14
+
15
+ def write_usage(self, prog: str, args: str = "", prefix: Optional[str] = None) -> None:
16
+ if prefix is None:
17
+ prefix = "Usage: "
18
+
19
+ styled_prefix = style(prefix, fg=self._primary, bold=True)
20
+ styled_prog = style(prog, fg=self._secondary, bold=True)
21
+ styled_args = style(args, fg=self._secondary, bold=True)
22
+
23
+ # this is required because otherwise the super() call would include the special characters for coloring in the
24
+ # width and indent computation leading to wrong results since these characters won't be displayed in the end.
25
+ usage_prefix = f"{prefix:>{self.current_indent}}{prog} "
26
+ styled_usage_prefix = f"{styled_prefix:>{self.current_indent}}{styled_prog} "
27
+ text_width = self.width - self.current_indent
28
+
29
+ if text_width >= (term_len(usage_prefix) + 20):
30
+ # The arguments will fit to the right of the prefix.
31
+ self.write(styled_usage_prefix)
32
+ indent = " " * term_len(usage_prefix)
33
+ self.write(
34
+ wrap_text(
35
+ styled_args,
36
+ text_width,
37
+ initial_indent="",
38
+ subsequent_indent=indent,
39
+ )
40
+ )
41
+ else:
42
+ # The prefix is too long, put the arguments on the next line.
43
+ self.write(styled_usage_prefix)
44
+ self.write("\n")
45
+ indent = " " * (max(self.current_indent, term_len(prefix)) + 4)
46
+ self.write(wrap_text(styled_args, text_width, initial_indent=indent, subsequent_indent=indent))
47
+
48
+ self.write("\n")
49
+
50
+ def write_dl(
51
+ self,
52
+ rows: Sequence[Tuple[str, str]],
53
+ col_max: int = 30,
54
+ col_spacing: int = 2,
55
+ ) -> None:
56
+ new_rows = []
57
+ for row in rows:
58
+ new_row = (style(row[0], fg=self._secondary, bold=True), row[1])
59
+ new_rows.append(new_row)
60
+ super().write_dl(new_rows, col_max=col_max, col_spacing=col_spacing)
@@ -12,51 +12,36 @@ from lightning_sdk.cli.studios_menu import _StudiosMenu
12
12
  from lightning_sdk.lightning_cloud.login import Auth
13
13
 
14
14
 
15
- class _Configure(_StudiosMenu):
16
- """Configure lightning products."""
17
-
18
- def ssh(self, name: Optional[str] = None, teamspace: Optional[str] = None, overwrite: bool = False) -> None:
19
- """Get SSH config entry for a studio.
20
-
21
- Args:
22
- name: The name of the studio to obtain SSH config.
23
- If not specified, tries to infer from the environment (e.g. when run from within a Studio.)
24
- teamspace: The teamspace the studio is part of. Should be of format <OWNER>/<TEAMSPACE_NAME>.
25
- If not specified, tries to infer from the environment (e.g. when run from within a Studio.)
26
- overwrite: Whether to overwrite the SSH key and config if they already exist.
27
- """
28
- ssh(name=name, teamspace=teamspace, overwrite=overwrite)
29
-
30
-
31
15
  @click.group(name="configure")
32
16
  def configure() -> None:
33
17
  """Configure access to resources on the Lightning AI platform."""
34
18
 
35
19
 
36
- # @configure.command(name="ssh")
37
- # @click.option(
38
- # "--name",
39
- # default=None,
40
- # help=(
41
- # "The name of the studio to obtain SSH config. "
42
- # "If not specified, tries to infer from the environment (e.g. when run from within a Studio.)"
43
- # ),
44
- # )
45
- # @click.option(
46
- # "--teamspace",
47
- # default=None,
48
- # help=(
49
- # "The teamspace the studio is part of. "
50
- # "Should be of format <OWNER>/<TEAMSPACE_NAME>. "
51
- # "If not specified, tries to infer from the environment (e.g. when run from within a Studio.)"
52
- # ),
53
- # )
54
- # @click.option(
55
- # "--overwrite",
56
- # is_flag=True,
57
- # flag_value=True,
58
- # help="Whether to overwrite the SSH key and config if they already exist.",
59
- # )
20
+ @configure.command(name="ssh")
21
+ @click.option(
22
+ "--name",
23
+ default=None,
24
+ help=(
25
+ "The name of the studio to obtain SSH config. "
26
+ "If not specified, tries to infer from the environment (e.g. when run from within a Studio.)"
27
+ ),
28
+ )
29
+ @click.option(
30
+ "--teamspace",
31
+ default=None,
32
+ help=(
33
+ "The teamspace the studio is part of. "
34
+ "Should be of format <OWNER>/<TEAMSPACE_NAME>. "
35
+ "If not specified, tries to infer from the environment (e.g. when run from within a Studio.)"
36
+ ),
37
+ )
38
+ @click.option(
39
+ "--overwrite",
40
+ is_flag=True,
41
+ flag_value=True,
42
+ default=False,
43
+ help="Whether to overwrite the SSH key and config if they already exist.",
44
+ )
60
45
  def ssh(name: Optional[str] = None, teamspace: Optional[str] = None, overwrite: bool = False) -> None:
61
46
  """Get SSH config entry for a studio."""
62
47
  auth = Auth()
@@ -8,31 +8,18 @@ from lightning_sdk.cli.configure import ssh as configure_ssh
8
8
  from lightning_sdk.cli.studios_menu import _StudiosMenu
9
9
 
10
10
 
11
- class _Connect:
12
- """Connect to lightning products."""
13
-
14
- def studio(self, name: Optional[str] = None, teamspace: Optional[str] = None) -> None:
15
- """Connect to a studio via SSH.
16
-
17
- Args:
18
- name: The name of the studio to connect to.
19
- teamspace: The teamspace the studio is part of. Should be of format <OWNER>/<TEAMSPACE_NAME>.
20
- """
21
- return studio(name=name, teamspace=teamspace)
22
-
23
-
24
11
  @click.group(name="connect")
25
12
  def connect() -> None:
26
13
  """Connect to lightning products."""
27
14
 
28
15
 
29
- # @connect.command(name="studio")
30
- # @click.option("--name", default=None, help="The name of the studio to connect to.")
31
- # @click.option(
32
- # "--teamspace",
33
- # default=None,
34
- # help="The teamspace the studio is part of. Should be of format <OWNER>/<TEAMSPACE_NAME>.",
35
- # )
16
+ @connect.command(name="studio")
17
+ @click.option("--name", default=None, help="The name of the studio to connect to.")
18
+ @click.option(
19
+ "--teamspace",
20
+ default=None,
21
+ help="The teamspace the studio is part of. Should be of format <OWNER>/<TEAMSPACE_NAME>.",
22
+ )
36
23
  def studio(name: Optional[str], teamspace: Optional[str]) -> None:
37
24
  """Connect to a studio via SSH."""
38
25
  configure_ssh(name=name, teamspace=teamspace, overwrite=False)
@@ -0,0 +1,83 @@
1
+ import random
2
+ import string
3
+ from contextlib import suppress
4
+ from typing import Optional
5
+
6
+ import click
7
+ from rich.console import Console
8
+
9
+ from lightning_sdk import Machine, Studio
10
+ from lightning_sdk.cli.teamspace_menu import _TeamspacesMenu
11
+
12
+ _MACHINE_VALUES = tuple([machine.name for machine in Machine.__dict__.values() if isinstance(machine, Machine)])
13
+
14
+
15
+ @click.group("create")
16
+ def create() -> None:
17
+ """Create new resources on the Lightning AI platform."""
18
+
19
+
20
+ @create.command("studio")
21
+ @click.argument("name")
22
+ @click.option(
23
+ "--teamspace",
24
+ default=None,
25
+ help=(
26
+ "The teamspace the studio will be part of. "
27
+ "Should be of format <OWNER>/<TEAMSPACE_NAME>. "
28
+ "If not specified, tries to infer from the environment (e.g. when run from within a Studio.)"
29
+ ),
30
+ )
31
+ @click.option(
32
+ "--start",
33
+ default=None,
34
+ type=click.Choice(_MACHINE_VALUES),
35
+ help="If specified, will start the created studio on the given machine.",
36
+ )
37
+ @click.option(
38
+ "--cloud-account",
39
+ "--cloud_account",
40
+ default=None,
41
+ help=(
42
+ "The cloud account to create the studio on. "
43
+ "If not specified, will try to infer from the environment (e.g. when run from within a Studio.) "
44
+ "or fall back to the teamspace default."
45
+ ),
46
+ )
47
+ def studio(
48
+ name: str, teamspace: Optional[str] = None, start: Optional[str] = None, cloud_account: Optional[str] = None
49
+ ) -> None:
50
+ """Create a new studio on the Lightning AI platform.
51
+
52
+ Example:
53
+ lightning create studio NAME
54
+
55
+ NAME: the name of the studio to create. If already present within teamspace, will add a random suffix.
56
+ """
57
+ menu = _TeamspacesMenu()
58
+ teamspace_resolved = menu._resolve_teamspace(teamspace)
59
+
60
+ # default cloud account to current studios cloud account if run from studio
61
+ # else it will fall back to teamspace default in the backend
62
+ if cloud_account is None:
63
+ with suppress(ValueError):
64
+ s = Studio()
65
+ if s.teamspace.name == teamspace_resolved.name and s.teamspace.owner.name == teamspace_resolved.owner.name:
66
+ cloud_account = s.cloud_account
67
+
68
+ console = Console()
69
+
70
+ with suppress(ValueError):
71
+ Studio(name, teamspace=teamspace_resolved, create_ok=False)
72
+ new_name = name + "-" + "".join(random.choices(string.ascii_lowercase + string.digits, k=4))
73
+ console.print(f"Studio with name {name} already exists. Using {new_name} instead.")
74
+ name = new_name
75
+
76
+ studio = Studio(name=name, teamspace=teamspace_resolved, cloud_account=cloud_account, create_ok=True)
77
+
78
+ console.print(f"Created Studio {studio.name}.")
79
+
80
+ if start is not None:
81
+ start_machine = getattr(Machine, start, start)
82
+ studio.start(start_machine)
83
+ console.print(f"Started Studio {studio.name} on machine {start}")
@@ -6,70 +6,27 @@ from rich.console import Console
6
6
  from lightning_sdk.cli.exceptions import StudioCliError
7
7
  from lightning_sdk.cli.job_and_mmt_action import _JobAndMMTAction
8
8
  from lightning_sdk.cli.teamspace_menu import _TeamspacesMenu
9
+ from lightning_sdk.lightning_cloud.openapi.rest import ApiException
9
10
  from lightning_sdk.lit_container import LitContainer
10
11
  from lightning_sdk.studio import Studio
11
12
 
12
13
 
13
- class _Delete(_JobAndMMTAction, _TeamspacesMenu):
14
- """Delete resources on the Lightning AI platform."""
15
-
16
- def container(self, container: str, teamspace: Optional[str] = None) -> None:
17
- """Delete a docker container.
18
-
19
- Args:
20
- container: The name of the container to delete.
21
- teamspace: The teamspace to delete the container from. Should be specified as {owner}/{name}
22
- If not provided, can be selected in an interactive menu.
23
- """
24
- delete_container(container=container, teamspace=teamspace)
25
-
26
- def job(self, name: Optional[str] = None, teamspace: Optional[str] = None) -> None:
27
- """Delete a job.
28
-
29
- Args:
30
- name: the name of the job. If not specified can be selected interactively.
31
- teamspace: the name of the teamspace the job lives in.
32
- Should be specified as {teamspace_owner}/{teamspace_name} (e.g my-org/my-teamspace).
33
- If not specified can be selected interactively.
34
-
35
- """
36
- job(name=name, teamspace=teamspace)
37
-
38
- def mmt(self, name: Optional[str] = None, teamspace: Optional[str] = None) -> None:
39
- """Delete a multi-machine job.
40
-
41
- Args:
42
- name: the name of the job. If not specified can be selected interactively.
43
- teamspace: the name of the teamspace the job lives in.
44
- Should be specified as {teamspace_owner}/{teamspace_name} (e.g my-org/my-teamspace).
45
- If not specified can be selected interactively.
46
-
47
- """
48
- mmt(name=name, teamspace=teamspace)
49
-
50
- def studio(self, name: Optional[str] = None, teamspace: Optional[str] = None) -> None:
51
- """Delete an existing studio.
52
-
53
- Args:
54
- name: The name of the studio to delete.
55
- If not specified, tries to infer from the environment (e.g. when run from within a Studio.)
56
- Note: This could delete your current studio if run without arguments.
57
- teamspace: The teamspace the studio is part of. Should be of format <OWNER>/<TEAMSPACE_NAME>.
58
- If not specified, tries to infer from the environment (e.g. when run from within a Studio.)
59
- """
60
- studio(name=name, teamspace=teamspace)
61
-
62
-
63
14
  @click.group()
64
15
  def delete() -> None:
65
16
  """Delete resources on the Lightning AI platform."""
66
17
 
67
18
 
68
- # @delete.command(name="container")
69
- # @click.option("--container", help="The name of the container to delete.")
70
- # @click.option("--teamspace", default=None, help=("The teamspace to delete the container from. "
71
- # "Should be specified as {owner}/{name} "
72
- # "If not provided, can be selected in an interactive menu."),)
19
+ @delete.command(name="container")
20
+ @click.argument("container")
21
+ @click.option(
22
+ "--teamspace",
23
+ default=None,
24
+ help=(
25
+ "The teamspace to delete the container from. "
26
+ "Should be specified as {owner}/{name} "
27
+ "If not provided, can be selected in an interactive menu."
28
+ ),
29
+ )
73
30
  def delete_container(container: str, teamspace: Optional[str] = None) -> None:
74
31
  """Delete the docker container CONTAINER."""
75
32
  api = LitContainer()
@@ -84,13 +41,27 @@ def delete_container(container: str, teamspace: Optional[str] = None) -> None:
84
41
  ) from None
85
42
 
86
43
 
87
- # @delete.command(name="job")
88
- # @click.option("--name", help="The name of the job to delete.")
89
- # @click.option("--teamspace", default=None, help=("The teamspace to delete the job from. "
90
- # "Should be specified as {owner}/{name} "
91
- # "If not provided, can be selected in an interactive menu."),)
44
+ @delete.command(name="job")
45
+ @click.argument(
46
+ "name",
47
+ )
48
+ @click.option(
49
+ "--teamspace",
50
+ default=None,
51
+ help=(
52
+ "The teamspace to delete the job from. "
53
+ "Should be specified as {owner}/{name} "
54
+ "If not provided, can be selected in an interactive menu."
55
+ ),
56
+ )
92
57
  def job(name: Optional[str] = None, teamspace: Optional[str] = None) -> None:
93
- """Delete a job."""
58
+ """Delete a job.
59
+
60
+ Example:
61
+ lightning delete job NAME
62
+
63
+ NAME: the name of the job to delete.
64
+ """
94
65
  menu = _JobAndMMTAction()
95
66
  job = menu.job(name=name, teamspace=teamspace)
96
67
 
@@ -98,13 +69,27 @@ def job(name: Optional[str] = None, teamspace: Optional[str] = None) -> None:
98
69
  Console().print(f"Successfully deleted {job.name}!")
99
70
 
100
71
 
101
- # @delete.command(name="mmt")
102
- # @click.option("--name", help="The name of the multi-machine job to delete.")
103
- # @click.option("--teamspace", default=None, help=("The teamspace to delete the job from. "
104
- # "Should be specified as {owner}/{name} "
105
- # "If not provided, can be selected in an interactive menu."),)
72
+ @delete.command(name="mmt")
73
+ @click.argument(
74
+ "name",
75
+ )
76
+ @click.option(
77
+ "--teamspace",
78
+ default=None,
79
+ help=(
80
+ "The teamspace to delete the job from. "
81
+ "Should be specified as {owner}/{name} "
82
+ "If not provided, can be selected in an interactive menu."
83
+ ),
84
+ )
106
85
  def mmt(name: Optional[str] = None, teamspace: Optional[str] = None) -> None:
107
- """Delete a multi-machine job."""
86
+ """Delete a multi-machine job.
87
+
88
+ Example:
89
+ lightning delete mmt NAME
90
+
91
+ NAME: the name of the multi-machine job to delete.
92
+ """
108
93
  menu = _JobAndMMTAction()
109
94
  mmt = menu.mmt(name=name, teamspace=teamspace)
110
95
 
@@ -112,13 +97,25 @@ def mmt(name: Optional[str] = None, teamspace: Optional[str] = None) -> None:
112
97
  Console().print(f"Successfully deleted {mmt.name}!")
113
98
 
114
99
 
115
- # @delete.command(name="studio")
116
- # @click.option("--name", help="The name of the studio to delete.")
117
- # @click.option("--teamspace", default=None, help=("The teamspace to delete the studio from. "
118
- # "Should be specified as {owner}/{name} "
119
- # "If not provided, can be selected in an interactive menu."),)
120
- def studio(name: Optional[str] = None, teamspace: Optional[str] = None) -> None:
121
- """Delete an existing studio."""
100
+ @delete.command(name="studio")
101
+ @click.argument("name")
102
+ @click.option(
103
+ "--teamspace",
104
+ default=None,
105
+ help=(
106
+ "The teamspace to delete the studio from. "
107
+ "Should be specified as {owner}/{name} "
108
+ "If not provided, can be selected in an interactive menu."
109
+ ),
110
+ )
111
+ def studio(name: str, teamspace: Optional[str] = None) -> None:
112
+ """Delete an existing studio.
113
+
114
+ Example:
115
+ lightning delete studio NAME
116
+
117
+ NAME: the name of the studio to delete
118
+ """
122
119
  if teamspace is not None:
123
120
  ts_splits = teamspace.split("/")
124
121
  if len(ts_splits) != 2:
@@ -129,7 +126,7 @@ def studio(name: Optional[str] = None, teamspace: Optional[str] = None) -> None:
129
126
 
130
127
  try:
131
128
  studio = Studio(name=name, teamspace=teamspace, org=owner, user=None, create_ok=False)
132
- except (RuntimeError, ValueError):
129
+ except (RuntimeError, ValueError, ApiException):
133
130
  studio = Studio(name=name, teamspace=teamspace, org=None, user=owner, create_ok=False)
134
131
 
135
132
  studio.delete()
@@ -0,0 +1,22 @@
1
+ import click
2
+
3
+ from lightning_sdk.serve import _LitServeDeployer
4
+
5
+
6
+ @click.group(name="dockerize")
7
+ def dockerize() -> None:
8
+ """Generate a Dockerfile for a LitServe model."""
9
+
10
+
11
+ @dockerize.command("api")
12
+ @click.argument("server-filename")
13
+ @click.option("--port", type=int, default=8000, help="Port to expose in the Docker container.")
14
+ @click.option("--gpu", is_flag=True, default=False, flag_value=True, help="Use a GPU-enabled Docker image.")
15
+ @click.option("--tag", default="litserve-model", help="Docker image tag to use in examples.")
16
+ def api(server_filename: str, port: int = 8000, gpu: bool = False, tag: str = "litserve-model") -> None:
17
+ """Generate a Dockerfile for the given server code."""
18
+ _api(server_filename=server_filename, port=port, gpu=gpu, tag=tag)
19
+
20
+
21
+ def _api(server_filename: str, port: int = 8000, gpu: bool = False, tag: str = "litserve-model") -> str:
22
+ return _LitServeDeployer().dockerize_api(server_filename=server_filename, port=port, gpu=gpu, tag=tag)