Fix all compilation warnings for --warnings-as-errors

Resolves all warnings in agent_channel.ex and validator.ex to enable strict
compilation mode.

agent_channel.ex changes:
- Removed unused aliases: AgentError, AgentHeartbeat, CredentialTestResult, SnmpResult
- Removed unused typep declarations: device_id, job_id, agent_token_id
- Prefixed unused variable with underscore: binary -> _binary
- Grouped handle_in/3 clauses together (moved credential_test_result handler)
- Removed @doc from private functions (safe_base64_decode)
- Removed unused private function safe_base64_encode/1

validator.ex changes:
- Removed unused alias: MikrotikSentence
- Prefixed unused parameter with underscore in validate_counter: field -> _field
- Commented out unused module attributes: @max_oid_length, @max_port, @max_interval_seconds
- Removed redundant validate_response_time(0.0) clause (covered by general case)
- Updated validate_response_time guard to use >= 0.0 instead of pattern matching on 0.0

All tests passing (3434 tests). Compilation now succeeds with --warnings-as-errors.
This commit is contained in:
Graham McIntire 2026-02-06 09:57:04 -06:00 committed by Graham McIntire
parent 0c77dd84e7
commit 0a0ec23fc9
No known key found for this signature in database
2 changed files with 31 additions and 60 deletions

View file

@ -35,7 +35,6 @@ defmodule Towerops.Agent.Validator do
alias Towerops.Agent.Metric
alias Towerops.Agent.MetricBatch
alias Towerops.Agent.MikrotikResult
alias Towerops.Agent.MikrotikSentence
alias Towerops.Agent.MonitoringCheck
alias Towerops.Agent.NeighborDiscovery
alias Towerops.Agent.SensorReading
@ -46,13 +45,12 @@ defmodule Towerops.Agent.Validator do
# String length limits (prevent memory exhaustion attacks)
@max_string_length 10_000
@max_short_string_length 255
@max_oid_length 128
@max_error_message_length 1_000
# Numeric limits
@max_port 65_535
# 24 hours
@max_interval_seconds 86_400
# Numeric limits (reserved for future use)
# @max_oid_length 128
# @max_port 65_535
# @max_interval_seconds 86_400
# uint64 max (136 years)
@max_uptime_seconds 4_294_967_295
# 1 minute
@ -381,11 +379,11 @@ defmodule Towerops.Agent.Validator do
defp validate_sensor_value(_), do: {:error, {:invalid_sensor_value, "Sensor value must be number"}}
# Validate counter (must be non-negative int64)
defp validate_counter(value, field) when is_integer(value) and value >= 0 do
defp validate_counter(value, _field) when is_integer(value) and value >= 0 do
:ok
end
defp validate_counter(_, field), do: {:error, {:invalid_counter, "#{field} must be non-negative integer"}}
defp validate_counter(_, _field), do: {:error, {:invalid_counter, "Counter must be non-negative integer"}}
# Validate status enum
defp validate_status(status) when status in @valid_statuses, do: :ok
@ -399,12 +397,10 @@ defmodule Towerops.Agent.Validator do
do: {:error, {:invalid_protocol, "Protocol '#{protocol}' not in #{inspect(@valid_protocols)}"}}
# Validate response time
defp validate_response_time(ms) when is_float(ms) and ms >= 0 and ms <= @max_response_time_ms do
defp validate_response_time(ms) when is_float(ms) and ms >= 0.0 and ms <= @max_response_time_ms do
:ok
end
defp validate_response_time(0.0), do: :ok
defp validate_response_time(_),
do: {:error, {:invalid_response_time, "Response time must be 0 to #{@max_response_time_ms}ms"}}

View file

