Skip to content

Commit

Permalink
Managed Deployments: Groups and Releases
Browse files Browse the repository at this point in the history
  • Loading branch information
nshoes committed Jan 15, 2025
1 parent a467823 commit 15dbf73
Show file tree
Hide file tree
Showing 62 changed files with 669 additions and 512 deletions.
2 changes: 1 addition & 1 deletion .dialyzer_ignore.exs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[
{"lib/x509/certificate.ex", "Unknown type: X509.ASN1.record/1."},
{"lib/x509/certificate/extension.ex", "Unknown type: X509.ASN1.record/1."},
{"lib/nerves_hub/deployments/orchestrator.ex", :unmatched_return, 1},
{"lib/nerves_hub/managed_deployments/orchestrator.ex", :unmatched_return, 1},
{"lib/nerves_hub_web/channels/device_channel.ex", :unmatched_return, 1},
{"lib/nerves_hub_web/channels/device_socket.ex", :unmatched_return, 1}
]
4 changes: 2 additions & 2 deletions lib/nerves_hub/accounts/remove_account.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ defmodule NervesHub.Accounts.RemoveAccount do
alias NervesHub.Accounts.OrgMetric
alias NervesHub.Accounts.OrgUser
alias NervesHub.Accounts.User
alias NervesHub.Deployments.Deployment
alias NervesHub.Devices.CACertificate
alias NervesHub.Devices.Device
alias NervesHub.Devices.DeviceCertificate
alias NervesHub.Firmwares
alias NervesHub.Firmwares.Firmware
alias NervesHub.Firmwares.FirmwareDelta
alias NervesHub.Firmwares.FirmwareTransfer
alias NervesHub.ManagedDeployments.DeploymentGroup
alias NervesHub.Products.Product

alias NervesHub.Repo
Expand All @@ -30,7 +30,7 @@ defmodule NervesHub.Accounts.RemoveAccount do
|> Multi.delete_all(:invites, &query_by_org_id(Invite, &1))
|> Multi.delete_all(:device_certificates, &query_by_org_id(DeviceCertificate, &1))
|> Multi.delete_all(:ca_certificates, &query_by_org_id(CACertificate, &1))
|> Multi.delete_all(:deployments, &query_by_org_id(Deployment, &1))
|> Multi.delete_all(:deployment_groups, &query_by_org_id(DeploymentGroup, &1))
|> Multi.delete_all(:firmware_deltas, &query_firmware_deltas/1)
|> Multi.delete_all(:firmware_transfers, &query_by_org_id(FirmwareTransfer, &1))
|> Multi.merge(&delete_firmwares/1)
Expand Down
2 changes: 1 addition & 1 deletion lib/nerves_hub/application.ex
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ defmodule NervesHub.Application do
defp deployments_supervisor("test"), do: []

defp deployments_supervisor(_) do
[NervesHub.Deployments.Supervisor]
[NervesHub.ManagedDeployments.Supervisor]
end

defp endpoints("test") do
Expand Down
6 changes: 3 additions & 3 deletions lib/nerves_hub/audit_logs.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ defmodule NervesHub.AuditLogs do
import Ecto.Query

alias NervesHub.AuditLogs.AuditLog
alias NervesHub.Deployments.Deployment
alias NervesHub.ManagedDeployments.DeploymentGroup
alias NervesHub.Repo
alias NimbleCSV.RFC4180, as: CSV

Expand Down Expand Up @@ -58,8 +58,8 @@ defmodule NervesHub.AuditLogs do
|> Flop.run(flop)
end

defp query_for_feed(%Deployment{id: id}) do
resource_type = to_string(Deployment)
defp query_for_feed(%DeploymentGroup{id: id}) do
resource_type = to_string(DeploymentGroup)

from(al in AuditLog, where: [resource_type: ^resource_type, resource_id: ^id])
|> order_by(desc: :inserted_at)
Expand Down
22 changes: 13 additions & 9 deletions lib/nerves_hub/audit_logs/templates.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ defmodule NervesHub.AuditLogs.Templates do
alias NervesHub.Accounts.User
alias NervesHub.AuditLogs
alias NervesHub.AuditLogs.AuditLog
alias NervesHub.Deployments.Deployment
alias NervesHub.Devices.Device
alias NervesHub.ManagedDeployments.DeploymentGroup

require Logger

