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.
102 lines
3.1 KiB
Elixir
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
|