Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,14 @@ module = [
"lightning.app.api.http_methods",
"lightning.app.api.request_types",
"lightning.app.cli.commands.app_commands",
"lightning.app.cli.commands.connection",
"lightning.app.cli.commands.lightning_cli",
"lightning.app.cli.commands.cmd_install",
"lightning.app.cli.connect.app",
"lightning.app.cli.commands.pwd",
"lightning.app.cli.commands.ls",
"lightning.app.cli.commands.cp",
"lightning.app.cli.commands.cd",
"lightning.app.cli.connect.data",
"lightning.app.cli.cmd_install",
"lightning.app.components.database.client",
"lightning.app.components.database.server",
Expand Down
2 changes: 1 addition & 1 deletion requirements/app/base.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
lightning-cloud>=0.5.22
lightning-cloud>=0.5.24
packaging
typing-extensions>=4.0.0, <=4.4.0
deepdiff>=5.7.0, <6.2.4
Expand Down
6 changes: 6 additions & 0 deletions src/lightning/app/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
* `pwd`: Return the current folder in your Cloud Platform Filesystem
* `cp`: Copy files between your Cloud Platform Filesystem and local filesystem

- Added `lightning connect data` to register data connection to s3 buckets ([#16670](https://github.com/Lightning-AI/lightning/pull/16670))


### Changed

- Changed the default `LightningClient(retry=False)` to `retry=True` ([#16382](https://github.com/Lightning-AI/lightning/pull/16382))
Expand All @@ -33,6 +36,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
- Renamed `lightning.app.components.LiteMultiNode` to `lightning.app.components.FabricMultiNode` ([#16505](https://github.com/Lightning-AI/lightning/pull/16505))


- Changed the command `lightning connect` to `lightning connect app` for consistency ([#16670](https://github.com/Lightning-AI/lightning/pull/16670))


### Deprecated

-
Expand Down
2 changes: 1 addition & 1 deletion src/lightning/app/cli/commands/app_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

import requests

from lightning.app.cli.commands.connection import (
from lightning.app.cli.connect.app import (
_clean_lightning_connection,
_install_missing_requirements,
_resolve_command_path,
Expand Down
2 changes: 1 addition & 1 deletion src/lightning/app/cli/commands/cd.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from rich.text import Text

from lightning.app.cli.commands import ls
from lightning.app.cli.commands.connection import _LIGHTNING_CONNECTION_FOLDER
from lightning.app.cli.connect.app import _LIGHTNING_CONNECTION_FOLDER
from lightning.app.utilities.app_helpers import Logger
from lightning.app.utilities.cli_helpers import _error_and_exit

Expand Down
5 changes: 2 additions & 3 deletions src/lightning/app/cli/commands/ls.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from rich.spinner import Spinner
from rich.text import Text

from lightning.app.cli.commands.connection import _LIGHTNING_CONNECTION_FOLDER
from lightning.app.cli.connect.app import _LIGHTNING_CONNECTION_FOLDER
from lightning.app.utilities.app_helpers import Logger
from lightning.app.utilities.cli_helpers import _error_and_exit
from lightning.app.utilities.network import LightningClient
Expand All @@ -44,8 +44,7 @@ def ls(path: Optional[str] = None, print: bool = True, use_live: bool = True) ->
from lightning.app.cli.commands.cd import _CD_FILE

if sys.platform == "win32":
print("`ls` isn't supported on windows. Open an issue on Github.")
sys.exit(0)
_error_and_exit("`ls` isn't supported on windows. Open an issue on Github.")

root = "/"

Expand Down
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@


@click.argument("app_name_or_id", required=True)
def connect(app_name_or_id: str):
def connect_app(app_name_or_id: str):
"""Connect your local terminal to a running lightning app.

After connecting, the lightning CLI will respond to commands exposed by the app.
Expand Down Expand Up @@ -79,8 +79,8 @@ def connect(app_name_or_id: str):
else:
click.echo(f"You are already connected to the cloud Lightning App: {app_name_or_id}.")
else:
disconnect()
connect(app_name_or_id)
disconnect_app()
connect_app(app_name_or_id)

elif app_name_or_id.startswith("localhost"):

Expand Down Expand Up @@ -217,7 +217,7 @@ def connect(app_name_or_id: str):
).wait()


def disconnect(logout: bool = False):
def disconnect_app(logout: bool = False):
"""Disconnect from an App."""
_clean_lightning_connection()

Expand Down
92 changes: 92 additions & 0 deletions src/lightning/app/cli/connect/data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Copyright The Lightning team.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import sys

import click
import rich
from lightning_cloud.openapi import ProjectIdDataConnectionsBody
from rich.live import Live
from rich.spinner import Spinner
from rich.text import Text

from lightning.app.utilities.app_helpers import Logger
from lightning.app.utilities.cli_helpers import _error_and_exit
from lightning.app.utilities.cloud import _get_project
from lightning.app.utilities.network import LightningClient

logger = Logger(__name__)


@click.argument("name", required=True)
@click.argument("region", required=True)
@click.argument("source", required=True)
@click.argument("destination", required=False)
@click.argument("project_name", required=False)
def connect_data(
name: str,
region: str,
source: str,
destination: str = "",
project_name: str = "",
) -> None:
"""Create a new data connection."""

if sys.platform == "win32":
_error_and_exit("Data connection isn't supported on windows. Open an issue on Github.")

with Live(Spinner("point", text=Text("pending...", style="white")), transient=True) as live:

live.stop()

client = LightningClient()
projects = client.projects_service_list_memberships()

project_id = None

for project in projects.memberships:

if project.name == project_name:
project_id = project.project_id
break

if project_id is None:
project_id = _get_project(client).project_id

if not source.startswith("s3://"):
return _error_and_exit(
"Only public S3 folders are supported for now. Please, open a Github issue with your use case."
)

try:
_ = client.data_connection_service_create_data_connection(
body=ProjectIdDataConnectionsBody(
name=name,
region=region,
source=source,
destination=destination,
),
project_id=project_id,
)

# Note: Expose through lightning show data {DATA_NAME}
# response = client.data_connection_service_list_data_connection_artifacts(
# project_id=project_id,
# id=response.id,
# )
# print(response)
except Exception:
_error_and_exit("The data connection creation failed.")

rich.print(f"[green]Succeeded[/green]: You have created a new data connection {name}.")
32 changes: 23 additions & 9 deletions src/lightning/app/cli/lightning_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,17 @@
from lightning.app.cli.cmd_clusters import AWSClusterManager
from lightning.app.cli.commands.app_commands import _run_app_command
from lightning.app.cli.commands.cd import cd
from lightning.app.cli.commands.connection import (
_list_app_commands,
_retrieve_connection_to_an_app,
connect,
disconnect,
)
from lightning.app.cli.commands.cp import cp
from lightning.app.cli.commands.logs import logs
from lightning.app.cli.commands.ls import ls
from lightning.app.cli.commands.pwd import pwd
from lightning.app.cli.connect.app import (
_list_app_commands,
_retrieve_connection_to_an_app,
connect_app,
disconnect_app,
)
from lightning.app.cli.connect.data import connect_data
from lightning.app.cli.lightning_cli_create import create
from lightning.app.cli.lightning_cli_delete import delete
from lightning.app.cli.lightning_cli_list import get_list
Expand Down Expand Up @@ -121,8 +122,21 @@ def show() -> None:
pass


_main.command()(connect)
_main.command()(disconnect)
@_main.group()
def connect() -> None:
"""Connect apps and data."""
pass


@_main.group()
def disconnect() -> None:
"""Disconnect apps."""
pass


connect.command("app")(connect_app)
disconnect.command("app")(disconnect_app)
connect.command("data")(connect_data)
_main.command()(ls)
_main.command()(cd)
_main.command()(cp)
Expand Down Expand Up @@ -240,7 +254,7 @@ def login() -> None:
def logout() -> None:
"""Log out of your lightning.ai account."""
Auth().clear()
disconnect(logout=True)
disconnect_app(logout=True)


def _run_app(
Expand Down
4 changes: 2 additions & 2 deletions tests/integrations_app/public/test_commands_and_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ def test_commands_and_api_example_cloud() -> None:
):
# Connect to the App and send the first & second command with the client
# Requires to be run within the same process.
cmd_1 = f"python -m lightning connect {app_name}"
cmd_1 = f"python -m lightning connect app {app_name}"
cmd_2 = "python -m lightning command with client --name=this"
cmd_3 = "python -m lightning command without client --name=is"
cmd_4 = "python -m lightning command without client --name=awesome"
cmd_5 = "lightning disconnect"
cmd_5 = "lightning disconnect app"
process = Popen(" && ".join([cmd_1, cmd_2, cmd_3, cmd_4, cmd_5]), shell=True)
process.wait()

Expand Down
42 changes: 21 additions & 21 deletions tests/tests_app/cli/test_connect.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,31 @@
import pytest

from lightning.app import _PROJECT_ROOT
from lightning.app.cli.commands.connection import (
from lightning.app.cli.connect.app import (
_list_app_commands,
_resolve_command_path,
_retrieve_connection_to_an_app,
connect,
disconnect,
connect_app,
disconnect_app,
)
from lightning.app.utilities import cli_helpers
from lightning.app.utilities.commands import base


def monkeypatch_connection(monkeypatch, tmpdir, ppid):
connection_path = os.path.join(tmpdir, ppid)
monkeypatch.setattr("lightning.app.cli.commands.connection._clean_lightning_connection", MagicMock())
monkeypatch.setattr("lightning.app.cli.commands.connection._PPID", ppid)
monkeypatch.setattr("lightning.app.cli.commands.connection._LIGHTNING_CONNECTION", tmpdir)
monkeypatch.setattr("lightning.app.cli.commands.connection._LIGHTNING_CONNECTION_FOLDER", connection_path)
monkeypatch.setattr("lightning.app.cli.connect.app._clean_lightning_connection", MagicMock())
monkeypatch.setattr("lightning.app.cli.connect.app._PPID", ppid)
monkeypatch.setattr("lightning.app.cli.connect.app._LIGHTNING_CONNECTION", tmpdir)
monkeypatch.setattr("lightning.app.cli.connect.app._LIGHTNING_CONNECTION_FOLDER", connection_path)
return connection_path


def test_connect_disconnect_local(tmpdir, monkeypatch):
disconnect()
disconnect_app()

with pytest.raises(Exception, match="Connection wasn't successful. Is your app localhost running ?"):
connect("localhost")
connect_app("localhost")

with open(os.path.join(os.path.dirname(__file__), "jsons/connect_1.json")) as f:
data = json.load(f)
Expand All @@ -43,7 +43,7 @@ def test_connect_disconnect_local(tmpdir, monkeypatch):

messages = []

disconnect()
disconnect_app()

def fn(msg):
messages.append(msg)
Expand All @@ -54,21 +54,21 @@ def fn(msg):
response.status_code = 200
response.json.return_value = data
monkeypatch.setattr(cli_helpers.requests, "get", MagicMock(return_value=response))
connect("localhost")
connect_app("localhost")
assert _retrieve_connection_to_an_app() == ("localhost", None)
command_path = _resolve_command_path("nested_command")
assert not os.path.exists(command_path)
command_path = _resolve_command_path("command_with_client")
assert os.path.exists(command_path)
messages = []
connect("localhost")
connect_app("localhost")
assert messages == ["You are connected to the local Lightning App."]

messages = []
disconnect()
disconnect_app()
assert messages == ["You are disconnected from the local Lightning App."]
messages = []
disconnect()
disconnect_app()
assert messages == [
"You aren't connected to any Lightning App. Please use `lightning connect app_name_or_id` to connect to one."
]
Expand All @@ -77,7 +77,7 @@ def fn(msg):


def test_connect_disconnect_cloud(tmpdir, monkeypatch):
disconnect()
disconnect_app()

ppid_1 = str(psutil.Process(os.getpid()).ppid())
ppid_2 = "222"
Expand Down Expand Up @@ -132,7 +132,7 @@ def fn(msg):
with open(data["paths"]["/command/command_with_client"]["post"]["cls_path"], "rb") as f:
response.content = f.read()

connect("example")
connect_app("example")
assert _retrieve_connection_to_an_app() == ("example", "1234")
commands = _list_app_commands()
assert commands == ["command with client", "command without client", "nested command"]
Expand All @@ -141,27 +141,27 @@ def fn(msg):
command_path = _resolve_command_path("command_with_client")
assert os.path.exists(command_path)
messages = []
connect("example")
connect_app("example")
assert messages == ["You are already connected to the cloud Lightning App: example."]

_ = monkeypatch_connection(monkeypatch, tmpdir, ppid=ppid_2)

messages = []
connect("example")
connect_app("example")
assert "The lightning CLI now responds to app commands" in messages[0]

messages = []
disconnect()
disconnect_app()
assert messages == ["You are disconnected from the cloud Lightning App: example."]

_ = monkeypatch_connection(monkeypatch, tmpdir, ppid=ppid_1)

messages = []
disconnect()
disconnect_app()
assert "You aren't connected to any Lightning App" in messages[0]

messages = []
disconnect()
disconnect_app()
assert messages == [
"You aren't connected to any Lightning App. Please use `lightning connect app_name_or_id` to connect to one."
]
Expand Down
Loading