def audit_resolve_changed_deployment(device, reference_id) do
description =
if device.deployment_id do
"device #{device.identifier} reloaded deployment and is attached to deployment #{device.deployment.name}"
"device #{device.identifier} reloaded deployment and is attached to deployment #{device.deployment_group.name}"
else
"device #{device.identifier} reloaded deployment and is no longer attached to a deployment"
end
Expand All @@ -19,18 +19,18 @@ defmodule NervesHub.AuditLogs.Templates do
end

def audit_device_deployment_update_triggered(device, reference_id) do
deployment = device.deployment
firmware = deployment.firmware
deployment_group = device.deployment_group
firmware = deployment_group.firmware

description =
"deployment #{deployment.name} update triggered device #{device.identifier} to update firmware #{firmware.uuid}"
"deployment #{deployment_group.name} update triggered device #{device.identifier} to update firmware #{firmware.uuid}"

AuditLogs.audit_with_ref!(deployment, device, description, reference_id)
AuditLogs.audit_with_ref!(deployment_group, device, description, reference_id)
end

def audit_device_assigned(device, reference_id) do
description =
"device #{device.identifier} reloaded deployment and is attached to deployment #{device.deployment.name}"
"device #{device.identifier} reloaded deployment and is attached to deployment #{device.deployment_group.name}"

AuditLogs.audit_with_ref!(device, device, description, reference_id)
end
Expand All @@ -43,7 +43,7 @@ defmodule NervesHub.AuditLogs.Templates do
Logger.info("[DeviceChannel] #{description}")
end

@spec audit_device_deployment_update(User.t(), Device.t(), Deployment.t()) :: AuditLog.t()
@spec audit_device_deployment_update(User.t(), Device.t(), DeploymentGroup.t()) :: AuditLog.t()
def audit_device_deployment_update(user, device, deployment) do
AuditLogs.audit!(
user,
Expand All @@ -52,7 +52,11 @@ defmodule NervesHub.AuditLogs.Templates do
)
end

