Support URL field in deployment group (#2625)

This commit is contained in:
Karol Wilk 2024-05-29 08:31:08 +00:00 committed by GitHub
parent b22d357132
commit e35d756f96
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 105 additions and 10 deletions

View file

@ -375,7 +375,8 @@ defmodule Livebook.Hubs.TeamClient do
agent_keys: agent_keys,
clustering: nullify(deployment_group.clustering),
zta_provider: atomize(deployment_group.zta_provider),
zta_key: nullify(deployment_group.zta_key)
zta_key: nullify(deployment_group.zta_key),
url: nullify(deployment_group.url)
}
end
@ -391,7 +392,8 @@ defmodule Livebook.Hubs.TeamClient do
agent_keys: agent_keys,
clustering: nullify(deployment_group_created.clustering),
zta_provider: atomize(deployment_group_created.zta_provider),
zta_key: nullify(deployment_group_created.zta_key)
zta_key: nullify(deployment_group_created.zta_key),
url: nullify(deployment_group_created.url)
}
end
@ -407,7 +409,8 @@ defmodule Livebook.Hubs.TeamClient do
agent_keys: agent_keys,
clustering: atomize(deployment_group_updated.clustering),
zta_provider: atomize(deployment_group_updated.zta_provider),
zta_key: nullify(deployment_group_updated.zta_key)
zta_key: nullify(deployment_group_updated.zta_key),
url: nullify(deployment_group_updated.url)
}
end

View file

@ -15,6 +15,7 @@ defmodule Livebook.Teams.DeploymentGroup do
field :clustering, Ecto.Enum, values: [:fly_io, :dns]
field :zta_provider, Ecto.Enum, values: @zta_providers
field :zta_key, :string
field :url, :string
has_many :secrets, Secret
has_many :agent_keys, AgentKey
@ -23,8 +24,19 @@ defmodule Livebook.Teams.DeploymentGroup do
def changeset(deployment_group, attrs \\ %{}) do
changeset =
deployment_group
|> cast(attrs, [:id, :name, :mode, :hub_id, :clustering, :zta_provider, :zta_key])
|> cast(attrs, [:id, :name, :mode, :hub_id, :clustering, :zta_provider, :zta_key, :url])
|> validate_required([:name, :mode])
|> update_change(:url, fn url ->
if url do
url
|> String.trim_leading("http://")
|> String.trim_leading("https://")
|> String.trim_trailing("/")
end
end)
|> validate_format(:url, ~r/(^[^\/\.\s]+(\.[^\/\.\s]+)+)(\/[^\s]+)?$/,
message: "must be a well-formed URL"
)
if get_field(changeset, :zta_provider) do
validate_required(changeset, [:zta_key])

View file

@ -174,7 +174,8 @@ defmodule Livebook.Teams.Requests do
mode: deployment_group.mode,
clustering: deployment_group.clustering,
zta_provider: deployment_group.zta_provider,
zta_key: deployment_group.zta_key
zta_key: deployment_group.zta_key,
url: deployment_group.url
}
post("/api/v1/org/deployment-groups", params, team)

View file

