Skip to content

Commit

Permalink
Merge pull request #101 from upmaru/feature/use-package-size-from-met…
Browse files Browse the repository at this point in the history
…adata

Add parsing of package_size to install metadata
  • Loading branch information
zacksiri authored Jul 18, 2024
2 parents bc8d8d6 + 14e40ea commit 839408c
Show file tree
Hide file tree
Showing 17 changed files with 1,437 additions and 20 deletions.
6 changes: 6 additions & 0 deletions lib/uplink/packages.ex
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ defmodule Uplink.Packages do
defdelegate get_or_create_project_name(client, metadata),
to: Metadata.Manager

defdelegate get_size_profile(metadata),
to: Metadata.Manager

defdelegate upsert_size_profile(metadata),
to: Metadata.Manager

defdelegate profile_name(metadata),
to: Metadata.Manager

Expand Down
24 changes: 21 additions & 3 deletions lib/uplink/packages/install/validate.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@ defmodule Uplink.Packages.Install.Validate do

alias Members.Actor

alias Packages.{
Install
}
alias Packages.Install
alias Packages.Metadata

alias Clients.LXD

Expand Down Expand Up @@ -41,9 +40,28 @@ defmodule Uplink.Packages.Install.Validate do

install
|> Packages.build_install_state(actor)
|> ensure_size_profile_exists()
|> ensure_profile_exists()
end

defp ensure_size_profile_exists(
%{metadata: %Metadata{package_size: nil}} = state
),
do: state

defp ensure_size_profile_exists(
%{metadata: %Metadata{package_size: %Metadata.Size{}} = metadata} =
state
) do
case Packages.upsert_size_profile(metadata) do
{:ok, _} ->
state

{:error, error} ->
raise "Error: #{inspect(error)} occured when attempting to update or create size profile"
end
end

