mirror of
https://github.com/livebook-dev/livebook.git
synced 2024-09-20 10:05:57 +08:00
Deployment group secrets (#2374)
Co-authored-by: Jonatan Kłosko <jonatanklosko@gmail.com>
This commit is contained in:
parent
839c326ab0
commit
8923e700d8
|
@ -196,13 +196,14 @@ defmodule Livebook.Hubs.TeamClient do
|
|||
%{state | secrets: Enum.reject(state.secrets, &(&1.name == secret.name))}
|
||||
end
|
||||
|
||||
defp build_secret(state, %{name: name, value: value}) do
|
||||
defp build_secret(state, %{name: name, value: value} = attrs) do
|
||||
{:ok, decrypted_value} = Teams.decrypt(value, state.derived_key)
|
||||
|
||||
%Secrets.Secret{
|
||||
name: name,
|
||||
value: decrypted_value,
|
||||
hub_id: state.hub.id
|
||||
hub_id: state.hub.id,
|
||||
deployment_group_id: Map.get(attrs, :deployment_group_id)
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -243,8 +244,9 @@ defmodule Livebook.Hubs.TeamClient do
|
|||
}
|
||||
end
|
||||
|
||||
defp build_deployment_group(state, %{id: id, name: name, mode: mode}) do
|
||||
%DeploymentGroup{id: id, name: name, mode: mode, hub_id: state.hub.id}
|
||||
defp build_deployment_group(state, %{id: id, name: name, mode: mode, secrets: secrets}) do
|
||||
secrets = Enum.map(secrets, &build_secret(state, &1))
|
||||
%DeploymentGroup{id: id, name: name, mode: mode, hub_id: state.hub.id, secrets: secrets}
|
||||
end
|
||||
|
||||
defp handle_event(:secret_created, %Secrets.Secret{} = secret, state) do
|
||||
|
|
|
@ -5,18 +5,20 @@ defmodule Livebook.Secrets.Secret do
|
|||
@type t :: %__MODULE__{
|
||||
name: String.t(),
|
||||
value: String.t(),
|
||||
hub_id: String.t() | nil
|
||||
hub_id: String.t() | nil,
|
||||
deployment_group_id: String.t() | nil
|
||||
}
|
||||
|
||||
@primary_key {:name, :string, autogenerate: false}
|
||||
embedded_schema do
|
||||
field :value, :string
|
||||
field :hub_id, :string
|
||||
field :deployment_group_id, :string
|
||||
end
|
||||
|
||||
def changeset(secret, attrs \\ %{}) do
|
||||
secret
|
||||
|> cast(attrs, [:name, :value, :hub_id])
|
||||
|> cast(attrs, [:name, :value, :hub_id, :deployment_group_id])
|
||||
|> update_change(:name, &String.upcase/1)
|
||||
|> validate_format(:name, ~r/^\w+$/,
|
||||
message: "should contain only alphanumeric characters and underscore"
|
||||
|
|
|
@ -1,19 +1,22 @@
|
|||
defmodule Livebook.Teams.DeploymentGroup do
|
||||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
alias Livebook.Secrets.Secret
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
id: pos_integer() | nil,
|
||||
id: String.t() | nil,
|
||||
name: String.t() | nil,
|
||||
mode: :online | :offline,
|
||||
hub_id: String.t() | nil
|
||||
hub_id: String.t() | nil,
|
||||
secrets: [Secret.t()]
|
||||
}
|
||||
|
||||
@primary_key {:id, :id, autogenerate: false}
|
||||
@primary_key {:id, :string, autogenerate: false}
|
||||
embedded_schema do
|
||||
field :name, :string
|
||||
field :mode, Ecto.Enum, values: [:online, :offline]
|
||||
field :hub_id, :string
|
||||
has_many :secrets, Secret
|
||||
end
|
||||
|
||||
def changeset(deployment_group, attrs \\ %{}) do
|
||||
|
|
|
@ -49,34 +49,66 @@ defmodule Livebook.Teams.Requests do
|
|||
"""
|
||||
@spec create_secret(Team.t(), Secret.t()) ::
|
||||
{:ok, map()} | {:error, map() | String.t()} | {:transport_error, String.t()}
|
||||
def create_secret(team, secret) do
|
||||
def create_secret(team, %{deployment_group_id: nil} = secret) do
|
||||
secret_key = Teams.derive_key(team.teams_key)
|
||||
secret_value = Teams.encrypt(secret.value, secret_key)
|
||||
|
||||
post("/api/v1/org/secrets", %{name: secret.name, value: secret_value}, team)
|
||||
end
|
||||
|
||||
def create_secret(team, secret) do
|
||||
secret_key = Teams.derive_key(team.teams_key)
|
||||
secret_value = Teams.encrypt(secret.value, secret_key)
|
||||
|
||||
params = %{
|
||||
name: secret.name,
|
||||
value: secret_value,
|
||||
deployment_group_id: secret.deployment_group_id
|
||||
}
|
||||
|
||||
post("/api/v1/org/deployment-groups/secrets", params, team)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Send a request to Livebook Team API to update a secret.
|
||||
"""
|
||||
@spec update_secret(Team.t(), Secret.t()) ::
|
||||
{:ok, map()} | {:error, map() | String.t()} | {:transport_error, String.t()}
|
||||
def update_secret(team, secret) do
|
||||
def update_secret(team, %{deployment_group_id: nil} = secret) do
|
||||
secret_key = Teams.derive_key(team.teams_key)
|
||||
secret_value = Teams.encrypt(secret.value, secret_key)
|
||||
|
||||
put("/api/v1/org/secrets", %{name: secret.name, value: secret_value}, team)
|
||||
end
|
||||
|
||||
def update_secret(team, secret) do
|
||||
secret_key = Teams.derive_key(team.teams_key)
|
||||
secret_value = Teams.encrypt(secret.value, secret_key)
|
||||
|
||||
params = %{
|
||||
name: secret.name,
|
||||
value: secret_value,
|
||||
deployment_group_id: secret.deployment_group_id
|
||||
}
|
||||
|
||||
put("/api/v1/org/deployment-groups/secrets", params, team)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Send a request to Livebook Team API to delete a secret.
|
||||
"""
|
||||
@spec delete_secret(Team.t(), Secret.t()) ::
|
||||
{:ok, String.t()} | {:error, map() | String.t()} | {:transport_error, String.t()}
|
||||
def delete_secret(team, secret) do
|
||||
def delete_secret(team, %{deployment_group_id: nil} = secret) do
|
||||
delete("/api/v1/org/secrets", %{name: secret.name}, team)
|
||||
end
|
||||
|
||||
def delete_secret(team, secret) do
|
||||
params = %{name: secret.name, deployment_group_id: secret.deployment_group_id}
|
||||
|
||||
delete("/api/v1/org/deployment-groups/secrets", params, team)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Send a request to Livebook Team API to create a file system.
|
||||
"""
|
||||
|
|
|
@ -101,6 +101,9 @@ defmodule LivebookWeb.Hub.Edit.PersonalComponent do
|
|||
id="hub-secrets-list"
|
||||
hub={@hub}
|
||||
secrets={@secrets}
|
||||
add_path={~p"/hub/#{@hub.id}/secrets/new"}
|
||||
edit_path={"hub/#{@hub.id}/secrets/edit"}
|
||||
return_to={~p"/hub/#{@hub.id}"}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -185,6 +185,9 @@ defmodule LivebookWeb.Hub.Edit.TeamComponent do
|
|||
id="hub-secrets-list"
|
||||
hub={@hub}
|
||||
secrets={@secrets}
|
||||
add_path={~p"/hub/#{@hub.id}/secrets/new"}
|
||||
edit_path={"hub/#{@hub.id}/secrets/edit"}
|
||||
return_to={~p"/hub/#{@hub.id}"}
|
||||
target={@myself}
|
||||
/>
|
||||
</div>
|
||||
|
@ -324,23 +327,6 @@ defmodule LivebookWeb.Hub.Edit.TeamComponent do
|
|||
return_to={~p"/hub/#{@hub.id}"}
|
||||
/>
|
||||
</.modal>
|
||||
|
||||
<.modal
|
||||
:if={@live_action in [:new_deployment_group, :edit_deployment_group]}
|
||||
id="deployment-groups-modal"
|
||||
show
|
||||
width={:medium}
|
||||
patch={~p"/hub/#{@hub.id}"}
|
||||
>
|
||||
<.live_component
|
||||
module={LivebookWeb.Hub.Teams.DeploymentGroupFormComponent}
|
||||
id="deployment-groups"
|
||||
hub={@hub}
|
||||
deployment_group_id={@deployment_group_id}
|
||||
deployment_group={@deployment_group}
|
||||
return_to={~p"/hub/#{@hub.id}"}
|
||||
/>
|
||||
</.modal>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -20,6 +20,7 @@ defmodule LivebookWeb.Hub.SecretFormComponent do
|
|||
title: title(socket),
|
||||
button: button(socket),
|
||||
changeset: changeset,
|
||||
deployment_group_id: assigns[:deployment_group_id],
|
||||
error_message: nil
|
||||
)}
|
||||
end
|
||||
|
@ -66,6 +67,7 @@ defmodule LivebookWeb.Hub.SecretFormComponent do
|
|||
phx-debounce
|
||||
/>
|
||||
<.hidden_field field={f[:hub_id]} value={@hub.id} />
|
||||
<.hidden_field field={f[:deployment_group_id]} value={@deployment_group_id} />
|
||||
<div class="flex space-x-2">
|
||||
<button class="button-base button-blue" type="submit" disabled={not @changeset.valid?}>
|
||||
<.remix_icon icon={@button.icon} class="align-middle mr-1" />
|
||||
|
|
|
@ -16,7 +16,7 @@ defmodule LivebookWeb.Hub.SecretListComponent do
|
|||
<div id={@id} class="flex flex-col space-y-4">
|
||||
<div class="flex flex-col space-y-4">
|
||||
<.no_entries :if={@secrets == []}>
|
||||
No secrets in this Hub yet.
|
||||
No secrets here... yet!
|
||||
</.no_entries>
|
||||
<div
|
||||
:for={secret <- @secrets}
|
||||
|
@ -43,7 +43,7 @@ defmodule LivebookWeb.Hub.SecretListComponent do
|
|||
<.menu_item>
|
||||
<.link
|
||||
id={"hub-secret-#{secret.name}-edit"}
|
||||
patch={~p"/hub/#{secret.hub_id}/secrets/edit/#{secret.name}"}
|
||||
patch={"/#{@edit_path}/#{secret.name}"}
|
||||
type="button"
|
||||
role="menuitem"
|
||||
>
|
||||
|
@ -60,7 +60,9 @@ defmodule LivebookWeb.Hub.SecretListComponent do
|
|||
value: %{
|
||||
name: secret.name,
|
||||
value: secret.value,
|
||||
hub_id: secret.hub_id
|
||||
hub_id: secret.hub_id,
|
||||
deployment_group_id: secret.deployment_group_id,
|
||||
return_to: @return_to
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -77,7 +79,7 @@ defmodule LivebookWeb.Hub.SecretListComponent do
|
|||
</div>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<.link patch={~p"/hub/#{@hub.id}/secrets/new"} class="button-base button-blue" id="add-secret">
|
||||
<.link patch={@add_path} class="button-base button-blue" id="add-secret">
|
||||
Add secret
|
||||
</.link>
|
||||
</div>
|
||||
|
@ -95,7 +97,7 @@ defmodule LivebookWeb.Hub.SecretListComponent do
|
|||
:ok ->
|
||||
socket
|
||||
|> put_flash(:success, "Secret #{secret.name} deleted successfully")
|
||||
|> push_navigate(to: ~p"/hub/#{hub.id}")
|
||||
|> push_navigate(to: attrs["return_to"])
|
||||
|
||||
{:transport_error, reason} ->
|
||||
put_flash(socket, :error, reason)
|
||||
|
|
|
@ -7,6 +7,7 @@ defmodule LivebookWeb.Hub.Teams.DeploymentGroupFormComponent do
|
|||
@impl true
|
||||
def update(assigns, socket) do
|
||||
deployment_group = assigns.deployment_group
|
||||
hub = assigns.hub
|
||||
|
||||
deployment_group = deployment_group || %DeploymentGroup{hub_id: assigns.hub.id}
|
||||
changeset = Teams.change_deployment_group(deployment_group)
|
||||
|
@ -20,6 +21,7 @@ defmodule LivebookWeb.Hub.Teams.DeploymentGroupFormComponent do
|
|||
mode: mode(deployment_group),
|
||||
title: title(deployment_group),
|
||||
button: button(deployment_group),
|
||||
subtitle: subtitle(deployment_group, hub.hub_name),
|
||||
error_message: nil
|
||||
)}
|
||||
end
|
||||
|
@ -27,10 +29,14 @@ defmodule LivebookWeb.Hub.Teams.DeploymentGroupFormComponent do
|
|||
@impl true
|
||||
def render(assigns) do
|
||||
~H"""
|
||||
<div class="p-6 max-w-4xl flex flex-col space-y-5">
|
||||
<h3 class="text-2xl font-semibold text-gray-800">
|
||||
<div class="max-w-4xl flex flex-col space-y-5">
|
||||
<h2 class="text-xl text-gray-800 font-medium pb-2 border-b border-gray-200">
|
||||
<%= @title %>
|
||||
</h3>
|
||||
</h2>
|
||||
|
||||
<p class="text-gray-700">
|
||||
<%= @subtitle %>
|
||||
</p>
|
||||
<div class="flex flex-columns gap-4">
|
||||
<.form
|
||||
:let={f}
|
||||
|
@ -69,9 +75,11 @@ defmodule LivebookWeb.Hub.Teams.DeploymentGroupFormComponent do
|
|||
<.remix_icon icon={@button.icon} class="align-middle mr-1" />
|
||||
<span class="font-normal"><%= @button.label %></span>
|
||||
</button>
|
||||
<.link patch={@return_to} class="button-base button-outlined-gray">
|
||||
Cancel
|
||||
</.link>
|
||||
<%= if @mode == :new do %>
|
||||
<.link patch={@return_to} class="button-base button-outlined-gray">
|
||||
Cancel
|
||||
</.link>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</.form>
|
||||
|
@ -85,7 +93,7 @@ defmodule LivebookWeb.Hub.Teams.DeploymentGroupFormComponent do
|
|||
changeset = Teams.change_deployment_group(socket.assigns.deployment_group, attrs)
|
||||
|
||||
with {:ok, deployment_group} <- Ecto.Changeset.apply_action(changeset, :update),
|
||||
{:ok, _id} <- save_deployment_group(deployment_group, socket) do
|
||||
{:ok, id} <- save_deployment_group(deployment_group, socket) do
|
||||
message =
|
||||
case socket.assigns.mode do
|
||||
:new -> "Deployment group #{deployment_group.name} added successfully"
|
||||
|
@ -95,7 +103,7 @@ defmodule LivebookWeb.Hub.Teams.DeploymentGroupFormComponent do
|
|||
{:noreply,
|
||||
socket
|
||||
|> put_flash(:success, message)
|
||||
|> push_redirect(to: socket.assigns.return_to)}
|
||||
|> push_redirect(to: ~p"/hub/#{socket.assigns.hub.id}/deployment-groups/edit/#{id}")}
|
||||
else
|
||||
{:error, %Ecto.Changeset{} = changeset} ->
|
||||
{:noreply, assign(socket, changeset: changeset)}
|
||||
|
@ -130,6 +138,12 @@ defmodule LivebookWeb.Hub.Teams.DeploymentGroupFormComponent do
|
|||
defp title(%DeploymentGroup{name: nil}), do: "Add deployment group"
|
||||
defp title(_), do: "Edit deployment group"
|
||||
|
||||
defp subtitle(%DeploymentGroup{name: nil}, hub_name),
|
||||
do: "Add a new deployment group to #{hub_name}"
|
||||
|
||||
defp subtitle(%DeploymentGroup{name: deployment_group}, _),
|
||||
do: "Manage the #{deployment_group} deployment group"
|
||||
|
||||
defp button(%DeploymentGroup{name: nil}), do: %{icon: "add-line", label: "Add"}
|
||||
defp button(_), do: %{icon: "save-line", label: "Save"}
|
||||
end
|
||||
|
|
168
lib/livebook_web/live/hub/teams/deployment_group_live.ex
Normal file
168
lib/livebook_web/live/hub/teams/deployment_group_live.ex
Normal file
|
@ -0,0 +1,168 @@
|
|||
defmodule LivebookWeb.Hub.Teams.DeploymentGroupLive do
|
||||
use LivebookWeb, :live_view
|
||||
|
||||
alias LivebookWeb.LayoutHelpers
|
||||
alias Livebook.Hubs
|
||||
alias Livebook.Teams
|
||||
alias Livebook.Hubs.Provider
|
||||
alias LivebookWeb.NotFoundError
|
||||
|
||||
on_mount LivebookWeb.SidebarHook
|
||||
|
||||
@impl true
|
||||
def handle_params(%{"id" => id} = params, _url, socket) do
|
||||
hub = Hubs.fetch_hub!(id)
|
||||
deployment_group_id = params["deployment_group_id"]
|
||||
secret_name = params["secret_name"]
|
||||
deployment_groups = Teams.get_deployment_groups(hub)
|
||||
default? = default_hub?(hub)
|
||||
|
||||
deployment_group =
|
||||
if socket.assigns.live_action != :new_deployment_group do
|
||||
Enum.find_value(deployment_groups, &(&1.id == deployment_group_id && &1)) ||
|
||||
raise(
|
||||
NotFoundError,
|
||||
"could not find deployment group matching #{inspect(deployment_group_id)}"
|
||||
)
|
||||
end
|
||||
|
||||
secrets =
|
||||
if socket.assigns.live_action != :new_deployment_group,
|
||||
do: deployment_group.secrets,
|
||||
else: []
|
||||
|
||||
secret_value =
|
||||
if socket.assigns.live_action == :edit_secret do
|
||||
Enum.find_value(secrets, &(&1.name == secret_name and &1.value)) ||
|
||||
raise(NotFoundError, "could not find secret matching #{inspect(secret_name)}")
|
||||
end
|
||||
|
||||
{:noreply,
|
||||
socket
|
||||
|> assign(
|
||||
hub: hub,
|
||||
deployment_groups: deployment_groups,
|
||||
deployment_group_id: deployment_group_id,
|
||||
deployment_group: deployment_group,
|
||||
hub_metadata: Provider.to_metadata(hub),
|
||||
secret_name: secret_name,
|
||||
secret_value: secret_value,
|
||||
default?: default?,
|
||||
secrets: secrets
|
||||
)}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def render(assigns) do
|
||||
~H"""
|
||||
<LayoutHelpers.layout
|
||||
current_page={~p"/hub/#{@hub.id}"}
|
||||
current_user={@current_user}
|
||||
saved_hubs={@saved_hubs}
|
||||
>
|
||||
<div>
|
||||
<LayoutHelpers.topbar
|
||||
:if={not @hub_metadata.connected? && Provider.connection_error(@hub)}
|
||||
variant={:warning}
|
||||
>
|
||||
<%= Provider.connection_error(@hub) %>
|
||||
</LayoutHelpers.topbar>
|
||||
|
||||
<div class="p-4 md:px-12 md:py-7 max-w-screen-md mx-auto">
|
||||
<div id={"#{@hub.id}-component"}>
|
||||
<div class="mb-8 flex flex-col space-y-10">
|
||||
<div class="flex flex-col space-y-2">
|
||||
<LayoutHelpers.title>
|
||||
<div class="flex gap-2 items-center">
|
||||
<div class="flex justify-center">
|
||||
<span class="relative">
|
||||
<%= @hub.hub_emoji %>
|
||||
|
||||
<div class={[
|
||||
"absolute w-[10px] h-[10px] border-white border-2 rounded-full right-0 bottom-1",
|
||||
if(@hub_metadata.connected?, do: "bg-green-400", else: "bg-red-400")
|
||||
]} />
|
||||
</span>
|
||||
</div>
|
||||
<%= @hub.hub_name %>
|
||||
<span class="bg-green-100 text-green-800 text-xs px-2.5 py-0.5 rounded cursor-default">
|
||||
Livebook Teams
|
||||
</span>
|
||||
<%= if @default? do %>
|
||||
<span class="bg-blue-100 text-blue-800 text-xs px-2.5 py-0.5 rounded cursor-default">
|
||||
Default
|
||||
</span>
|
||||
<% end %>
|
||||
</div>
|
||||
</LayoutHelpers.title>
|
||||
<p class="text-sm flex flex-row space-x-6 text-gray-700">
|
||||
<.link patch={~p"/hub/#{@hub.id}"} class="hover:text-blue-600 cursor-pointer">
|
||||
<.remix_icon icon="arrow-left-line" /> Back to Hub
|
||||
</.link>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col space-y-4">
|
||||
<.live_component
|
||||
module={LivebookWeb.Hub.Teams.DeploymentGroupFormComponent}
|
||||
id="deployment-groups"
|
||||
hub={@hub}
|
||||
deployment_group_id={@deployment_group_id}
|
||||
deployment_group={@deployment_group}
|
||||
return_to={~p"/hub/#{@hub.id}"}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<%= if @deployment_group_id do %>
|
||||
<div class="flex flex-col space-y-4">
|
||||
<h2 class="text-xl text-gray-800 font-medium pb-2 border-b border-gray-200">
|
||||
Secrets
|
||||
</h2>
|
||||
|
||||
<p class="text-gray-700">
|
||||
Deployment group secrets overrides Hub secrets
|
||||
</p>
|
||||
|
||||
<.live_component
|
||||
module={LivebookWeb.Hub.SecretListComponent}
|
||||
id="hub-secrets-list"
|
||||
hub={@hub}
|
||||
secrets={@secrets}
|
||||
deployment_group={@deployment_group}
|
||||
add_path={
|
||||
~p"/hub/#{@hub.id}/deployment-groups/edit/#{@deployment_group.id}/secrets/new"
|
||||
}
|
||||
edit_path={"hub/#{@hub.id}/deployment-groups/edit/#{@deployment_group.id}/secrets/edit"}
|
||||
return_to={~p"/hub/#{@hub.id}/deployment-groups/edit/#{@deployment_group.id}"}
|
||||
/>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<.modal
|
||||
:if={@live_action in [:new_secret, :edit_secret]}
|
||||
id="secrets-modal"
|
||||
show
|
||||
width={:medium}
|
||||
patch={~p"/hub/#{@hub.id}/deployment-groups/edit/#{@deployment_group.id}"}
|
||||
>
|
||||
<.live_component
|
||||
module={LivebookWeb.Hub.SecretFormComponent}
|
||||
id="secrets"
|
||||
hub={@hub}
|
||||
deployment_group_id={@deployment_group.id}
|
||||
secret_name={@secret_name}
|
||||
secret_value={@secret_value}
|
||||
return_to={~p"/hub/#{@hub.id}/deployment-groups/edit/#{@deployment_group.id}"}
|
||||
/>
|
||||
</.modal>
|
||||
</LayoutHelpers.layout>
|
||||
"""
|
||||
end
|
||||
|
||||
defp default_hub?(hub) do
|
||||
Hubs.get_default_hub().id == hub.id
|
||||
end
|
||||
end
|
|
@ -83,13 +83,25 @@ defmodule LivebookWeb.Router do
|
|||
live "/hub/:id/secrets/edit/:secret_name", Hub.EditLive, :edit_secret, as: :hub
|
||||
live "/hub/:id/file-systems/new", Hub.EditLive, :new_file_system, as: :hub
|
||||
live "/hub/:id/file-systems/edit/:file_system_id", Hub.EditLive, :edit_file_system, as: :hub
|
||||
live "/hub/:id/deployment-groups/new", Hub.EditLive, :new_deployment_group, as: :hub
|
||||
|
||||
live "/hub/:id/deployment-groups/new", Hub.Teams.DeploymentGroupLive, :new_deployment_group,
|
||||
as: :hub
|
||||
|
||||
live "/hub/:id/deployment-groups/edit/:deployment_group_id",
|
||||
Hub.EditLive,
|
||||
Hub.Teams.DeploymentGroupLive,
|
||||
:edit_deployment_group,
|
||||
as: :hub
|
||||
|
||||
live "/hub/:id/deployment-groups/edit/:deployment_group_id/secrets/new",
|
||||
Hub.Teams.DeploymentGroupLive,
|
||||
:new_secret,
|
||||
as: :hub
|
||||
|
||||
live "/hub/:id/deployment-groups/edit/:deployment_group_id/secrets/edit/:secret_name",
|
||||
Hub.Teams.DeploymentGroupLive,
|
||||
:edit_secret,
|
||||
as: :hub
|
||||
|
||||
live "/sessions/:id", SessionLive, :page
|
||||
live "/sessions/:id/shortcuts", SessionLive, :shortcuts
|
||||
live "/sessions/:id/secrets", SessionLive, :secrets
|
||||
|
|
|
@ -4,4 +4,5 @@ defmodule LivebookProto.DeploymentGroup do
|
|||
field :id, 1, type: :string
|
||||
field :name, 2, type: :string
|
||||
field :mode, 3, type: :string
|
||||
field :secrets, 4, repeated: true, type: LivebookProto.DeploymentGroupSecret
|
||||
end
|
||||
|
|
|
@ -4,4 +4,5 @@ defmodule LivebookProto.DeploymentGroupCreated do
|
|||
field :id, 1, type: :string
|
||||
field :name, 2, type: :string
|
||||
field :mode, 3, type: :string
|
||||
field :secrets, 4, repeated: true, type: LivebookProto.DeploymentGroupSecret
|
||||
end
|
||||
|
|
7
proto/lib/livebook_proto/deployment_group_secret.pb.ex
Normal file
7
proto/lib/livebook_proto/deployment_group_secret.pb.ex
Normal file
|
@ -0,0 +1,7 @@
|
|||
defmodule LivebookProto.DeploymentGroupSecret do
|
||||
use Protobuf, syntax: :proto3, protoc_gen_elixir_version: "0.12.0"
|
||||
|
||||
field :name, 1, type: :string
|
||||
field :value, 2, type: :string
|
||||
field :deployment_group_id, 3, type: :string
|
||||
end
|
|
@ -4,4 +4,5 @@ defmodule LivebookProto.DeploymentGroupUpdated do
|
|||
field :id, 1, type: :string
|
||||
field :name, 2, type: :string
|
||||
field :mode, 3, type: :string
|
||||
field :secrets, 4, repeated: true, type: LivebookProto.DeploymentGroupSecret
|
||||
end
|
||||
|
|
|
@ -48,22 +48,31 @@ message FileSystemDeleted {
|
|||
string id = 1;
|
||||
}
|
||||
|
||||
message DeploymentGroupSecret {
|
||||
string name = 1;
|
||||
string value = 2;
|
||||
string deployment_group_id = 3;
|
||||
}
|
||||
|
||||
message DeploymentGroup {
|
||||
string id = 1;
|
||||
string name = 2;
|
||||
string mode = 3;
|
||||
repeated DeploymentGroupSecret secrets = 4;
|
||||
}
|
||||
|
||||
message DeploymentGroupCreated {
|
||||
string id = 1;
|
||||
string name = 2;
|
||||
string mode = 3;
|
||||
repeated DeploymentGroupSecret secrets = 4;
|
||||
}
|
||||
|
||||
message DeploymentGroupUpdated {
|
||||
string id = 1;
|
||||
string name = 2;
|
||||
string mode = 3;
|
||||
repeated DeploymentGroupSecret secrets = 4;
|
||||
}
|
||||
|
||||
message DeploymentGroupDeleted {
|
||||
|
|
|
@ -325,14 +325,14 @@ defmodule LivebookWeb.Integration.Hub.EditLiveTest do
|
|||
}
|
||||
}
|
||||
|
||||
refute render(view) =~ deployment_group.name
|
||||
|
||||
view
|
||||
|> element("#add-deployment-group")
|
||||
|> render_click(%{})
|
||||
|> render_click()
|
||||
|
||||
assert_patch(view, ~p"/hub/#{hub.id}/deployment-groups/new")
|
||||
assert render(view) =~ "Add deployment group"
|
||||
|
||||
{:ok, view, html} = live(conn, ~p"/hub/#{hub.id}/deployment-groups/new")
|
||||
assert html =~ "Add a new deployment group to"
|
||||
|
||||
view
|
||||
|> element("#deployment-groups-form")
|
||||
|
@ -350,7 +350,7 @@ defmodule LivebookWeb.Integration.Hub.EditLiveTest do
|
|||
%DeploymentGroup{name: "TEAM_ADD_DEPLOYMENT_GROUP"} = deployment_group}
|
||||
|
||||
%{"success" => "Deployment group TEAM_ADD_DEPLOYMENT_GROUP added successfully"} =
|
||||
assert_redirect(view, "/hub/#{hub.id}")
|
||||
assert_redirect(view, "/hub/#{hub.id}/deployment-groups/edit/#{deployment_group.id}")
|
||||
|
||||
{:ok, view, _html} = live(conn, ~p"/hub/#{hub.id}")
|
||||
|
||||
|
@ -386,7 +386,12 @@ defmodule LivebookWeb.Integration.Hub.EditLiveTest do
|
|||
|> render_click(%{"deployment_group_name" => deployment_group.id})
|
||||
|
||||
assert_patch(view, ~p"/hub/#{hub.id}/deployment-groups/edit/#{deployment_group.id}")
|
||||
assert render(view) =~ "Edit deployment group"
|
||||
|
||||
{:ok, view, html} =
|
||||
live(conn, ~p"/hub/#{hub.id}/deployment-groups/edit/#{deployment_group.id}")
|
||||
|
||||
assert html =~ "Edit deployment group"
|
||||
assert html =~ "Manage the #{deployment_group.name} deployment group"
|
||||
|
||||
view
|
||||
|> element("#deployment-groups-form")
|
||||
|
@ -405,7 +410,7 @@ defmodule LivebookWeb.Integration.Hub.EditLiveTest do
|
|||
assert_receive {:deployment_group_updated, ^updated_deployment_group}
|
||||
|
||||
%{"success" => "Deployment group TEAM_EDIT_DEPLOYMENT_GROUP updated successfully"} =
|
||||
assert_redirect(view, "/hub/#{hub.id}")
|
||||
assert_redirect(view, "/hub/#{hub.id}/deployment-groups/edit/#{deployment_group.id}")
|
||||
|
||||
{:ok, view, _html} = live(conn, ~p"/hub/#{hub.id}")
|
||||
assert render(element(view, "#hub-deployment-groups-list")) =~ deployment_group.name
|
||||
|
|
|
@ -51,7 +51,8 @@ defmodule Livebook.Factory do
|
|||
%Livebook.Secrets.Secret{
|
||||
name: "FOO",
|
||||
value: "123",
|
||||
hub_id: Livebook.Hubs.Personal.id()
|
||||
hub_id: Livebook.Hubs.Personal.id(),
|
||||
deployment_group_id: nil
|
||||
}
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue