Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Setup merging for hosts #107

Merged
merged 3 commits into from
Dec 23, 2024
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
34 changes: 31 additions & 3 deletions lib/uplink/clients/caddy/config/builder.ex
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,15 @@ defmodule Uplink.Clients.Caddy.Config.Builder do
) do
main_routing = Map.get(metadata.main_port, :routing)

main_paths =
main_routing_hosts =
if main_routing do
main_routing.hosts
else
[]
end

main_paths =
if main_routing && main_routing.paths != [] do
main_routing.paths
else
["*"]
Expand Down Expand Up @@ -187,11 +194,17 @@ defmodule Uplink.Clients.Caddy.Config.Builder do
}
end)

main_hosts =
metadata.hosts
|> Enum.concat(main_routing_hosts)
|> Enum.uniq()
|> Enum.sort()

main_route = %{
group: main_group,
match: [
%{
host: metadata.hosts,
host: main_hosts,
path: main_paths
}
],
Expand Down Expand Up @@ -233,8 +246,23 @@ defmodule Uplink.Clients.Caddy.Config.Builder do

routing = Map.get(port, :routing)

paths =
routing_hosts =
if routing do
Enum.map(routing.hosts, fn host ->
port.slug <> "." <> host
end)
else
[]
end

hosts =
hosts
|> Enum.concat(routing_hosts)
|> Enum.uniq()
|> Enum.sort()

paths =
if routing && routing.paths != [] do
routing.paths
else
["*"]
Expand Down
3 changes: 2 additions & 1 deletion lib/uplink/packages/metadata/port.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ defmodule Uplink.Packages.Metadata.Port do

embeds_one :routing, Routing, primary_key: false do
field :router_id, :integer
field :hosts, {:array, :string}, default: []
field :paths, {:array, :string}, default: ["*"]
end
end
Expand All @@ -23,7 +24,7 @@ defmodule Uplink.Packages.Metadata.Port do

defp routing_changeset(routing, params) do
routing
|> cast(params, [:router_id, :paths])
|> cast(params, [:router_id, :hosts, :paths])
|> validate_required([:router_id, :paths])
end
end
8 changes: 7 additions & 1 deletion test/scenarios/deployment.ex
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,20 @@ defmodule Uplink.Scenarios.Deployment do
"target" => 4000,
"routing" => %{
"router_id" => 1,
"hosts" => ["another.com", "something.com"],
"paths" => ["/configure*"]
}
},
"ports" => [
%{
"slug" => "grpc",
"source" => 49153,
"target" => 6000
"target" => 6000,
"routing" => %{
"router_id" => 1,
"hosts" => ["another.com", "something.com"],
"paths" => ["/*"]
}
}
],
"hosts" => ["something.com"],
Expand Down
162 changes: 153 additions & 9 deletions test/uplink/clients/caddy/config/builder_test.exs
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
defmodule Uplink.Clients.Caddy.Config.BuilderTest do
use ExUnit.Case

alias Uplink.Members
alias Uplink.Packages
alias Uplink.Secret
alias Uplink.Cache

alias Uplink.Packages.Metadata

import Uplink.Scenarios.Deployment

setup [:setup_endpoints, :setup_base]
Expand Down Expand Up @@ -66,36 +73,173 @@ defmodule Uplink.Clients.Caddy.Config.BuilderTest do
"provider" => %{"api_token" => "something", "name" => "cloudflare"}
} = dns

assert %{routes: [first_route, second_route, third_route]} = server
assert %{routes: routes} = server

routes = Enum.sort(routes)

[first_route, second_route, third_route] = routes

assert %{handle: [handle], match: [match]} = first_route
assert %{handle: [second_handle], match: [second_match]} = second_route
assert %{handle: [third_handle], match: [third_match]} = third_route

assert match.host == ["another.com", "something.com"]
assert match.path == ["/configure*"]

assert third_match.path == ["*"]
assert second_match.path == ["/*"]

