towerops/test/towerops_web/channels/agent_channel_test.exs
Graham McIntire 9e36d5030a
poll device immediately after discovery completes
newly discovered devices sat idle with no metric data until the
next scheduling cycle. now the channel sends a poll job (and ping
job if monitoring enabled) right after discovery succeeds, using
send(self(), ...) so discovery DB writes commit first.

also reduces k8s replicas from 3 to 2.
2026-02-11 13:24:55 -06:00

102 lines
3.1 KiB
Elixir

defmodule ToweropsWeb.AgentChannelTest do
use Towerops.DataCase, async: false
import Phoenix.ChannelTest
alias Towerops.AccountsFixtures
alias Towerops.Agent.AgentJobList
alias Towerops.Agent.SnmpResult
alias Towerops.AgentsFixtures
alias Towerops.DevicesFixtures
alias Towerops.OrganizationsFixtures
alias ToweropsWeb.AgentSocket
@endpoint ToweropsWeb.Endpoint
setup do
# Create organization, site, device, and agent token
user = AccountsFixtures.user_fixture()
organization = OrganizationsFixtures.organization_fixture(user.id)
device =
DevicesFixtures.device_fixture(%{
organization_id: organization.id,
snmp_version: "2c",
snmp_community: "public"
})
{:ok, agent_token, token_string} =
AgentsFixtures.agent_token_fixture(organization.id)
# Assign device to agent
{:ok, _assignment} =
AgentsFixtures.agent_assignment_fixture(agent_token.id, device.id)
# Connect socket and join channel
{:ok, socket} = connect(AgentSocket, %{})
{:ok, _, socket} =
subscribe_and_join(socket, "agent:#{agent_token.id}", %{"token" => token_string})
# Drain the initial :send_jobs message pushed on join
assert_push "jobs", _initial_jobs
%{
socket: socket,
device: device,
agent_token: agent_token,
organization: organization
}
end
describe "poll after discovery" do
test "pushes poll jobs after successful discovery result", %{
socket: socket,
device: device
} do
# Build a minimal discovery result with system info OIDs
# that AgentDiscovery.process_agent_discovery can handle
discovery_result = %SnmpResult{
device_id: device.id,
job_type: :DISCOVER,
job_id: "discover:#{device.id}",
timestamp: DateTime.to_unix(DateTime.utc_now()),
oid_values: %{
# sysDescr
"1.3.6.1.2.1.1.1.0" => "Test Device Description",
# sysObjectID
"1.3.6.1.2.1.1.2.0" => "1.3.6.1.4.1.9.1.1",
# sysUpTime
"1.3.6.1.2.1.1.3.0" => "123456",
# sysContact
"1.3.6.1.2.1.1.4.0" => "admin@test.com",
# sysName
"1.3.6.1.2.1.1.5.0" => "test-device",
# sysLocation
"1.3.6.1.2.1.1.6.0" => "Test Location"
}
}
binary = SnmpResult.encode(discovery_result)
payload = %{"binary" => Base.encode64(binary)}
# Send the discovery result to the channel
push(socket, "result", payload)
# Should receive a "jobs" push with poll job(s) for the discovered device
assert_push "jobs", %{binary: jobs_binary}, 5_000
# Decode the job list and verify it contains a POLL job for our device
{:ok, decoded_binary} = Base.decode64(jobs_binary)
job_list = AgentJobList.decode(decoded_binary)
poll_job =
Enum.find(job_list.jobs, fn job ->
job.job_type == :POLL and job.device_id == device.id
end)
assert poll_job != nil, "Expected a POLL job for device #{device.id}"
assert poll_job.job_id == "poll:#{device.id}"
end
end
end