diff --git a/lib/nerves_hub/deployments.ex b/lib/nerves_hub/deployments.ex
index 610daca56..ae909ec9c 100644
--- a/lib/nerves_hub/deployments.ex
+++ b/lib/nerves_hub/deployments.ex
@@ -6,7 +6,6 @@ defmodule NervesHub.Deployments do
alias NervesHub.AuditLogs
alias NervesHub.Deployments.Deployment
alias NervesHub.Deployments.InflightDeploymentCheck
- alias NervesHub.Devices
alias NervesHub.Devices.Device
alias NervesHub.Products.Product
alias NervesHub.Repo
@@ -276,38 +275,6 @@ defmodule NervesHub.Deployments do
Phoenix.PubSub.broadcast(NervesHub.PubSub, "deployment:#{id}", message)
end
- @doc """
- Find all potential deployments for a device
-
- Based on the product, firmware platform, firmware architecture, and device tags
- """
- def alternate_deployments(device, active \\ [true, false])
- def alternate_deployments(%Device{firmware_metadata: nil}, _active), do: []
-
- def alternate_deployments(device, active) do
- Deployment
- |> join(:inner, [d], assoc(d, :firmware), as: :firmware)
- |> preload([_, firmware: f], firmware: f)
- |> where([d], d.product_id == ^device.product_id)
- |> where([d], d.is_active in ^active)
- |> ignore_same_deployment(device)
- |> where([d, firmware: f], f.platform == ^device.firmware_metadata.platform)
- |> where([d, firmware: f], f.architecture == ^device.firmware_metadata.architecture)
- |> where([d], fragment("?->'tags' <@ to_jsonb(?::text[])", d.conditions, ^device.tags))
- |> Repo.all()
- |> Enum.filter(&version_match?(device, &1))
- |> Enum.sort_by(
- &{&1.firmware.version, &1.id},
- fn {a_vsn, a_id}, {b_vsn, b_id} ->
- case Version.compare(a_vsn, b_vsn) do
- :lt -> false
- :eq -> a_id <= b_id
- :gt -> true
- end
- end
- )
- end
-
@doc """
Find all potential devices for a deployment
@@ -336,61 +303,36 @@ defmodule NervesHub.Deployments do
def version_match?(_device, _deployment), do: true
- defp ignore_same_deployment(query, %{deployment_id: nil}), do: query
-
- defp ignore_same_deployment(query, %{deployment_id: deployment_id}) do
- where(query, [d], d.id != ^deployment_id)
- end
-
- @doc """
- If the device is missing a deployment, find a matching deployment
-
- Do nothing if a deployment is already set
- """
- @spec set_deployment(Device.t()) :: Device.t()
- def set_deployment(device) do
- case alternate_deployments(device, [true]) do
- [] ->
- Logger.debug("No matching deployments for #{device.identifier}")
-
- device
-
- [deployment] ->
- device
- |> Devices.update_deployment(deployment)
- |> preload_with_firmware_and_archive(true)
-
- [deployment | _] ->
- Logger.debug(
- "More than one deployment matches for #{device.identifier}, setting to the first"
- )
-
- device
- |> Devices.update_deployment(deployment)
- |> preload_with_firmware_and_archive(true)
- end
- end
-
- @spec maybe_set_deployment(Device.t()) :: Device.t()
- def maybe_set_deployment(%Device{deployment_id: nil} = device), do: set_deployment(device)
- def maybe_set_deployment(device), do: device
-
@spec verify_deployment_membership(Device.t()) :: Device.t()
def verify_deployment_membership(%Device{deployment_id: deployment_id} = device)
when not is_nil(deployment_id) do
%{deployment: deployment} = device = Repo.preload(device, deployment: :firmware)
+ bad_architecture = device.firmware_metadata.architecture != deployment.firmware.architecture
+ bad_platform = device.firmware_metadata.platform != deployment.firmware.platform
+
+ reason =
+ cond do
+ bad_architecture and bad_platform ->
+ :bad_architecture_and_platform
- if device.firmware_metadata.platform == deployment.firmware.platform and
- device.firmware_metadata.architecture == deployment.firmware.architecture do
+ bad_architecture ->
+ :bad_architecture
+
+ bad_platform ->
+ :bad_platform
+
+ true ->
+ nil
+ end
+
+ if reason do
device
+ |> Ecto.Changeset.change(%{deployment_id: nil, deployment_conflict: reason})
+ |> Repo.update!()
else
- Devices.clear_deployment(device)
+ device
end
end
def verify_deployment_membership(device), do: device
-
- def preload_with_firmware_and_archive(device, force \\ false) do
- Repo.preload(device, [deployment: [:archive, :firmware]], force: force)
- end
end
diff --git a/lib/nerves_hub/devices.ex b/lib/nerves_hub/devices.ex
index 866cd3600..4625a1733 100644
--- a/lib/nerves_hub/devices.ex
+++ b/lib/nerves_hub/devices.ex
@@ -9,7 +9,6 @@ defmodule NervesHub.Devices do
alias NervesHub.Accounts.User
alias NervesHub.AuditLogs
alias NervesHub.Certificate
- alias NervesHub.Deployments
alias NervesHub.Deployments.Deployment
alias NervesHub.Deployments.Orchestrator
alias NervesHub.Devices.CACertificate
@@ -1035,7 +1034,7 @@ defmodule NervesHub.Devices do
|> Repo.transaction()
|> case do
{:ok, %{move: updated}} ->
- Deployments.set_deployment(updated)
+ # Deployments.set_deployment(updated)
{:ok, updated}
err ->
@@ -1350,29 +1349,6 @@ defmodule NervesHub.Devices do
|> Repo.one()
end
- @doc """
- Get the firmware status for a device
-
- "latest", "pending", or "updating"
- """
- def firmware_status(device) do
- device = Repo.preload(device, deployment: [:firmware])
-
- cond do
- is_nil(device.deployment_id) ->
- "latest"
-
- get_in(device.firmware_metadata.uuid) == get_in(device.deployment.firmware.uuid) ->
- "latest"
-
- !Enum.empty?(device.update_attempts) ->
- "updating"
-
- true ->
- "pending"
- end
- end
-
def enable_extension_setting(%Device{} = device, extension_string) do
device = get_device(device.id)
diff --git a/lib/nerves_hub/devices/device.ex b/lib/nerves_hub/devices/device.ex
index b97fa3c19..edc6ce1b5 100644
--- a/lib/nerves_hub/devices/device.ex
+++ b/lib/nerves_hub/devices/device.ex
@@ -63,6 +63,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.
diff --git a/lib/nerves_hub_web/channels/device_channel.ex b/lib/nerves_hub_web/channels/device_channel.ex
index d1c71889e..e6fe13a8e 100644
--- a/lib/nerves_hub_web/channels/device_channel.ex
+++ b/lib/nerves_hub_web/channels/device_channel.ex
@@ -37,7 +37,6 @@ defmodule NervesHubWeb.DeviceChannel do
device =
device
|> Deployments.verify_deployment_membership()
- |> Deployments.maybe_set_deployment()
maybe_send_public_keys(device, socket, params)
@@ -457,7 +456,7 @@ defmodule NervesHubWeb.DeviceChannel do
end
defp maybe_send_archive(socket) do
- device = socket.assigns.device
+ device = deployment_preload(socket.assigns.device)
updates_enabled = device.updates_enabled && !Devices.device_in_penalty_box?(device)
version_match = Version.match?(socket.assigns.device_api_version, ">= 2.0.0")
diff --git a/lib/nerves_hub_web/live/deployments/edit.html.heex b/lib/nerves_hub_web/live/deployments/edit.html.heex
index 1827d8167..8a7857066 100644
--- a/lib/nerves_hub_web/live/deployments/edit.html.heex
+++ b/lib/nerves_hub_web/live/deployments/edit.html.heex
@@ -67,13 +67,9 @@
-
-
-
- Changing the version requirement will reset all devices on this deployment
-
+
+
<%= text_input(f, :version,
class: "form-control",
id: "version_requirement",
diff --git a/lib/nerves_hub_web/views/api/device_view.ex b/lib/nerves_hub_web/views/api/device_view.ex
index 72e62bd8c..ea483bf5f 100644
--- a/lib/nerves_hub_web/views/api/device_view.ex
+++ b/lib/nerves_hub_web/views/api/device_view.ex
@@ -1,7 +1,6 @@
defmodule NervesHubWeb.API.DeviceView do
use NervesHubWeb, :api_view
- alias NervesHub.Devices
alias NervesHub.Tracker
def render("index.json", %{devices: devices, pagination: pagination}) do
@@ -29,7 +28,6 @@ defmodule NervesHubWeb.API.DeviceView do
last_communication: connection_last_seen_at(device),
description: device.description,
firmware_metadata: device.firmware_metadata,
- firmware_update_status: Devices.firmware_status(device),
deployment: render_one(device.deployment, __MODULE__, "deployment.json", as: :deployment),
updates_enabled: device.updates_enabled,
updates_blocked_until: device.updates_blocked_until,
diff --git a/priv/repo/migrations/20241126000914_add_deployment_conflict_to_devices.exs b/priv/repo/migrations/20241126000914_add_deployment_conflict_to_devices.exs
new file mode 100644
index 000000000..3aa9459b9
--- /dev/null
+++ b/priv/repo/migrations/20241126000914_add_deployment_conflict_to_devices.exs
@@ -0,0 +1,9 @@
+defmodule NervesHub.Repo.Migrations.AddDeploymentConflictToDevices do
+ use Ecto.Migration
+
+ def change do
+ alter table(:devices) do
+ add(:deployment_conflict, :text)
+ end
+ end
+end
diff --git a/test/nerves_hub/deployments_test.exs b/test/nerves_hub/deployments_test.exs
index 5747b2c3e..a8695f5b1 100644
--- a/test/nerves_hub/deployments_test.exs
+++ b/test/nerves_hub/deployments_test.exs
@@ -3,7 +3,6 @@ defmodule NervesHub.DeploymentsTest do
import Phoenix.ChannelTest
alias NervesHub.Deployments
- alias NervesHub.Devices.Device
alias NervesHub.Fixtures
alias Ecto.Changeset
@@ -125,171 +124,4 @@ defmodule NervesHub.DeploymentsTest do
assert_broadcast("deployments/update", %{}, 500)
end
end
-
- describe "device's matching deployments" do
- test "finds all matching deployments", state do
- %{org: org, product: product, firmware: firmware} = state
-
- %{id: beta_deployment_id} =
- Fixtures.deployment_fixture(org, firmware, %{
- name: "beta",
- conditions: %{"tags" => ["beta"]}
- })
-
- %{id: rpi_deployment_id} =
- Fixtures.deployment_fixture(org, firmware, %{
- name: "rpi",
- conditions: %{"tags" => ["rpi"]}
- })
-
- Fixtures.deployment_fixture(org, firmware, %{
- name: "rpi0",
- conditions: %{"tags" => ["rpi0"]}
- })
-
- device = Fixtures.device_fixture(org, product, firmware, %{tags: ["beta", "rpi"]})
-
- assert [
- %{id: ^beta_deployment_id},
- %{id: ^rpi_deployment_id}
- ] = Deployments.alternate_deployments(device)
- end
-
- test "finds matching deployments including the platform", state do
- %{org: org, org_key: org_key, product: product} = state
-
- rpi_firmware = Fixtures.firmware_fixture(org_key, product, %{platform: "rpi"})
- rpi0_firmware = Fixtures.firmware_fixture(org_key, product, %{platform: "rpi0"})
-
- %{id: rpi_deployment_id} =
- Fixtures.deployment_fixture(org, rpi_firmware, %{
- name: "rpi",
- conditions: %{"tags" => ["rpi"]}
- })
-
- Fixtures.deployment_fixture(org, rpi0_firmware, %{
- name: "rpi0",
- conditions: %{"tags" => ["rpi"]}
- })
-
- device = Fixtures.device_fixture(org, product, rpi_firmware, %{tags: ["beta", "rpi"]})
-
- assert [%{id: ^rpi_deployment_id}] = Deployments.alternate_deployments(device)
- end
-
- test "finds matching deployments including the architecture", state do
- %{org: org, org_key: org_key, product: product} = state
-
- rpi_firmware = Fixtures.firmware_fixture(org_key, product, %{architecture: "rpi"})
- rpi0_firmware = Fixtures.firmware_fixture(org_key, product, %{architecture: "rpi0"})
-
- %{id: rpi_deployment_id} =
- Fixtures.deployment_fixture(org, rpi_firmware, %{
- name: "rpi",
- conditions: %{"tags" => ["rpi"]}
- })
-
- Fixtures.deployment_fixture(org, rpi0_firmware, %{
- name: "rpi0",
- conditions: %{"tags" => ["rpi"]}
- })
-
- device = Fixtures.device_fixture(org, product, rpi_firmware, %{tags: ["beta", "rpi"]})
-
- assert [%{id: ^rpi_deployment_id}] = Deployments.alternate_deployments(device)
- end
-
- test "finds matching deployments including the version", state do
- %{org: org, product: product, firmware: firmware} = state
-
- %{id: low_deployment_id} =
- Fixtures.deployment_fixture(org, firmware, %{
- name: "rpi",
- conditions: %{"tags" => ["rpi"], "version" => "~> 1.0"}
- })
-
- Fixtures.deployment_fixture(org, firmware, %{
- name: "rpi0",
- conditions: %{"tags" => ["rpi"], "version" => "~> 2.0"}
- })
-
- device = Fixtures.device_fixture(org, product, firmware, %{tags: ["beta", "rpi"]})
-
- assert [%{id: ^low_deployment_id}] = Deployments.alternate_deployments(device)
- end
-
- test "finds matching deployments including pre versions", state do
- %{org: org, org_key: org_key, product: product, firmware: firmware} = state
-
- %{id: low_deployment_id} =
- Fixtures.deployment_fixture(org, firmware, %{
- name: "rpi",
- conditions: %{"tags" => ["rpi"], "version" => "~> 1.0"}
- })
-
- Fixtures.deployment_fixture(org, firmware, %{
- name: "rpi0",
- conditions: %{"tags" => ["rpi"], "version" => "~> 2.0"}
- })
-
- firmware = Fixtures.firmware_fixture(org_key, product, %{version: "1.2.0-pre"})
-
- device = Fixtures.device_fixture(org, product, firmware, %{tags: ["beta", "rpi"]})
-
- assert [%{id: ^low_deployment_id}] = Deployments.alternate_deployments(device)
- end
-
- test "finds the newest firmware version including pre-releases", state do
- %{
- org: org,
- org_key: org_key,
- product: product,
- firmware: %{version: "1.0.0"} = v100_firmware
- } = state
-
- v090_fw = Fixtures.firmware_fixture(org_key, product, %{version: "0.9.0"})
- v100rc1_fw = Fixtures.firmware_fixture(org_key, product, %{version: "1.0.0-rc.1"})
- v100rc2_fw = Fixtures.firmware_fixture(org_key, product, %{version: "1.0.0-rc.2"})
- v101_fw = Fixtures.firmware_fixture(org_key, product, %{version: "1.0.1"})
-
- %{id: v100_deployment_id} =
- Fixtures.deployment_fixture(org, v100_firmware, %{
- name: v100_firmware.version,
- conditions: %{"version" => "", "tags" => ["next"]}
- })
-
- %{id: v100rc1_deployment_id} =
- Fixtures.deployment_fixture(org, v100rc1_fw, %{
- name: v100rc1_fw.version,
- conditions: %{"version" => "", "tags" => ["next"]}
- })
-
- %{id: v100rc2_deployment_id} =
- Fixtures.deployment_fixture(org, v100rc2_fw, %{
- name: v100rc2_fw.version,
- conditions: %{"version" => "", "tags" => ["next"]}
- })
-
- %{id: v101_deployment_id} =
- Fixtures.deployment_fixture(org, v101_fw, %{
- name: v101_fw.version,
- conditions: %{"version" => "", "tags" => ["next"]}
- })
-
- device = Fixtures.device_fixture(org, product, v090_fw, %{tags: ["next"]})
-
- assert [
- %{id: ^v101_deployment_id},
- %{id: ^v100_deployment_id},
- %{id: ^v100rc2_deployment_id},
- %{id: ^v100rc1_deployment_id}
- ] = Deployments.alternate_deployments(device)
- end
- end
-
- test "alternate_deployments/2 ignores device without firmware metadata" do
- assert [] == Deployments.alternate_deployments(%Device{firmware_metadata: nil})
- assert [] == Deployments.alternate_deployments(%Device{firmware_metadata: nil}, [true])
- assert [] == Deployments.alternate_deployments(%Device{firmware_metadata: nil}, [false])
- end
end
diff --git a/test/nerves_hub/devices_test.exs b/test/nerves_hub/devices_test.exs
index b06fb1fb9..9c2761b60 100644
--- a/test/nerves_hub/devices_test.exs
+++ b/test/nerves_hub/devices_test.exs
@@ -720,133 +720,6 @@ defmodule NervesHub.DevicesTest do
end
end
- describe "firmware status" do
- test "latest: no deployment" do
- user = Fixtures.user_fixture()
- org = Fixtures.org_fixture(user, %{name: "org"})
- product = Fixtures.product_fixture(user, org)
- org_key = Fixtures.org_key_fixture(org, user)
- firmware = Fixtures.firmware_fixture(org_key, product)
-
- device = Fixtures.device_fixture(org, product, firmware, %{tags: ["alpha"]})
-
- refute device.deployment_id
- assert Devices.firmware_status(device) == "latest"
- end
-
- test "latest: firmware matches the deployment" do
- user = Fixtures.user_fixture()
- org = Fixtures.org_fixture(user, %{name: "org"})
- product = Fixtures.product_fixture(user, org)
- org_key = Fixtures.org_key_fixture(org, user)
- firmware = Fixtures.firmware_fixture(org_key, product)
-
- deployment =
- Fixtures.deployment_fixture(org, firmware, %{
- name: "alpha",
- conditions: %{"tags" => ["alpha"]}
- })
-
- {:ok, deployment} = Deployments.update_deployment(deployment, %{is_active: true})
-
- device = Fixtures.device_fixture(org, product, firmware, %{tags: ["alpha"]})
- device = Deployments.set_deployment(device)
-
- assert device.deployment_id == deployment.id
- assert device.updates_enabled
-
- assert Devices.firmware_status(device) == "latest"
- end
-
- test "updating: there are update attempts" do
- user = Fixtures.user_fixture()
- org = Fixtures.org_fixture(user, %{name: "org"})
- product = Fixtures.product_fixture(user, org)
- org_key = Fixtures.org_key_fixture(org, user)
- firmware_one = Fixtures.firmware_fixture(org_key, product)
- firmware_two = Fixtures.firmware_fixture(org_key, product)
-
- deployment =
- Fixtures.deployment_fixture(org, firmware_one, %{
- name: "alpha",
- conditions: %{"tags" => ["alpha"]}
- })
-
- {:ok, deployment} = Deployments.update_deployment(deployment, %{is_active: true})
-
- device = Fixtures.device_fixture(org, product, firmware_two, %{tags: ["alpha"]})
- device = Deployments.set_deployment(device)
- {:ok, device} = Devices.update_attempted(device)
-
- assert device.deployment_id == deployment.id
- assert device.updates_enabled
-
- assert Devices.firmware_status(device) == "updating"
- end
-
- test "pending: updates are disabled" do
- user = Fixtures.user_fixture()
- org = Fixtures.org_fixture(user, %{name: "org"})
- product = Fixtures.product_fixture(user, org)
- org_key = Fixtures.org_key_fixture(org, user)
- firmware_one = Fixtures.firmware_fixture(org_key, product)
- firmware_two = Fixtures.firmware_fixture(org_key, product)
-
- deployment =
- Fixtures.deployment_fixture(org, firmware_one, %{
- name: "alpha",
- conditions: %{"tags" => ["alpha"]}
- })
-
- {:ok, deployment} = Deployments.update_deployment(deployment, %{is_active: true})
-
- device = Fixtures.device_fixture(org, product, firmware_two, %{tags: ["alpha"]})
- device = Deployments.set_deployment(device)
- {:ok, device} = Devices.disable_updates(device, user)
-
- assert device.deployment_id == deployment.id
- refute device.updates_enabled
-
- assert Devices.firmware_status(device) == "pending"
- end
-
- test "pending: still waiting on updating" do
- user = Fixtures.user_fixture()
- org = Fixtures.org_fixture(user, %{name: "org"})
- product = Fixtures.product_fixture(user, org)
- org_key = Fixtures.org_key_fixture(org, user)
- firmware_one = Fixtures.firmware_fixture(org_key, product)
- firmware_two = Fixtures.firmware_fixture(org_key, product)
-
- deployment =
- Fixtures.deployment_fixture(org, firmware_one, %{
- name: "alpha",
- conditions: %{"tags" => ["alpha"]}
- })
-
- {:ok, deployment} = Deployments.update_deployment(deployment, %{is_active: true})
-
- device = Fixtures.device_fixture(org, product, firmware_two, %{tags: ["alpha"]})
- device = Deployments.set_deployment(device)
-
- assert device.deployment_id == deployment.id
- assert device.updates_enabled
-
- assert Devices.firmware_status(device) == "pending"
- end
-
- test "safe against missing metadata", %{device: device} do
- # This is mostly for race conditions between finishing the DB write
- # of related firmware metadata or deployment update and reading the
- # record back in with a firmware_status (i.e via API request)
- # In those rare cases we might have missing data and need to be able to
- # handle it
- missing_meta_device = %{device | deployment: nil, firmware_metadata: nil}
-
- assert Devices.firmware_status(missing_meta_device) == "latest"
- end
- end
-
describe "inflight updates" do
test "clears expired inflight updates", %{device: device, deployment: deployment} do
deployment = Repo.preload(deployment, :firmware)
diff --git a/test/nerves_hub_web/channels/device_channel_test.exs b/test/nerves_hub_web/channels/device_channel_test.exs
index 11ba9160c..89b97b359 100644
--- a/test/nerves_hub_web/channels/device_channel_test.exs
+++ b/test/nerves_hub_web/channels/device_channel_test.exs
@@ -128,54 +128,6 @@ defmodule NervesHubWeb.DeviceChannelTest do
assert device.connection_types == [:ethernet, :wifi]
end
- test "deployment condition changing causes a deployment relookup but it still matches" do
- user = Fixtures.user_fixture()
- org = Fixtures.org_fixture(user)
- product = Fixtures.product_fixture(user, org)
- org_key = Fixtures.org_key_fixture(org, user)
-
- firmware =
- Fixtures.firmware_fixture(org_key, product, %{
- version: "0.0.1"
- })
-
- deployment =
- Fixtures.deployment_fixture(org, firmware, %{
- conditions: %{"tags" => ["alpha"], "version" => ""}
- })
-
- {:ok, deployment} =
- NervesHub.Deployments.update_deployment(deployment, %{
- is_active: true
- })
-
- device_alpha =
- Fixtures.device_fixture(org, product, firmware, %{
- tags: ["alpha", "device"],
- identifier: "123"
- })
-
- %{db_cert: alpha_certificate, cert: _cert} =
- Fixtures.device_certificate_fixture(device_alpha, X509.PrivateKey.new_ec(:secp256r1))
-
- {:ok, socket_alpha} =
- connect(DeviceSocket, %{}, connect_info: %{peer_data: %{ssl_cert: alpha_certificate.der}})
-
- {:ok, %{}, socket_alpha} =
- subscribe_and_join(socket_alpha, DeviceChannel, "device")
-
- socket_alpha = :sys.get_state(socket_alpha.channel_pid)
- refute is_nil(socket_alpha.assigns.device.deployment_id)
-
- {:ok, _deployment} =
- NervesHub.Deployments.update_deployment(deployment, %{
- conditions: %{"tags" => ["alpha", "device"]}
- })
-
- socket_alpha = :sys.get_state(socket_alpha.channel_pid)
- refute is_nil(socket_alpha.assigns.device.deployment_id)
- end
-
describe "unhandled messages are caught" do
test "handle_info" do
user = Fixtures.user_fixture()
diff --git a/test/nerves_hub_web/channels/websocket_test.exs b/test/nerves_hub_web/channels/websocket_test.exs
index f43916460..a9b37f1d8 100644
--- a/test/nerves_hub_web/channels/websocket_test.exs
+++ b/test/nerves_hub_web/channels/websocket_test.exs
@@ -6,7 +6,6 @@ defmodule NervesHubWeb.WebsocketTest do
import TrackerHelper
alias NervesHub.Fixtures
- alias NervesHub.Accounts
alias NervesHub.Deployments
alias NervesHub.Deployments.Orchestrator
alias NervesHub.Devices
@@ -643,26 +642,35 @@ defmodule NervesHubWeb.WebsocketTest do
user: user,
tmp_dir: tmp_dir
} do
- {device, firmware} = device_fixture(tmp_dir, user, %{identifier: @valid_serial})
-
- device = NervesHub.Repo.preload(device, :org)
- firmware = NervesHub.Repo.preload(firmware, :product)
+ org = Fixtures.org_fixture(user)
+ org_key = Fixtures.org_key_fixture(org, user, tmp_dir)
+ product = Fixtures.product_fixture(user, org)
- Fixtures.device_certificate_fixture(device)
- org_key = Fixtures.org_key_fixture(device.org, user, tmp_dir)
+ firmware =
+ Fixtures.firmware_fixture(org_key, product, %{
+ version: "0.0.1",
+ dir: tmp_dir
+ })
+ |> Repo.preload([:product])
- deployment =
- Fixtures.deployment_fixture(device.org, firmware, %{
+ {:ok, deployment} =
+ Fixtures.deployment_fixture(org, firmware, %{
name: "a different name",
conditions: %{
- "tags" => ["beta", "beta-edge"]
+ "tags" => ["beta"]
}
})
+ |> Deployments.update_deployment(%{is_active: true})
+
+ device =
+ Fixtures.device_fixture(
+ org,
+ product,
+ firmware,
+ %{tags: ["beta", "beta-edge"], identifier: @valid_serial, deployment_id: deployment.id}
+ )
- {:ok, deployment} =
- Deployments.update_deployment(deployment, %{
- is_active: true
- })
+ Fixtures.device_certificate_fixture(device)
{:ok, socket} = SocketClient.start_link(@socket_config)
SocketClient.join_and_wait(socket)
@@ -726,25 +734,44 @@ defmodule NervesHubWeb.WebsocketTest do
SocketClient.clean_close(socket)
end
- test "removes device from deployment if firmware doesn't match", %{
- user: user,
- tmp_dir: tmp_dir
- } do
- {device, firmware} =
- device_fixture(tmp_dir, user, %{identifier: @valid_serial, product: @valid_product})
+ test "removes device from deployment and sets reason if firmware doesn't match",
+ %{
+ user: user,
+ tmp_dir: tmp_dir
+ } do
+ org = Fixtures.org_fixture(user)
+ product = Fixtures.product_fixture(user, org)
+ org_key = Fixtures.org_key_fixture(org, user, tmp_dir)
- org = %Accounts.Org{id: device.org_id}
+ firmware =
+ Fixtures.firmware_fixture(org_key, product, %{
+ version: "0.0.1",
+ dir: tmp_dir
+ })
- Fixtures.deployment_fixture(org, firmware, %{
- name: "a different name",
- conditions: %{
- "version" => "~> 0.0.1",
- "tags" => ["beta", "beta-edge"]
- }
- })
- |> Deployments.update_deployment(%{is_active: true})
+ {:ok, deployment} =
+ Fixtures.deployment_fixture(org, firmware, %{
+ name: "a different name",
+ conditions: %{
+ "version" => "~> 0.0.1",
+ "tags" => ["beta", "beta-edge"]
+ }
+ })
+ |> Deployments.update_deployment(%{is_active: true})
+
+ device =
+ Fixtures.device_fixture(
+ org,
+ product,
+ firmware,
+ %{
+ deployment_id: deployment.id,
+ tags: ["beta", "beta-edge"],
+ identifier: @valid_serial,
+ product: @valid_product
+ }
+ )
- device = Deployments.set_deployment(device)
assert device.deployment_id
Fixtures.device_certificate_fixture(device)
@@ -762,36 +789,52 @@ defmodule NervesHubWeb.WebsocketTest do
"nerves_fw_version" => "0.1.0"
})
- assert device.firmware_metadata.architecture != different_architecture
- assert device.firmware_metadata.platform != different_platform
-
Process.sleep(100)
device = Repo.reload(device)
- refute device.deployment_id
+ assert device.deployment_conflict == :bad_architecture_and_platform
SocketClient.clean_close(socket)
end
- test "updates device deployment on connect if no device.deployment_id", %{
+ test "does nothing when device matches deployment conditions", %{
user: user,
tmp_dir: tmp_dir
} do
- {device, firmware} =
- device_fixture(tmp_dir, user, %{identifier: @valid_serial, product: @valid_product})
+ org = Fixtures.org_fixture(user)
+ product = Fixtures.product_fixture(user, org)
+ org_key = Fixtures.org_key_fixture(org, user, tmp_dir)
- org = %Accounts.Org{id: device.org_id}
+ firmware =
+ Fixtures.firmware_fixture(org_key, product, %{
+ version: "0.0.1",
+ dir: tmp_dir
+ })
- Fixtures.deployment_fixture(org, firmware, %{
- name: "a different name",
- conditions: %{
- "version" => "~> 0.0.1",
- "tags" => ["beta", "beta-edge"]
- }
- })
- |> Deployments.update_deployment(%{is_active: true})
+ {:ok, deployment} =
+ Fixtures.deployment_fixture(org, firmware, %{
+ name: "a different name",
+ conditions: %{
+ "version" => "~> 0.0.1",
+ "tags" => ["beta", "beta-edge"]
+ }
+ })
+ |> Deployments.update_deployment(%{is_active: true})
+
+ device =
+ Fixtures.device_fixture(
+ org,
+ product,
+ firmware,
+ %{
+ deployment_id: deployment.id,
+ tags: ["beta", "beta-edge"],
+ identifier: @valid_serial,
+ product: @valid_product
+ }
+ )
- refute device.deployment_id
+ assert device.deployment_id
Fixtures.device_certificate_fixture(device)
@@ -977,24 +1020,34 @@ defmodule NervesHubWeb.WebsocketTest do
test "on connect receive an archive", %{user: user, tmp_dir: tmp_dir} do
org = Fixtures.org_fixture(user)
org_key = Fixtures.org_key_fixture(org, user, tmp_dir)
+ product = Fixtures.product_fixture(user, org)
- {device, firmware} = device_fixture(tmp_dir, user, %{identifier: @valid_serial}, org)
-
- firmware = Repo.preload(firmware, [:product])
- product = firmware.product
+ firmware =
+ Fixtures.firmware_fixture(org_key, product, %{
+ version: "0.0.1",
+ dir: tmp_dir
+ })
+ |> Repo.preload([:product])
archive = Fixtures.archive_fixture(org_key, product, %{dir: tmp_dir})
- deployment =
+ {:ok, deployment} =
Fixtures.deployment_fixture(org, firmware, %{
name: "beta",
conditions: %{
"tags" => ["beta"]
- }
+ },
+ archive_id: archive.id
})
-
- {:ok, deployment} = Deployments.update_deployment(deployment, %{archive_id: archive.id})
- {:ok, _deployment} = Deployments.update_deployment(deployment, %{is_active: true})
+ |> Deployments.update_deployment(%{is_active: true})
+
+ device =
+ Fixtures.device_fixture(
+ org,
+ product,
+ firmware,
+ %{tags: ["beta", "beta-edge"], identifier: @valid_serial, deployment_id: deployment.id}
+ )
Fixtures.device_certificate_fixture(device)
@@ -1015,24 +1068,34 @@ defmodule NervesHubWeb.WebsocketTest do
test "on updates enabled receive an archive", %{user: user, tmp_dir: tmp_dir} do
org = Fixtures.org_fixture(user)
org_key = Fixtures.org_key_fixture(org, user, tmp_dir)
+ product = Fixtures.product_fixture(user, org)
- {device, firmware} = device_fixture(tmp_dir, user, %{identifier: @valid_serial}, org)
-
- firmware = Repo.preload(firmware, [:product])
- product = firmware.product
+ firmware =
+ Fixtures.firmware_fixture(org_key, product, %{
+ version: "0.0.1",
+ dir: tmp_dir
+ })
+ |> Repo.preload([:product])
archive = Fixtures.archive_fixture(org_key, product, %{dir: tmp_dir})
- deployment =
+ {:ok, deployment} =
Fixtures.deployment_fixture(org, firmware, %{
name: "beta",
conditions: %{
"tags" => ["beta"]
- }
+ },
+ archive_id: archive.id
})
-
- {:ok, deployment} = Deployments.update_deployment(deployment, %{archive_id: archive.id})
- {:ok, _deployment} = Deployments.update_deployment(deployment, %{is_active: true})
+ |> Deployments.update_deployment(%{is_active: true})
+
+ device =
+ Fixtures.device_fixture(
+ org,
+ product,
+ firmware,
+ %{tags: ["beta", "beta-edge"], identifier: @valid_serial, deployment_id: deployment.id}
+ )
Fixtures.device_certificate_fixture(device)
@@ -1059,23 +1122,33 @@ defmodule NervesHubWeb.WebsocketTest do
test "deployment archive updated", %{user: user, tmp_dir: tmp_dir} do
org = Fixtures.org_fixture(user)
org_key = Fixtures.org_key_fixture(org, user, tmp_dir)
+ product = Fixtures.product_fixture(user, org)
- {device, firmware} = device_fixture(tmp_dir, user, %{identifier: @valid_serial}, org)
-
- firmware = Repo.preload(firmware, [:product])
- product = firmware.product
-
- archive = Fixtures.archive_fixture(org_key, product, %{dir: tmp_dir})
+ firmware =
+ Fixtures.firmware_fixture(org_key, product, %{
+ version: "0.0.1",
+ dir: tmp_dir
+ })
+ |> Repo.preload([:product])
- deployment =
+ {:ok, deployment} =
Fixtures.deployment_fixture(org, firmware, %{
name: "beta",
conditions: %{
"tags" => ["beta"]
}
})
+ |> Deployments.update_deployment(%{is_active: true})
+
+ device =
+ Fixtures.device_fixture(
+ org,
+ product,
+ firmware,
+ %{tags: ["beta", "beta-edge"], identifier: @valid_serial, deployment_id: deployment.id}
+ )
- {:ok, deployment} = Deployments.update_deployment(deployment, %{is_active: true})
+ archive = Fixtures.archive_fixture(org_key, product, %{dir: tmp_dir})
Fixtures.device_certificate_fixture(device)