Skip to content

Commit

Permalink
Refactor configuration builder for caddy
Browse files Browse the repository at this point in the history
  • Loading branch information
zacksiri committed Dec 24, 2024
1 parent aedce2c commit f13b422
Show file tree
Hide file tree
Showing 6 changed files with 299 additions and 101 deletions.
18 changes: 18 additions & 0 deletions lib/uplink/caddy/config/hosts.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
defmodule Uplink.Caddy.Config.Hosts do
alias Uplink.Packages.Metadata
alias Uplink.Packages.Metadata.Port

def routable?(%{metadata: %Metadata{main_port: nil}}), do: false

def routable?(%{
metadata: %Metadata{
main_port: %{routing: %Port.Routing{}}
}
}),
do: true

def routable?(%{metadata: %Metadata{hosts: hosts}}) when length(hosts) > 0,
do: true

def routable?(%{metadata: %Metadata{hosts: []}}), do: false
end
79 changes: 79 additions & 0 deletions lib/uplink/caddy/config/port.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
defmodule Uplink.Caddy.Config.Port do
alias Uplink.Packages.Metadata

alias Uplink.Caddy.Config.Upstreams

def build(%Metadata{ports: ports} = metadata, install_id) do
ports
|> Enum.map(&build(&1, metadata, install_id))
|> Enum.reject(&is_nil/1)
end

def build(%Metadata.Port{} = port, metadata, install_id) do
hosts = Enum.map(metadata.hosts, &merge_slug_and_host(&1, port))

routing = Map.get(port, :routing)

routing_hosts =
if routing do
Enum.map(routing.hosts, &merge_slug_and_host(&1, port))
else
[]
end

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

paths =
if routing && routing.paths != [] do
routing.paths
else
["*"]
end

group =
if routing,
do: "router_#{routing.router_id}",
else: "installation_#{metadata.id}"

if hosts == [] do
nil
else
%{
group: group,
match: [
%{
host: hosts,
path: paths
}
],
handle: [
%{
handler: "reverse_proxy",
load_balancing: %{
selection_policy: %{
policy: "least_conn"
}
},
health_checks: %{
passive: %{
fail_duration: "10s",
max_fails: 3,
unhealthy_request_count: 80,
unhealthy_status: [500, 501, 502, 503, 504],
unhealthy_latency: "30s"
}
},
upstreams: Upstreams.build(metadata, port, install_id)
}
]
}
end
end

defp merge_slug_and_host(host, %Metadata.Port{slug: slug}),
do: slug <> "." <> host
end
29 changes: 29 additions & 0 deletions lib/uplink/caddy/config/upstreams.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
defmodule Uplink.Caddy.Config.Upstreams do
alias Uplink.Cache
alias Uplink.Packages.Metadata
alias Uplink.Packages.Metadata.Port

def build(%Metadata{instances: instances}, %Port{} = port, install_id) do
instances
|> filter_valid(install_id)
|> Enum.map(fn instance ->
%{
dial: "#{instance.slug}:#{port.target}",
max_requests: 100
}
end)
end

def filter_valid(instances, install_id) do
completed_instances = Cache.get({:install, install_id, "completed"})

if is_list(completed_instances) and Enum.count(completed_instances) > 0 do
instances
|> Enum.filter(fn instance ->
instance.slug in completed_instances
end)
else
instances
end
end
end
106 changes: 7 additions & 99 deletions lib/uplink/clients/caddy/config/builder.ex
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
defmodule Uplink.Clients.Caddy.Config.Builder do
alias Uplink.Repo
alias Uplink.Cache

alias Uplink.Packages
alias Uplink.Routings

alias Uplink.Caddy.Config.Hosts
alias Uplink.Caddy.Config.Port
alias Uplink.Caddy.Config.Upstreams

alias Uplink.Clients.Caddy

alias Uplink.Clients.Caddy.Admin
Expand All @@ -17,9 +20,7 @@ defmodule Uplink.Clients.Caddy.Config.Builder do
|> Repo.all()
|> Repo.preload(deployment: [:app])
|> Enum.map(&Packages.build_install_state/1)
|> Enum.reject(fn %{metadata: metadata} ->
metadata.hosts == [] || is_nil(metadata.main_port)
end)
|> Enum.filter(&Hosts.routable?/1)

%{"organization" => %{"storage" => storage_params}} =
uplink = Uplink.Clients.Instellar.get_self()
Expand Down Expand Up @@ -157,8 +158,6 @@ defmodule Uplink.Clients.Caddy.Config.Builder do
[]
end

valid_instances = find_valid_instances(metadata.instances, install_id)

proxy_routes =
proxies
|> Enum.map(fn proxy ->
Expand Down Expand Up @@ -225,90 +224,12 @@ defmodule Uplink.Clients.Caddy.Config.Builder do
unhealthy_latency: "30s"
}
},
upstreams:
Enum.map(valid_instances, fn instance ->
%{
dial: "#{instance.slug}:#{metadata.main_port.target}",
max_requests: 100
}
end)
upstreams: Upstreams.build(metadata, metadata.main_port, install_id)
}
]
}

sub_routes =
metadata.ports
|> Enum.map(fn port ->
hosts =
Enum.map(metadata.hosts, fn host ->
port.slug <> "." <> host
end)

routing = Map.get(port, :routing)

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
["*"]
end

group =
if routing,
do: "router_#{routing.router_id}",
else: "installation_#{metadata.id}"

%{
group: group,
match: [
%{
host: hosts,
path: paths
}
],
handle: [
%{
handler: "reverse_proxy",
load_balancing: %{
selection_policy: %{
policy: "least_conn"
}
},
health_checks: %{
passive: %{
fail_duration: "10s",
max_fails: 3,
unhealthy_request_count: 80,
unhealthy_status: [500, 501, 502, 503, 504],
unhealthy_latency: "30s"
}
},
upstreams:
Enum.map(valid_instances, fn instance ->
%{
dial: "#{instance.slug}:#{port.target}",
max_requests: 100
}
end)
}
]
}
end)
sub_routes = Port.build(metadata, install_id)

sub_routes_and_proxies = Enum.concat(sub_routes, proxy_routes)

Expand All @@ -328,19 +249,6 @@ defmodule Uplink.Clients.Caddy.Config.Builder do
]
end

defp find_valid_instances(instances, install_id) do
completed_instances = Cache.get({:install, install_id, "completed"})

if is_list(completed_instances) and Enum.count(completed_instances) > 0 do
instances
|> Enum.filter(fn instance ->
instance.slug in completed_instances
end)
else
instances
end
end

defp maybe_merge_tls(params, %{tls: true}) do
Map.put(params, :transport, %{
protocol: "http",
Expand Down
Loading

0 comments on commit f13b422

Please sign in to comment.