towerops/lib/towerops/contexts/config_change_tracker.ex
2026-02-04 17:56:48 -06:00

109 lines
3.2 KiB
Elixir

defmodule Towerops.Contexts.ConfigChangeTracker do
@moduledoc """
Tracks configuration changes for SNMP and MikroTik settings across
organizations and sites to trigger device propagation.
Provides functions to capture configuration state before updates and
detect which configuration fields changed after updates.
"""
@config_fields [
:snmp_community,
:mikrotik_username,
:mikrotik_password,
:mikrotik_port,
:mikrotik_use_ssl,
:mikrotik_enabled
]
@doc """
Captures the current configuration state from a struct.
Returns a map with all tracked configuration fields.
## Examples
iex> org = %Organization{snmp_community: "public", mikrotik_username: "admin"}
iex> ConfigChangeTracker.capture_config_state(org)
%{
snmp_community: "public",
mikrotik_username: "admin",
mikrotik_password: nil,
mikrotik_port: nil,
mikrotik_use_ssl: nil,
mikrotik_enabled: nil
}
"""
@spec capture_config_state(struct()) :: map()
def capture_config_state(struct) do
Map.new(@config_fields, fn field ->
{field, Map.get(struct, field)}
end)
end
@doc """
Checks if the SNMP community string changed.
## Examples
iex> old_state = %{snmp_community: "public"}
iex> updated = %Organization{snmp_community: "private"}
iex> ConfigChangeTracker.snmp_changed?(updated, old_state)
true
"""
@spec snmp_changed?(struct(), map()) :: boolean()
def snmp_changed?(updated_struct, old_state) do
Map.get(updated_struct, :snmp_community) != old_state.snmp_community
end
@doc """
Checks if any MikroTik configuration field changed.
Compares all MikroTik-related fields (username, password, port, ssl, enabled)
except snmp_community.
## Examples
iex> old_state = %{mikrotik_username: "admin", mikrotik_password: "pass"}
iex> updated = %Organization{mikrotik_username: "root", mikrotik_password: "pass"}
iex> ConfigChangeTracker.mikrotik_changed?(updated, old_state)
true
"""
@spec mikrotik_changed?(struct(), map()) :: boolean()
def mikrotik_changed?(updated_struct, old_state) do
Enum.any?(@config_fields, fn field ->
case field do
:snmp_community -> false
field -> Map.get(updated_struct, field) != old_state[field]
end
end)
end
@doc """
Extracts MikroTik configuration attributes from a struct.
Returns a map with all MikroTik-related fields suitable for device propagation.
## Examples
iex> site = %Site{mikrotik_username: "admin", mikrotik_port: 8729}
iex> ConfigChangeTracker.extract_mikrotik_attrs(site)
%{
mikrotik_username: "admin",
mikrotik_password: nil,
mikrotik_port: 8729,
mikrotik_use_ssl: nil,
mikrotik_enabled: nil
}
"""
@spec extract_mikrotik_attrs(struct()) :: map()
def extract_mikrotik_attrs(struct) do
%{
mikrotik_username: Map.get(struct, :mikrotik_username),
mikrotik_password: Map.get(struct, :mikrotik_password),
mikrotik_port: Map.get(struct, :mikrotik_port),
mikrotik_use_ssl: Map.get(struct, :mikrotik_use_ssl),
mikrotik_enabled: Map.get(struct, :mikrotik_enabled)
}
end
end