- help_live/index.ex: 2,642→173 lines, 15 section modules + sidebar extracted MikroTik now real section, dead if false removed - agent_channel.ex: 2,506→1,751 lines, 3 helper modules extracted (heartbeat/subscriptions/job_builder), decode_and_process/4 eliminates 8 repeated handle_in patterns, guard-based size checks - antenna_catalog.ex: 1,174→47 lines, 107 specs → priv/antennas/catalog.json - topology.ex: unbounded query → batched loading (100/batch), all guard errors fixed, zero if/case/cond conditionals - proto: decoder_macros.ex + field_specs.ex infrastructure for macro-generated protobuf decoders
226 lines
9.5 KiB
Elixir
226 lines
9.5 KiB
Elixir
defmodule Towerops.Proto.FieldSpecs do
|
|
@moduledoc """
|
|
Declarative field specifications for all protobuf message decoders.
|
|
|
|
This module documents every message type and its wire format fields.
|
|
Each spec tuple: `{struct_module, decode_function_name, fields_list, opts_keyword}`
|
|
|
|
Field types: `:string`, `:uint`, `:int64`, `:double`, `:bool`,
|
|
`{:enum, conv_fn}`, `{:message, decode_fn}`, `{:oneof, decode_fn, tag}`,
|
|
`{:repeated, :string}`, `{:map, :string, :string}`,
|
|
`{:repeated_message, decode_fn}`, `{:repeated_message, decode_fn, validate_fn}`.
|
|
|
|
Options: `validate`, `finalize`, `defaults`.
|
|
"""
|
|
|
|
alias Towerops.Proto.Types
|
|
|
|
@doc "Return all decoder specifications."
|
|
def all do
|
|
[
|
|
# ── Agent → Server messages ──────────────────────
|
|
|
|
{Types.AgentHeartbeat, :decode_agent_heartbeat,
|
|
[
|
|
{1, :version, :string},
|
|
{2, :hostname, :string},
|
|
{3, :uptime_seconds, :uint},
|
|
{4, :ip_address, :string},
|
|
{5, :arch, :string}
|
|
], validate: :validate_heartbeat},
|
|
{Types.HeartbeatMetadata, :decode_heartbeat_metadata,
|
|
[{1, :version, :string}, {2, :hostname, :string}, {3, :uptime_seconds, :uint}]},
|
|
{Types.HeartbeatResponse, :decode_heartbeat_response, [{1, :status, :string}]},
|
|
{Types.SnmpResult, :decode_snmp_result,
|
|
[
|
|
{1, :device_id, :string},
|
|
{2, :job_type, {:enum, &Types.job_type_from_int/1}},
|
|
{3, :oid_values, {:map, :string, :string}},
|
|
{4, :timestamp, :int64},
|
|
{5, :job_id, :string}
|
|
], validate: :validate_snmp_result, defaults: [job_type: :discover]},
|
|
{Types.AgentError, :decode_agent_error,
|
|
[{1, :device_id, :string}, {2, :job_id, :string}, {3, :message, :string}, {4, :timestamp, :int64}],
|
|
validate: :validate_agent_error},
|
|
{Types.CredentialTestResult, :decode_credential_test_result,
|
|
[
|
|
{1, :test_id, :string},
|
|
{2, :success, :bool},
|
|
{3, :error_message, :string},
|
|
{4, :system_description, :string},
|
|
{5, :timestamp, :int64}
|
|
], validate: :validate_credential_test_result},
|
|
{Types.MikrotikResult, :decode_mikrotik_result,
|
|
[
|
|
{1, :device_id, :string},
|
|
{2, :job_id, :string},
|
|
{3, :sentences, {:repeated_message, :decode_mikrotik_sentence}},
|
|
{4, :error, :string},
|
|
{5, :timestamp, :int64}
|
|
], validate: :validate_mikrotik_result, finalize: {:reverse, [:sentences]}},
|
|
{Types.MonitoringCheck, :decode_monitoring_check,
|
|
[{1, :device_id, :string}, {2, :status, :string}, {3, :response_time_ms, :double}, {4, :timestamp, :int64}],
|
|
validate: :validate_monitoring_check},
|
|
{Types.LldpTopologyResult, :decode_lldp_topology_result,
|
|
[
|
|
{1, :device_id, :string},
|
|
{2, :job_id, :string},
|
|
{3, :local_system_name, :string},
|
|
{4, :neighbors, {:repeated_message, :decode_lldp_neighbor}},
|
|
{5, :timestamp, :int64}
|
|
], validate: :validate_lldp_topology_result, finalize: {:reverse, [:neighbors]}},
|
|
{Types.CheckResult, :decode_check_result,
|
|
[
|
|
{1, :check_id, :string},
|
|
{2, :status, :uint},
|
|
{3, :output, :string},
|
|
{4, :response_time_ms, :double},
|
|
{5, :timestamp, :int64}
|
|
], validate: :validate_check_result},
|
|
{Types.Sensor, :decode_sensor,
|
|
[
|
|
{1, :id, :string},
|
|
{2, :sensor_type, :string},
|
|
{3, :oid, :string},
|
|
{4, :divisor, :double},
|
|
{5, :unit, :string},
|
|
{6, :metadata, {:map, :string, :string}}
|
|
]},
|
|
|
|
# ── Server → Agent messages ──────────────────────
|
|
|
|
{Types.AgentJob, :decode_agent_job,
|
|
[
|
|
{1, :job_id, :string},
|
|
{2, :job_type, {:enum, &Types.job_type_from_int/1}},
|
|
{3, :device_id, :string},
|
|
{4, :snmp_device, {:message, :decode_snmp_device, :validate_snmp_device}},
|
|
{5, :queries, {:repeated_message, :decode_snmp_query, :validate_snmp_query}},
|
|
{6, :mikrotik_device, {:message, :decode_mikrotik_device, :validate_mikrotik_device}},
|
|
{7, :mikrotik_commands, {:repeated_message, :decode_mikrotik_command, :validate_mikrotik_command}}
|
|
], defaults: [job_type: :discover], finalize: {:reverse, [:queries, :mikrotik_commands]}},
|
|
{Types.AgentConfig, :decode_agent_config,
|
|
[
|
|
{1, :version, :string},
|
|
{2, :poll_interval_seconds, :uint},
|
|
{3, :devices, {:repeated_message, :decode_device}},
|
|
{4, :checks, {:repeated_message, :decode_check, :validate_check}}
|
|
], finalize: {:reverse, [:devices, :checks]}},
|
|
|
|
# ── Nested sub-messages ──────────────────────────
|
|
|
|
{Types.Device, :decode_device,
|
|
[
|
|
{1, :id, :string},
|
|
{2, :name, :string},
|
|
{3, :ip_address, :string},
|
|
{4, :snmp, {:message, :decode_snmp_config}},
|
|
{5, :poll_interval_seconds, :uint},
|
|
{6, :sensors, {:repeated_message, :decode_sensor, :validate_sensor}},
|
|
{7, :interfaces, {:repeated_message, :decode_interface, :validate_interface}},
|
|
{8, :monitoring_enabled, :bool},
|
|
{9, :check_interval_seconds, :uint}
|
|
], finalize: {:reverse, [:sensors, :interfaces]}},
|
|
{Types.SnmpConfig, :decode_snmp_config,
|
|
[
|
|
{1, :enabled, :bool},
|
|
{2, :version, :string},
|
|
{3, :community, :string},
|
|
{4, :port, :uint},
|
|
{5, :transport, :string}
|
|
]},
|
|
{Types.SensorReading, :decode_sensor_reading,
|
|
[{1, :sensor_id, :string}, {2, :value, :double}, {3, :status, :string}, {4, :timestamp, :int64}]},
|
|
{Types.InterfaceStat, :decode_interface_stat,
|
|
[
|
|
{1, :interface_id, :string},
|
|
{2, :if_in_octets, :int64},
|
|
{3, :if_out_octets, :int64},
|
|
{4, :if_in_errors, :int64},
|
|
{5, :if_out_errors, :int64},
|
|
{6, :if_in_discards, :int64},
|
|
{7, :if_out_discards, :int64},
|
|
{8, :timestamp, :int64}
|
|
]},
|
|
{Types.NeighborDiscovery, :decode_neighbor_discovery,
|
|
[
|
|
{1, :interface_id, :string},
|
|
{2, :protocol, :string},
|
|
{3, :remote_chassis_id, :string},
|
|
{4, :remote_system_name, :string},
|
|
{5, :remote_system_description, :string},
|
|
{6, :remote_platform, :string},
|
|
{7, :remote_port_id, :string},
|
|
{8, :remote_port_description, :string},
|
|
{9, :remote_address, :string},
|
|
{10, :remote_capabilities, {:repeated, :string}},
|
|
{11, :timestamp, :int64}
|
|
]},
|
|
{Types.Interface, :decode_interface, [{1, :id, :string}, {2, :if_index, :uint}, {3, :if_name, :string}]},
|
|
{Types.Check, :decode_check,
|
|
[
|
|
{1, :id, :string},
|
|
{2, :check_type, :string},
|
|
{3, :interval_seconds, :uint},
|
|
{4, :timeout_ms, :uint},
|
|
{5, :config, {:oneof, :decode_http_check_config, :http}},
|
|
{6, :config, {:oneof, :decode_tcp_check_config, :tcp}},
|
|
{7, :config, {:oneof, :decode_dns_check_config, :dns}},
|
|
{8, :config, {:oneof, :decode_ssl_check_config, :ssl}}
|
|
], defaults: [config: :no_config]},
|
|
{Types.HttpCheckConfig, :decode_http_check_config,
|
|
[
|
|
{1, :url, :string},
|
|
{2, :method, :string},
|
|
{3, :expected_status, :uint},
|
|
{4, :verify_ssl, :bool},
|
|
{5, :headers, {:map, :string, :string}},
|
|
{6, :body, :string},
|
|
{7, :regex, :string},
|
|
{8, :follow_redirects, :bool}
|
|
]},
|
|
{Types.TcpCheckConfig, :decode_tcp_check_config,
|
|
[{1, :host, :string}, {2, :port, :uint}, {3, :send, :string}, {4, :expect, :string}]},
|
|
{Types.DnsCheckConfig, :decode_dns_check_config,
|
|
[{1, :hostname, :string}, {2, :server, :string}, {3, :record_type, :string}, {4, :expected, :string}]},
|
|
{Types.SslCheckConfig, :decode_ssl_check_config,
|
|
[{1, :host, :string}, {2, :port, :uint}, {3, :warning_days, :uint}]},
|
|
{Types.SnmpDevice, :decode_snmp_device,
|
|
[
|
|
{1, :ip, :string},
|
|
{2, :community, :string},
|
|
{3, :version, :string},
|
|
{4, :port, :uint},
|
|
{5, :v3_security_level, :string},
|
|
{6, :v3_username, :string},
|
|
{7, :v3_auth_protocol, :string},
|
|
{8, :v3_auth_password, :string},
|
|
{9, :v3_priv_protocol, :string},
|
|
{10, :v3_priv_password, :string},
|
|
{11, :transport, :string}
|
|
], validate: :validate_snmp_device},
|
|
{Types.SnmpQuery, :decode_snmp_query,
|
|
[{1, :query_type, {:enum, &Types.query_type_from_int/1}}, {2, :oids, {:repeated, :string}}],
|
|
validate: :validate_snmp_query, defaults: [query_type: :get], finalize: {:reverse, [:oids]}},
|
|
{Types.MikrotikDevice, :decode_mikrotik_device,
|
|
[
|
|
{1, :ip, :string},
|
|
{2, :port, :uint},
|
|
{3, :username, :string},
|
|
{4, :password, :string},
|
|
{5, :use_ssl, :bool},
|
|
{6, :ssh_port, :uint}
|
|
], validate: :validate_mikrotik_device},
|
|
{Types.MikrotikCommand, :decode_mikrotik_command, [{1, :command, :string}, {2, :args, {:map, :string, :string}}],
|
|
validate: :validate_mikrotik_command},
|
|
{Types.LldpNeighbor, :decode_lldp_neighbor,
|
|
[
|
|
{1, :neighbor_name, :string},
|
|
{2, :local_port, :string},
|
|
{3, :remote_port, :string},
|
|
{4, :remote_port_id, :string},
|
|
{5, :management_addresses, {:repeated, :string}}
|
|
], finalize: {:reverse, [:management_addresses]}}
|
|
]
|
|
end
|
|
end
|