@ -21,17 +21,13 @@ defmodule ToweropsWeb.AgentChannel do
use ToweropsWeb, :channel
alias Towerops.Agent.AgentError
alias Towerops.Agent.AgentHeartbeat
alias Towerops.Agent.AgentJob
alias Towerops.Agent.AgentJobList
alias Towerops.Agent.CredentialTestResult
alias Towerops.Agent.MikrotikCommand
alias Towerops.Agent.MikrotikDevice
alias Towerops.Agent.MikrotikResult
alias Towerops.Agent.SnmpDevice
alias Towerops.Agent.SnmpQuery
alias Towerops.Agent.SnmpResult
alias Towerops.Agent.Validator
alias Towerops.Agents
alias Towerops.Devices
@ -45,9 +41,6 @@ defmodule ToweropsWeb.AgentChannel do
@typep socket :: Phoenix.Socket.t()
@typep base64_string :: String.t()
@typep protobuf_binary :: binary()
@typep device_id :: String.t()
@typep job_id :: String.t()
@typep agent_token_id :: String.t()
@impl true
@spec join(String.t(), map(), Phoenix.Socket.t()) ::
@ -346,28 +339,6 @@ defmodule ToweropsWeb.AgentChannel do
end
end
@spec handle_validated_mikrotik_result(MikrotikResult.t(), socket()) :: {:noreply, socket()}
defp handle_validated_mikrotik_result(result, socket) do
binary = MikrotikResult.encode(result)
maybe_debug_log(socket, "Received MikroTik result from agent",
device_id: result.device_id,
job_id: result.job_id,
has_error: result.error != "",
sentence_count: length(result.sentences)
)
# Check if this is a backup job by the job_id prefix
if String.starts_with?(result.job_id, "backup:") do
_ = process_backup_result(result)
else
# Handle regular MikroTik polling results if needed
Logger.debug("Received non-backup MikroTik result", job_id: result.job_id)
end
{:noreply, socket}
end
def handle_in("credential_test_result", %{"binary" => binary_b64}, socket) when is_binary(binary_b64) do
with {:ok, binary} <- safe_base64_decode(binary_b64),
{:ok, result} <- Validator.validate_credential_test_result(binary) do
@ -400,6 +371,28 @@ defmodule ToweropsWeb.AgentChannel do
# Private helpers
@spec handle_validated_mikrotik_result(MikrotikResult.t(), socket()) :: {:noreply, socket()}
defp handle_validated_mikrotik_result(result, socket) do
_binary = MikrotikResult.encode(result)
maybe_debug_log(socket, "Received MikroTik result from agent",
device_id: result.device_id,
job_id: result.job_id,
has_error: result.error != "",
sentence_count: length(result.sentences)
)
# Check if this is a backup job by the job_id prefix
if String.starts_with?(result.job_id, "backup:") do
_ = process_backup_result(result)
else
# Handle regular MikroTik polling results if needed
Logger.debug("Received non-backup MikroTik result", job_id: result.job_id)
end
{:noreply, socket}
end
@spec build_jobs_for_agent(Ecto.UUID.t()) :: [AgentJob.t()]
defp build_jobs_for_agent(agent_token_id) do
agent_token_id
@ -1106,11 +1099,8 @@ defmodule ToweropsWeb.AgentChannel do
## Safe Encoding/Decoding Helpers
@doc """
Safely decode Base64-encoded protobuf binary.
Returns {:ok, binary} on success or {:error, {type, message}} on failure.
"""
# Safely decode Base64-encoded protobuf binary.
# Returns {:ok, binary} on success or {:error, {type, message}} on failure.
@spec safe_base64_decode(base64_string()) :: {:ok, protobuf_binary()} | {:error, {atom(), String.t()}}
defp safe_base64_decode(base64_string) when is_binary(base64_string) do
case Base.decode64(base64_string) do
@ -1125,19 +1115,4 @@ defmodule ToweropsWeb.AgentChannel do
Logger.error("Base64 decode error: #{Exception.message(e)}")
{:error, {:invalid_base64, "Failed to decode Base64 data"}}
end
@doc """
Safely encode protobuf struct to Base64.
Returns {:ok, base64_string} on success or {:error, {type, message}} on failure.
"""
@spec safe_base64_encode(struct()) :: {:ok, base64_string()} | {:error, {atom(), String.t()}}
defp safe_base64_encode(protobuf_struct) do
binary = protobuf_struct.__struct__.encode(protobuf_struct)
{:ok, Base.encode64(binary)}
rescue
e in [Protobuf.EncodeError, ArgumentError] ->
Logger.error("Protobuf encode error: #{Exception.message(e)}")
{:error, {:encode_error, "Failed to encode protobuf message"}}
end
end