defp ensure_profile_exists(%{
install: install,
metadata: metadata,
Expand Down
25 changes: 17 additions & 8 deletions lib/uplink/packages/instance/bootstrap.ex
Original file line number Diff line number Diff line change
Expand Up @@ -83,17 +83,30 @@ defmodule Uplink.Packages.Instance.Bootstrap do
|> Enum.find(fn member ->
member.server_name == node
end) do
client = LXD.client()

profile_name = Packages.profile_name(metadata)

size_profile_name = Packages.get_size_profile(metadata)

lxd_project_name = Packages.get_or_create_project_name(client, metadata)

image_server = get_image_server()

profiles = [profile_name, "default"]

profiles =
if size_profile_name do
[size_profile_name | profiles]
else
profiles
end

lxd_instance =
Map.merge(@default_params, %{
"name" => instance_name,
"architecture" => architecture,
"profiles" => [
profile_name,
"default"
],
"profiles" => profiles,
"source" => %{
"type" => "image",
"mode" => "pull",
Expand All @@ -103,10 +116,6 @@ defmodule Uplink.Packages.Instance.Bootstrap do
}
})

client = LXD.client()

lxd_project_name = Packages.get_or_create_project_name(client, metadata)

client
|> Formation.lxd_create(node, lxd_instance, project: lxd_project_name)
|> case do
Expand Down
34 changes: 34 additions & 0 deletions lib/uplink/packages/instance/upgrade.ex
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ defmodule Uplink.Packages.Instance.Upgrade do
Map.put(@transition_parameters, "node", node["slug"])

LXD.client()
|> handle_update_config(formation_instance, metadata)
|> Formation.lxd_upgrade_alpine_package(formation_instance)
|> case do
{:ok, upgrade_package_output} ->
Expand Down Expand Up @@ -220,4 +221,37 @@ defmodule Uplink.Packages.Instance.Upgrade do
|> Instance.Cleanup.new()
|> Oban.insert()
end

defp handle_update_config(client, _instance, %Metadata{package_size: nil}),
do: client

defp handle_update_config(client, instance, metadata) do
profile_name = Packages.profile_name(metadata)
size_profile_name = Packages.get_size_profile(metadata)

profiles = [profile_name, "default"]

profiles =
if size_profile_name do
[size_profile_name | profiles]
else
profiles
end

params = %{
"profiles" => profiles
}

client
|> Lexdee.update_instance(instance.slug, params,
query: [project: instance.project]
)
|> case do
{:ok, _message} ->
client

{:error, error} ->
raise "Failed to update instance config: #{inspect(error)}"
end
end
end
39 changes: 39 additions & 0 deletions lib/uplink/packages/metadata.ex
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,20 @@ defmodule Uplink.Packages.Metadata do

embeds_many :ports, __MODULE__.Port

embeds_one :package_size, Size, primary_key: false do
field :slug, :string

embeds_one :allocation, Allocation, primary_key: false do
field :cpu, :integer
field :cpu_allowance, :string, default: "100%"
field :cpu_priority, :integer, default: 10
field :memory, :integer
field :memory_unit, :string, default: "GiB"
field :memory_enforce, Ecto.Enum, values: [:hard, :soft], default: :hard
field :memory_swap, :boolean, default: false
end
end

embeds_one :channel, Channel, primary_key: false do
field :slug, :string

Expand Down Expand Up @@ -57,6 +71,7 @@ defmodule Uplink.Packages.Metadata do
|> cast_embed(:main_port)
|> cast_embed(:ports)
|> cast_embed(:variables, with: &variable_changeset/2)
|> cast_embed(:package_size, with: &package_size_changeset/2)
end

defp organization_changeset(organization, params) do
Expand All @@ -71,6 +86,30 @@ defmodule Uplink.Packages.Metadata do
|> validate_required([:key, :value])
end

defp package_size_changeset(package_size, params) do
package_size
|> cast(params, [:slug])
|> cast_embed(:allocation, with: &allocation_changeset/2)
end

defp allocation_changeset(allocation, params) do
allocation
|> cast(params, [
:cpu,
:cpu_allowance,
:cpu_priority,
:memory,
:memory_unit,
:memory_enforce,
:memory_swap
])
|> validate_inclusion(:memory_unit, ["GiB", "MiB", "GB", "MB"])
|> validate_number(:cpu_priority,
greater_than_or_equal_to: 0,
less_than_or_equal_to: 10
)
end

defp package_changeset(package, params) do
package
|> cast(params, [:slug])
Expand Down
104 changes: 104 additions & 0 deletions lib/uplink/packages/metadata/manager.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
defmodule Uplink.Packages.Metadata.Manager do
alias Uplink.Packages.Metadata
alias Uplink.Clients.LXD

defdelegate parse(params),
to: Metadata
Expand Down Expand Up @@ -32,6 +33,38 @@ defmodule Uplink.Packages.Metadata.Manager do
end
end

def get_size_profile(%Metadata{package_size: nil}), do: nil

def get_size_profile(%Metadata{} = metadata) do
size_profile = size_profile_name(metadata)

LXD.client()
|> Lexdee.get_profile(size_profile)
|> case do
{:ok, %{body: %{"name" => _name}}} ->
size_profile

{:error, %{"error_code" => 404}} ->
nil
end
end

def upsert_size_profile(%Metadata{package_size: %Metadata.Size{}} = metadata) do
size_profile = size_profile_name(metadata)

client = LXD.client()

client
|> Lexdee.get_profile(size_profile)
|> case do
{:ok, %{body: %{"name" => _name}}} ->
update_size_profile(client, metadata)

{:error, %{"error_code" => 404}} ->
create_size_profile(client, metadata)
end
end

defp create_project(client, %Metadata{} = metadata) do
project = project_name(metadata)

Expand All @@ -58,10 +91,81 @@ defmodule Uplink.Packages.Metadata.Manager do
end
end

defp create_size_profile(client, %Metadata{} = metadata) do
profile_params = build_size_config(metadata)

client
|> Lexdee.create_profile(profile_params)
|> case do
{:ok, %{body: nil}} ->
{:ok, :size_profile_created}

{:error, %{"error" => message}} ->
{:error, message}
end
end

defp update_size_profile(client, %Metadata{} = metadata) do
profile_params = build_size_config(metadata)
profile_name = profile_params["name"]

profile_params = Map.delete(profile_params, "name")

client
|> Lexdee.update_profile(profile_name, profile_params)
|> case do
{:ok, %{body: _body}} ->
{:ok, :size_profile_updated}

{:error, %{"error" => message}} ->
{:error, message}
end
end

defp build_size_config(%Metadata{package_size: package_size} = metadata) do
profile_name = size_profile_name(metadata)

config = %{
"limits.cpu.allowance" => package_size.allocation.cpu_allowance,
"limits.cpu.priority" => package_size.allocation.cpu_priority,
"limits.memory.swap" => package_size.allocation.memory_swap,
"limits.memory.enforce" => "#{package_size.allocation.memory_enforce}"
}

config =
if package_size.allocation.cpu do
Map.put(config, "limits.cpu", package_size.allocation.cpu)
else
config
end

config =
if package_size.allocation.memory do
Map.put(
config,
"limits.memory",
"#{package_size.allocation.memory}#{package_size.allocation.memory_unit}"
)
else
config
end

%{
"name" => profile_name,
"config" => config,
"description" =>
"Size profile for #{metadata.channel.package.organization.slug}/#{metadata.channel.package.slug}"
}
end

defp project_name(%Metadata{channel: channel}) do
"#{channel.package.organization.slug}.#{channel.package.slug}"
end

defp size_profile_name(%Metadata{channel: channel, package_size: package_size}) do
"size.#{channel.package.organization.slug}.#{channel.package.slug}.#{package_size.slug}"
end

def public_key_name(%Metadata{channel: channel}) do
Enum.join([channel.package.organization.slug, channel.package.slug], "-")
end
Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ defmodule Uplink.MixProject do

# Infrastructure
{:formation, "~> 0.15"},
{:lexdee, "~> 2.3"},
{:lexdee, "~> 2.4"},
{:plug_cowboy, "~> 2.0"},
{:reverse_proxy_plug, "~> 2.1"},
{:mint_web_socket, "~> 1.0.2"},
Expand Down
Loading

0 comments on commit 839408c

Please sign in to comment.