@ -92,7 +92,21 @@ defmodule LivebookWeb.AppComponents do
def deployment_group_form_content(assigns) do
~H"""
<div>
<div class="flex flex-col">
<div class="flex flex-col gap-4">
<.schemaless_url_field
label="URL"
help={
~S'''
If you provide the URL you
will host your instances at,
Livebook will use it to
generate direct links
throughout its interface
'''
}
field={@form[:url]}
/>
<.select_field
label="Clustering"
help={

View file

@ -5,6 +5,40 @@ defmodule LivebookWeb.FormComponents do
alias Phoenix.LiveView.JS
@doc """
Renders a text input with label and error messages, as well as a "http(s)://" prefix.
"""
attr :id, :any, default: nil
attr :name, :any
attr :label, :string, default: nil
attr :value, :any
attr :errors, :list, default: []
attr :field, Phoenix.HTML.FormField, doc: "a form field struct retrieved from the form"
attr :help, :string, default: nil
attr :class, :string, default: nil
attr :rest, :global, include: ~w(autocomplete readonly disabled step min max)
def schemaless_url_field(assigns) do
assigns = assigns_from_field(assigns)
~H"""
<.field_wrapper id={@id} name={@name} label={@label} errors={@errors} help={@help}>
<div class="flex flex-row">
<div class={[input_classes([]), "flex-1 rounded-e-none border-e-0"]}>http(s)://</div>
<input
type="text"
name={@name}
id={@id || @name}
value={Phoenix.HTML.Form.normalize_value("text", @value)}
class={[input_classes(@errors), "rounded-s-none", @class]}
{@rest}
/>
</div>
</.field_wrapper>
"""
end
@doc """
Renders a text input with label and error messages.
"""

View file

@ -40,7 +40,14 @@ defmodule LivebookWeb.Hub.Teams.DeploymentGroupComponent do
</div>
<% end %>
</div>
<div class="text-sm mt-1">internal-domain.example.com</div>
<.link
:if={@deployment_group.url}
href={"https://#{@deployment_group.url}"}
class="text-sm font-semibold text-blue-600 hover:text-blue-700 mt-1"
target="_blank"
>
<%= @deployment_group.url %>
</.link>
</div>
<.link
href={Livebook.Config.teams_url() <> "/orgs/#{@hub.org_id}/deployments/groups/#{@deployment_group.id}"}

View file

@ -9,4 +9,5 @@ defmodule LivebookProto.DeploymentGroup do
field :zta_provider, 6, type: :string, json_name: "ztaProvider"
field :zta_key, 7, type: :string, json_name: "ztaKey"
field :agent_keys, 8, repeated: true, type: LivebookProto.AgentKey, json_name: "agentKeys"
field :url, 9, type: :string
end

View file

@ -8,4 +8,5 @@ defmodule LivebookProto.DeploymentGroupCreated do
field :zta_provider, 6, type: :string, json_name: "ztaProvider"
field :zta_key, 7, type: :string, json_name: "ztaKey"
field :agent_keys, 8, repeated: true, type: LivebookProto.AgentKey, json_name: "agentKeys"
field :url, 9, type: :string
end

View file

@ -8,4 +8,5 @@ defmodule LivebookProto.DeploymentGroupUpdated do
field :zta_provider, 5, type: :string, json_name: "ztaProvider"
field :zta_key, 6, type: :string, json_name: "ztaKey"
field :agent_keys, 7, repeated: true, type: LivebookProto.AgentKey, json_name: "agentKeys"
field :url, 8, type: :string
end

View file

@ -63,6 +63,7 @@ message DeploymentGroup {
string zta_provider = 6;
string zta_key = 7;
repeated AgentKey agent_keys = 8;
string url = 9;
}
message DeploymentGroupCreated {
@ -73,6 +74,7 @@ message DeploymentGroupCreated {
string zta_provider = 6;
string zta_key = 7;
repeated AgentKey agent_keys = 8;
string url = 9;
}
message DeploymentGroupUpdated {
@ -83,6 +85,7 @@ message DeploymentGroupUpdated {
string zta_provider = 5;
string zta_key = 6;
repeated AgentKey agent_keys = 7;
string url = 8;
}
message DeploymentGroupDeleted {

View file

@ -19,14 +19,18 @@ defmodule LivebookWeb.Integration.Hub.DeploymentGroupTest do
end
test "creates a deployment group", %{conn: conn, hub: hub} do
deployment_group = build(:deployment_group, mode: :offline, hub_id: hub.id)
deployment_group =
build(:deployment_group, mode: :offline, hub_id: hub.id, url: "example.com")
name = deployment_group.name
url = deployment_group.url
attrs = %{
deployment_group: %{
name: deployment_group.name,
value: deployment_group.mode,
hub_id: deployment_group.hub_id
hub_id: deployment_group.hub_id,
url: url
}
}
@ -48,7 +52,8 @@ defmodule LivebookWeb.Integration.Hub.DeploymentGroupTest do
|> element("#deployment-group-form")
|> render_submit(attrs)
assert_receive {:deployment_group_created, %DeploymentGroup{name: ^name} = deployment_group}
assert_receive {:deployment_group_created,
%DeploymentGroup{name: ^name, url: ^url} = deployment_group}
assert_patch(view, "/hub/#{hub.id}")
assert render(view) =~ "Deployment group added successfully"
@ -64,6 +69,19 @@ defmodule LivebookWeb.Integration.Hub.DeploymentGroupTest do
assert view
|> element("#deployment-group-form")
|> render_submit(attrs) =~ "has already been taken"
invalid_attrs = %{
deployment_group: %{
name: "other-name",
value: deployment_group.mode,
hub_id: deployment_group.hub_id,
url: "not a valid url"
}
}
assert view
|> element("#deployment-group-form")
|> render_submit(invalid_attrs) =~ "must be a well-formed URL"
end
test "creates a secret", %{conn: conn, hub: hub} do