@spec audit_device_deployment_update(Device.t(), Deployment.t(), :one_found | :multiple_found) ::
@spec audit_device_deployment_update(
Device.t(),
DeploymentGroup.t(),
:one_found | :multiple_found
) ::
AuditLog.t()
def audit_set_deployment(device, deployment, :one_found) do
AuditLogs.audit!(
Expand Down
15 changes: 0 additions & 15 deletions lib/nerves_hub/deployments/inflight_deployment_check.ex

This file was deleted.

19 changes: 0 additions & 19 deletions lib/nerves_hub/deployments/supervisor.ex

This file was deleted.

46 changes: 23 additions & 23 deletions lib/nerves_hub/devices.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ defmodule NervesHub.Devices do
alias NervesHub.Accounts.User
alias NervesHub.AuditLogs
alias NervesHub.Certificate
alias NervesHub.Deployments.Deployment
alias NervesHub.Deployments.Orchestrator
alias NervesHub.Devices.CACertificate
alias NervesHub.Devices.Connections
alias NervesHub.Devices.Device
Expand All @@ -24,6 +22,8 @@ defmodule NervesHub.Devices do
alias NervesHub.Firmwares
alias NervesHub.Firmwares.Firmware
alias NervesHub.Firmwares.FirmwareMetadata
alias NervesHub.ManagedDeployments.DeploymentGroup
alias NervesHub.ManagedDeployments.Orchestrator
alias NervesHub.Products
alias NervesHub.Products.Product
alias NervesHub.Repo
Expand Down Expand Up @@ -86,12 +86,12 @@ defmodule NervesHub.Devices do
|> where([d], d.product_id == ^product_id)
|> join(:left, [d], o in assoc(d, :org))
|> join(:left, [d, o], p in assoc(d, :product))
|> join(:left, [d, o, p], dp in assoc(d, :deployment))
|> join(:left, [d, o, p], dp in assoc(d, :deployment_group))
|> join(:left, [d, o, p, dp], f in assoc(dp, :firmware))
|> Repo.exclude_deleted()
|> order_by(^sort_devices(sorting))
|> Filtering.build_filters(filters)
|> preload([d, o, p, dp, f], org: o, product: p, deployment: {dp, firmware: f})
|> preload([d, o, p, dp, f], org: o, product: p, deployment_group: {dp, firmware: f})
|> Connections.preload_latest_connection()
|> Flop.run(flop)
end
Expand Down Expand Up @@ -256,7 +256,7 @@ defmodule NervesHub.Devices do
{:error, :not_found}

device ->
{:ok, Repo.preload(device, [:org, :product, deployment: [:firmware]])}
{:ok, Repo.preload(device, [:org, :product, deployment_group: [:firmware]])}
end
end

Expand All @@ -283,9 +283,9 @@ defmodule NervesHub.Devices do
|> where(identifier: ^identifier)
|> where(org_id: ^org_id)
|> join(:left, [d], o in assoc(d, :org))
|> join(:left, [d], dp in assoc(d, :deployment))
|> join(:left, [d], dp in assoc(d, :deployment_group))
|> join_and_preload(preload_assoc)
|> preload([d, o, dp], org: o, deployment: dp)
|> preload([d, o, dp], org: o, deployment_group: dp)
end

defp join_and_preload(query, nil), do: query
Expand Down Expand Up @@ -357,7 +357,7 @@ defmodule NervesHub.Devices do

def get_eligible_deployments(%Device{firmware_metadata: meta} = device) do
from(
d in Deployment,
d in DeploymentGroup,
join: p in assoc(d, :product),
on: [org_id: ^device.org_id, name: ^meta.product],
join: f in assoc(d, :firmware),
Expand Down Expand Up @@ -627,7 +627,7 @@ defmodule NervesHub.Devices do
@spec get_device_firmware_for_delta_generation_by_product(binary()) ::
list({source_firmware_id(), target_firmware_id()})
def get_device_firmware_for_delta_generation_by_product(product_id) do
Deployment
DeploymentGroup
|> where([dep], dep.product_id == ^product_id)
|> join(:inner, [dep], dev in Device, on: dev.deployment_id == dep.id)
|> join(:inner, [dep, dev], f in Firmware,
Expand All @@ -642,7 +642,7 @@ defmodule NervesHub.Devices do
@spec get_device_firmware_for_delta_generation_by_deployment(binary()) ::
list({source_firmware_id(), target_firmware_id()})
def get_device_firmware_for_delta_generation_by_deployment(deployment_id) do
Deployment
DeploymentGroup
|> where([dep], dep.id == ^deployment_id)
|> join(:inner, [dep], dev in Device, on: dev.deployment_id == dep.id)
|> join(:inner, [dep, dev], f in Firmware,
Expand Down Expand Up @@ -708,7 +708,7 @@ defmodule NervesHub.Devices do
end

def resolve_update(device) do
deployment = Repo.preload(device.deployment, [:firmware])
deployment = Repo.preload(device.deployment_group, [:firmware])

case verify_update_eligibility(device, deployment) do
{:ok, _device} ->
Expand All @@ -719,7 +719,7 @@ defmodule NervesHub.Devices do
update_available: true,
firmware_url: url,
firmware_meta: meta,
deployment: deployment,
deployment_group: deployment,
deployment_id: deployment.id
}

Expand Down Expand Up @@ -754,7 +754,7 @@ defmodule NervesHub.Devices do
"""
def matches_deployment?(
%Device{tags: tags, firmware_metadata: %FirmwareMetadata{version: version}},
%Deployment{conditions: %{"version" => requirement, "tags" => dep_tags}}
%DeploymentGroup{conditions: %{"version" => requirement, "tags" => dep_tags}}
) do
if version_match?(version, requirement) and tags_match?(tags, dep_tags) do
true
Expand All @@ -765,7 +765,7 @@ defmodule NervesHub.Devices do

def matches_deployment?(_, _), do: false

@spec update_deployment(Device.t(), Deployment.t()) :: Device.t()
@spec update_deployment(Device.t(), DeploymentGroup.t()) :: Device.t()
def update_deployment(device, deployment) do
device
|> Ecto.Changeset.change()
Expand All @@ -781,13 +781,13 @@ defmodule NervesHub.Devices do
|> Repo.update!()
end

@spec failure_threshold_met?(Device.t(), Deployment.t()) :: boolean()
def failure_threshold_met?(%Device{} = device, %Deployment{} = deployment) do
@spec failure_threshold_met?(Device.t(), DeploymentGroup.t()) :: boolean()
def failure_threshold_met?(%Device{} = device, %DeploymentGroup{} = deployment) do
Enum.count(device.update_attempts) >= deployment.device_failure_threshold
end

@spec failure_rate_met?(Device.t(), Deployment.t()) :: boolean()
def failure_rate_met?(%Device{} = device, %Deployment{} = deployment) do
@spec failure_rate_met?(Device.t(), DeploymentGroup.t()) :: boolean()
def failure_rate_met?(%Device{} = device, %DeploymentGroup{} = deployment) do
seconds_ago =
Timex.shift(DateTime.utc_now(), seconds: -deployment.device_failure_rate_seconds)

Expand Down Expand Up @@ -918,7 +918,7 @@ defmodule NervesHub.Devices do
if inflight_update != nil do
Orchestrator.device_updated(inflight_update.deployment_id)

Deployment
DeploymentGroup
|> where([d], d.id == ^inflight_update.deployment_id)
|> Repo.update_all(inc: [current_updated_devices: 1])

Expand Down Expand Up @@ -983,7 +983,7 @@ defmodule NervesHub.Devices do
|> Repo.transaction()
|> case do
{:ok, %{move: updated}} ->
_ = broadcast(updated, "moved")
# Deployments.set_deployment(updated)
{:ok, updated}

err ->
Expand Down Expand Up @@ -1056,7 +1056,7 @@ defmodule NervesHub.Devices do
{:ok, %{updated: non_neg_integer(), ignored: non_neg_integer()}}
def move_many_to_deployment(device_ids, deployment_id) do
%{firmware: firmware} =
Deployment |> where(id: ^deployment_id) |> preload(:firmware) |> Repo.one()
DeploymentGroup |> where(id: ^deployment_id) |> preload(:firmware) |> Repo.one()

{devices_updated_count, _} =
Device
Expand Down Expand Up @@ -1300,14 +1300,14 @@ defmodule NervesHub.Devices do
|> Repo.update!()
end

def inflight_updates_for(%Deployment{} = deployment) do
def inflight_updates_for(%DeploymentGroup{} = deployment) do
InflightUpdate
|> where([iu], iu.deployment_id == ^deployment.id)
|> preload([:device])
|> Repo.all()
end

def count_inflight_updates_for(%Deployment{} = deployment) do
def count_inflight_updates_for(%DeploymentGroup{} = deployment) do
InflightUpdate
|> select([iu], count(iu))
|> where([iu], iu.deployment_id == ^deployment.id)
Expand Down
8 changes: 6 additions & 2 deletions lib/nerves_hub/devices/device.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ defmodule NervesHub.Devices.Device do
import Ecto.Changeset

alias NervesHub.Accounts.Org
alias NervesHub.Deployments.Deployment
alias NervesHub.Devices.DeviceCertificate
alias NervesHub.Devices.DeviceConnection
alias NervesHub.Devices.DeviceMetric
alias NervesHub.Extensions.DeviceExtensionsSetting
alias NervesHub.Firmwares.FirmwareMetadata
alias NervesHub.ManagedDeployments.DeploymentGroup
alias NervesHub.Products.Product

alias __MODULE__
Expand Down Expand Up @@ -40,7 +40,7 @@ defmodule NervesHub.Devices.Device do
schema "devices" do
belongs_to(:org, Org, where: [deleted_at: nil])
belongs_to(:product, Product, where: [deleted_at: nil])
belongs_to(:deployment, Deployment)
belongs_to(:deployment_group, DeploymentGroup, foreign_key: :deployment_id)
embeds_one(:firmware_metadata, FirmwareMetadata, on_replace: :update)
has_many(:device_certificates, DeviceCertificate, on_delete: :delete_all)
has_many(:device_connections, DeviceConnection, on_delete: :delete_all)
Expand All @@ -65,6 +65,10 @@ defmodule NervesHub.Devices.Device do
field(:connecting_code, :string)
field(:connection_metadata, :map, default: %{})

field(:deployment_conflict, Ecto.Enum,
values: [:bad_architecture, :bad_platform, :bad_architecture_and_platform]
)

timestamps()

# Deprecated fields, replaced with device_connections table.
Expand Down
4 changes: 2 additions & 2 deletions lib/nerves_hub/devices/inflight_update.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@ defmodule NervesHub.Devices.InflightUpdate do

import Ecto.Changeset

alias NervesHub.Deployments.Deployment
alias NervesHub.Devices.Device
alias NervesHub.Devices.InflightUpdate
alias NervesHub.Firmwares.Firmware
alias NervesHub.ManagedDeployments.DeploymentGroup

@required_params [:device_id, :deployment_id, :firmware_id, :firmware_uuid, :expires_at]

schema "inflight_updates" do
belongs_to(:device, Device)
belongs_to(:deployment, Deployment)
belongs_to(:deployment_group, DeploymentGroup, foreign_key: :deployment_id)
belongs_to(:firmware, Firmware)

field(:firmware_uuid, Ecto.UUID)
Expand Down
Loading

0 comments on commit 15dbf73

Please sign in to comment.