mirror of
https://github.com/livebook-dev/livebook.git
synced 2025-09-07 13:34:55 +08:00
Add function to deploy the app using a CLI session
This commit is contained in:
parent
e604e05d09
commit
5160ae4a96
3 changed files with 114 additions and 0 deletions
|
@ -265,6 +265,19 @@ defmodule Livebook.Teams do
|
|||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Deploys the given app deployment to given deployment group using a deploy key.
|
||||
"""
|
||||
@spec deploy_app_from_cli(Team.t(), Teams.AppDeployment.t(), String.t()) ::
|
||||
{:ok, String.t()} | {:error, map()} | {:transport_error, String.t()}
|
||||
def deploy_app_from_cli(%Team{} = team, %Teams.AppDeployment{} = app_deployment, name) do
|
||||
case Requests.deploy_app_from_cli(team, app_deployment, name) do
|
||||
{:ok, %{"url" => url}} -> {:ok, url}
|
||||
{:error, %{"errors" => errors}} -> {:error, errors}
|
||||
any -> any
|
||||
end
|
||||
end
|
||||
|
||||
defp map_teams_field_to_livebook_field(map, teams_field, livebook_field) do
|
||||
if value = map[teams_field] do
|
||||
Map.put_new(map, livebook_field, value)
|
||||
|
|
|
@ -239,6 +239,26 @@ defmodule Livebook.Teams.Requests do
|
|||
post("/api/v1/cli/auth", %{}, config)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Send a request to Livebook Team API to deploy an app using a deploy key.
|
||||
"""
|
||||
@spec deploy_app_from_cli(Team.t(), Teams.AppDeployment.t(), String.t()) :: api_result()
|
||||
def deploy_app_from_cli(team, app_deployment, deployment_group_name) do
|
||||
secret_key = Teams.derive_key(team.teams_key)
|
||||
|
||||
params = %{
|
||||
title: app_deployment.title,
|
||||
slug: app_deployment.slug,
|
||||
multi_session: app_deployment.multi_session,
|
||||
access_type: app_deployment.access_type,
|
||||
deployment_group_name: deployment_group_name,
|
||||
sha: app_deployment.sha
|
||||
}
|
||||
|
||||
encrypted_content = Teams.encrypt(app_deployment.file, secret_key)
|
||||
upload("/api/v1/cli/org/apps", encrypted_content, params, team)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Normalizes errors map into errors for the given schema.
|
||||
"""
|
||||
|
@ -283,6 +303,7 @@ defmodule Livebook.Teams.Requests do
|
|||
defp upload(path, content, params, team) do
|
||||
build_req(team)
|
||||
|> Req.Request.put_header("content-length", "#{byte_size(content)}")
|
||||
|> Req.Request.put_private(:cli, path =~ "cli")
|
||||
|> Req.Request.put_private(:deploy, true)
|
||||
|> Req.post(url: path, params: params, body: content)
|
||||
|> handle_response()
|
||||
|
@ -322,6 +343,9 @@ defmodule Livebook.Teams.Requests do
|
|||
|
||||
defp transform_response({request, response}) do
|
||||
case {request, response} do
|
||||
{request, %{status: 404}} when request.private.cli and request.private.deploy ->
|
||||
{request, %{response | status: 422, body: %{"errors" => %{"name" => ["does not exist"]}}}}
|
||||
|
||||
{request, %{status: 400, body: %{"errors" => %{"detail" => error}}}}
|
||||
when request.private.deploy ->
|
||||
{request, %{response | status: 422, body: %{"errors" => %{"file" => [error]}}}}
|
||||
|
|
|
@ -297,4 +297,81 @@ defmodule Livebook.TeamsTest do
|
|||
refute Livebook.Hubs.hub_exists?(team.id)
|
||||
end
|
||||
end
|
||||
|
||||
describe "deploy_app_from_cli/2" do
|
||||
@describetag teams_for: :user
|
||||
|
||||
@tag :tmp_dir
|
||||
test "deploys app to Teams using a CLI session",
|
||||
%{team: team, node: node, tmp_dir: tmp_dir, org: org} do
|
||||
%{id: id, name: name} =
|
||||
TeamsRPC.create_deployment_group(node,
|
||||
name: "angry-cat-#{Ecto.UUID.generate()}",
|
||||
url: "http://localhost:4123",
|
||||
mode: :online,
|
||||
org: org
|
||||
)
|
||||
|
||||
id = to_string(id)
|
||||
hub_id = "team-#{org.name}"
|
||||
slug = Utils.random_short_id()
|
||||
title = "MyNotebook-#{slug}"
|
||||
app_settings = %{Notebook.AppSettings.new() | slug: slug}
|
||||
|
||||
notebook = %{
|
||||
Notebook.new()
|
||||
| app_settings: app_settings,
|
||||
name: title,
|
||||
hub_id: hub_id,
|
||||
deployment_group_id: id
|
||||
}
|
||||
|
||||
files_dir = FileSystem.File.local(tmp_dir)
|
||||
|
||||
# stamp the notebook
|
||||
assert {:ok, app_deployment} = Teams.AppDeployment.new(notebook, files_dir)
|
||||
|
||||
# fetch the cli session
|
||||
{key, _deploy_key} = TeamsRPC.create_deploy_key(node, org: org)
|
||||
config = %{teams_key: team.teams_key, session_token: key}
|
||||
assert {:ok, team} = Teams.fetch_cli_session(config)
|
||||
|
||||
# deploy the app
|
||||
assert {:ok, _url} = Teams.deploy_app_from_cli(team, app_deployment, name)
|
||||
|
||||
sha = app_deployment.sha
|
||||
multi_session = app_settings.multi_session
|
||||
access_type = app_settings.access_type
|
||||
|
||||
assert_receive {:app_deployment_started,
|
||||
%Livebook.Teams.AppDeployment{
|
||||
slug: ^slug,
|
||||
sha: ^sha,
|
||||
title: ^title,
|
||||
deployed_by: "CLI",
|
||||
multi_session: ^multi_session,
|
||||
access_type: ^access_type,
|
||||
deployment_group_id: ^id
|
||||
} = app_deployment2}
|
||||
|
||||
assert Teams.deploy_app_from_cli(team, app_deployment, "foo") ==
|
||||
{:error, %{"name" => ["does not exist"]}}
|
||||
|
||||
assert Teams.deploy_app_from_cli(team, %{app_deployment | slug: "@abc"}, name) ==
|
||||
{:error, %{"slug" => ["should only contain alphanumeric characters and dashes"]}}
|
||||
|
||||
assert Teams.deploy_app_from_cli(team, %{app_deployment | multi_session: nil}, name) ==
|
||||
{:error, %{"multi_session" => ["can't be blank"]}}
|
||||
|
||||
assert Teams.deploy_app_from_cli(team, %{app_deployment | access_type: nil}, name) ==
|
||||
{:error, %{"access_type" => ["can't be blank"]}}
|
||||
|
||||
assert Teams.deploy_app_from_cli(team, %{app_deployment | access_type: :abc}, name) ==
|
||||
{:error, %{"access_type" => ["is invalid"]}}
|
||||
|
||||
# force app deployment to be stopped
|
||||
TeamsRPC.toggle_app_deployment(node, app_deployment2.id, team.org_id)
|
||||
assert_receive {:app_deployment_stopped, ^app_deployment2}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Reference in a new issue