assert second_match.path == ["/how-to*"]
assert third_match.path == ["/how-to*"]

assert "grpc.something.com" in third_match.host
assert "grpc.something.com" in second_match.host
assert "grpc.another.com" in second_match.host

[third_upstream] = third_handle.upstreams
[second_upstream] = second_handle.upstreams

assert third_upstream.dial =~ "6000"
assert second_upstream.dial =~ "6000"

assert %{handler: "reverse_proxy"} = handle
assert %{host: _hosts} = match

[second_upstream] = second_handle.upstreams
[third_upstream] = third_handle.upstreams

assert %{protocol: "http", tls: %{}} = second_handle.transport
assert %{protocol: "http", tls: %{}} = third_handle.transport

assert second_upstream.dial == "proxy.webflow.com:80"
assert third_upstream.dial == "proxy.webflow.com:80"

assert %{identity: identity} = admin
assert %{identifiers: ["127.0.0.1"]} = identity

assert %{module: "s3"} = storage
end

describe "when routing is nil" do
setup do
deployment_params = %{
"hash" => "a-different-hash",
"archive_url" => "http://localhost/archives/packages.zip",
"stack" => "alpine/3.14",
"channel" => "develop",
"metadata" => %{
"id" => 1,
"slug" => "uplink-web",
"main_port" => %{
"slug" => "web",
"source" => 49152,
"target" => 4000
},
"ports" => [
%{
"slug" => "grpc",
"source" => 49153,
"target" => 6000
}
],
"hosts" => ["something.com"],
"variables" => [
%{"key" => "SOMETHING", "value" => "blah"}
],
"channel" => %{
"slug" => "develop",
"package" => %{
"slug" => "something-1640927800",
"credential" => %{
"public_key" => "public_key"
},
"organization" => %{
"slug" => "upmaru"
}
}
},
"instances" => [
%{
"id" => 1,
"slug" => "something-1",
"node" => %{
"slug" => "some-node"
}
}
]
}
}

{:ok, actor} =
Members.get_or_create_actor(%{
"identifier" => "zacksiri",
"provider" => "instellar",
"id" => "1"
})

metadata = Map.get(deployment_params, "metadata")

{:ok, metadata} = Packages.parse_metadata(metadata)

app =
metadata
|> Metadata.app_slug()
|> Packages.get_or_create_app()

{:ok, deployment} =
Packages.get_or_create_deployment(app, deployment_params)

{:ok, %{resource: preparing_deployment}} =
Packages.transition_deployment_with(deployment, actor, "prepare")

{:ok, %{resource: deployment}} =
Packages.transition_deployment_with(
preparing_deployment,
actor,
"complete"
)

{:ok, install} =
Packages.create_install(deployment, %{
"installation_id" => 1,
"deployment" => deployment_params
})

signature = Secret.Signature.compute_signature(deployment.hash)

Cache.put(
{:deployment, signature, install.instellar_installation_id},
metadata
)

{:ok, %{resource: validating_install}} =
Packages.transition_install_with(install, actor, "validate")

{:ok, %{resource: _executing_install}} =
Packages.transition_install_with(validating_install, actor, "execute")

:ok
end

test "render port when routing is nil correctly" do
assert %{apps: apps} = Uplink.Clients.Caddy.build_new_config()

assert %{http: %{servers: %{"uplink" => server}}} = apps

assert %{routes: routes} = server

routes = Enum.sort(routes)

[first_route, second_route] = routes

assert %{handle: [handle], match: [match]} = first_route
assert %{handle: [second_handle], match: [second_match]} = second_route

assert match.host == ["something.com"]
assert match.path == ["*"]

assert second_match.path == ["*"]

assert "grpc.something.com" in second_match.host

[second_upstream] = second_handle.upstreams

assert second_upstream.dial =~ "6000"

assert %{handler: "reverse_proxy"} = handle
assert %{host: _hosts} = match
end
end
end