fix siteless devices not inheriting org default agent
devices assigned directly to an org (no site) were excluded from apply_agent_to_all_equipment due to inner join through site table. also fix fallback agent resolution to check device.organization when device.site is nil.
This commit is contained in:
parent
bd24dfcbed
commit
92eb583a8b
6 changed files with 41 additions and 33 deletions
|
|
@ -710,11 +710,11 @@ defmodule Towerops.Agents do
|
|||
|
||||
Returns the agent_token_id if found, nil otherwise.
|
||||
|
||||
The device must be preloaded with site: [organization: :default_agent_token].
|
||||
The device must be preloaded with `[:organization, site: [organization: :default_agent_token]]`.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> device = Repo.preload(device, site: [organization: :default_agent_token])
|
||||
iex> device = Repo.preload(device, [:organization, site: [organization: :default_agent_token]])
|
||||
iex> get_effective_agent_token(device)
|
||||
"agent-token-uuid"
|
||||
|
||||
|
|
@ -730,21 +730,27 @@ defmodule Towerops.Agents do
|
|||
agent_token_id
|
||||
|
||||
_ ->
|
||||
get_fallback_agent_token(device.site)
|
||||
get_fallback_agent_token(device)
|
||||
end
|
||||
end
|
||||
|
||||
# Checks site, organization, and global default in sequence
|
||||
defp get_fallback_agent_token(site) do
|
||||
case site do
|
||||
%{agent_token_id: agent_token_id} when not is_nil(agent_token_id) ->
|
||||
agent_token_id
|
||||
defp get_fallback_agent_token(device) do
|
||||
cond do
|
||||
# 2. Site-level agent
|
||||
match?(%{agent_token_id: id} when not is_nil(id), device.site) ->
|
||||
device.site.agent_token_id
|
||||
|
||||
%{organization: %{default_agent_token_id: agent_token_id}}
|
||||
when not is_nil(agent_token_id) ->
|
||||
agent_token_id
|
||||
# 3. Organization default via site
|
||||
match?(%{organization: %{default_agent_token_id: id}} when not is_nil(id), device.site) ->
|
||||
device.site.organization.default_agent_token_id
|
||||
|
||||
_ ->
|
||||
# 3b. Organization default directly (device has no site)
|
||||
match?(%{default_agent_token_id: id} when not is_nil(id), device.organization) ->
|
||||
device.organization.default_agent_token_id
|
||||
|
||||
# 4. Global default
|
||||
true ->
|
||||
Towerops.Settings.get_global_default_cloud_poller()
|
||||
end
|
||||
end
|
||||
|
|
@ -777,21 +783,27 @@ defmodule Towerops.Agents do
|
|||
{agent_token_id, :device}
|
||||
|
||||
_ ->
|
||||
get_fallback_agent_token_with_source(device.site)
|
||||
get_fallback_agent_token_with_source(device)
|
||||
end
|
||||
end
|
||||
|
||||
# Checks site, organization, and global default in sequence with source tracking
|
||||
defp get_fallback_agent_token_with_source(site) do
|
||||
case site do
|
||||
%{agent_token_id: agent_token_id} when not is_nil(agent_token_id) ->
|
||||
{agent_token_id, :site}
|
||||
defp get_fallback_agent_token_with_source(device) do
|
||||
cond do
|
||||
# 2. Site-level agent
|
||||
match?(%{agent_token_id: id} when not is_nil(id), device.site) ->
|
||||
{device.site.agent_token_id, :site}
|
||||
|
||||
%{organization: %{default_agent_token_id: agent_token_id}}
|
||||
when not is_nil(agent_token_id) ->
|
||||
{agent_token_id, :organization}
|
||||
# 3. Organization default via site
|
||||
match?(%{organization: %{default_agent_token_id: id}} when not is_nil(id), device.site) ->
|
||||
{device.site.organization.default_agent_token_id, :organization}
|
||||
|
||||
_ ->
|
||||
# 3b. Organization default directly (device has no site)
|
||||
match?(%{default_agent_token_id: id} when not is_nil(id), device.organization) ->
|
||||
{device.organization.default_agent_token_id, :organization}
|
||||
|
||||
# 4. Global default
|
||||
true ->
|
||||
case Towerops.Settings.get_global_default_cloud_poller() do
|
||||
agent_token_id when not is_nil(agent_token_id) ->
|
||||
{agent_token_id, :global}
|
||||
|
|
|
|||
|
|
@ -378,7 +378,7 @@ defmodule Towerops.Agents.Stats do
|
|||
device =
|
||||
Device
|
||||
|> Repo.get!(device_id)
|
||||
|> Repo.preload(site: [organization: :default_agent_token])
|
||||
|> Repo.preload([:organization, site: [organization: :default_agent_token]])
|
||||
|
||||
{current_agent_id, source} = Towerops.Agents.get_effective_agent_token_with_source(device)
|
||||
|
||||
|
|
@ -453,7 +453,7 @@ defmodule Towerops.Agents.Stats do
|
|||
device =
|
||||
Device
|
||||
|> Repo.get!(device_id)
|
||||
|> Repo.preload(site: [organization: :default_agent_token])
|
||||
|> Repo.preload([:organization, site: [organization: :default_agent_token]])
|
||||
|
||||
{current_agent_id, source} = Towerops.Agents.get_effective_agent_token_with_source(device)
|
||||
|
||||
|
|
|
|||
|
|
@ -241,7 +241,7 @@ defmodule Towerops.Devices do
|
|||
nil
|
||||
|
||||
device ->
|
||||
Repo.preload(device, [:site, snmp_device: [:interfaces, :sensors]])
|
||||
Repo.preload(device, [:site, :organization, snmp_device: [:interfaces, :sensors]])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -653,7 +653,7 @@ defmodule Towerops.Devices do
|
|||
|
||||
defp validate_cloud_poller_requires_ssl(changeset, device) do
|
||||
# Get effective agent to check if it's a cloud poller
|
||||
device_with_site = Repo.preload(device, site: :organization)
|
||||
device_with_site = Repo.preload(device, [:organization, site: :organization])
|
||||
{effective_agent_id, _source} = Agents.get_effective_agent_token_with_source(device_with_site)
|
||||
|
||||
using_cloud_poller =
|
||||
|
|
|
|||
|
|
@ -415,11 +415,9 @@ defmodule Towerops.Organizations do
|
|||
organization = Repo.get!(Organization, organization_id)
|
||||
|
||||
if organization.default_agent_token_id do
|
||||
# device IDs for this organization
|
||||
# device IDs for this organization (includes devices with and without sites)
|
||||
device_ids =
|
||||
Repo.all(
|
||||
from(e in Device, join: s in assoc(e, :site), where: s.organization_id == ^organization_id, select: e.id)
|
||||
)
|
||||
Repo.all(from(e in Device, where: e.organization_id == ^organization_id, select: e.id))
|
||||
|
||||
# Delete existing assignments
|
||||
Repo.delete_all(from(a in AgentAssignment, where: a.device_id in ^device_ids))
|
||||
|
|
@ -442,9 +440,7 @@ defmodule Towerops.Organizations do
|
|||
else
|
||||
# No default agent set, delete all assignments
|
||||
device_ids =
|
||||
Repo.all(
|
||||
from(e in Device, join: s in assoc(e, :site), where: s.organization_id == ^organization_id, select: e.id)
|
||||
)
|
||||
Repo.all(from(e in Device, where: e.organization_id == ^organization_id, select: e.id))
|
||||
|
||||
Repo.delete_all(from(a in AgentAssignment, where: a.device_id in ^device_ids))
|
||||
end
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ defmodule ToweropsWeb.DeviceLive.Form do
|
|||
case AccessControl.verify_device_access(id, organization.id) do
|
||||
{:ok, device} ->
|
||||
# Preload necessary associations for agent resolution
|
||||
device = Repo.preload(device, site: [organization: :default_agent_token])
|
||||
device = Repo.preload(device, [:organization, site: [organization: :default_agent_token]])
|
||||
apply_edit_action(socket, device)
|
||||
|
||||
{:error, :not_found} ->
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@ defmodule ToweropsWeb.DeviceLive.Show do
|
|||
|
||||
defp load_equipment_data(socket, device_id) do
|
||||
device = Devices.get_device!(device_id)
|
||||
device_with_associations = Repo.preload(device, site: [organization: :default_agent_token])
|
||||
device_with_associations = Repo.preload(device, [:organization, site: [organization: :default_agent_token]])
|
||||
{agent_token_id, agent_source} = Agents.get_effective_agent_token_with_source(device_with_associations)
|
||||
agent_info = load_agent_info(agent_token_id, agent_source)
|
||||
recent_checks = Monitoring.list_devices_checks(device_id, 50)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue