add preseem API client with test connection support
This commit is contained in:
parent
e302b8e9c4
commit
06f822dd50
2 changed files with 181 additions and 0 deletions
103
lib/towerops/preseem/client.ex
Normal file
103
lib/towerops/preseem/client.ex
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
defmodule Towerops.Preseem.Client do
|
||||
@moduledoc """
|
||||
HTTP client for the Preseem Model API.
|
||||
|
||||
Uses Req with built-in test support via `Req.Test`.
|
||||
"""
|
||||
|
||||
require Logger
|
||||
|
||||
@default_base_url "https://apidocs.preseem.com/model/v1"
|
||||
|
||||
@doc """
|
||||
Tests the connection to the Preseem API by fetching account info.
|
||||
|
||||
Returns `{:ok, body}` on success, `{:error, reason}` on failure.
|
||||
"""
|
||||
def test_connection(api_key, opts \\ []) do
|
||||
base_url = Keyword.get(opts, :base_url, @default_base_url)
|
||||
|
||||
case request(:get, "#{base_url}/account", api_key) do
|
||||
{:ok, %{status: status, body: body}} when status in 200..299 ->
|
||||
{:ok, body}
|
||||
|
||||
{:ok, %{status: 401}} ->
|
||||
{:error, :unauthorized}
|
||||
|
||||
{:ok, %{status: 403}} ->
|
||||
{:error, :forbidden}
|
||||
|
||||
{:ok, %{status: status, body: body}} ->
|
||||
Logger.warning("Preseem API unexpected status #{status}: #{inspect(body)}")
|
||||
{:error, {:unexpected_status, status}}
|
||||
|
||||
{:error, reason} ->
|
||||
Logger.error("Preseem API connection error: #{inspect(reason)}")
|
||||
{:error, reason}
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Lists all access points from the Preseem API.
|
||||
|
||||
Returns `{:ok, [access_point]}` on success.
|
||||
"""
|
||||
def list_access_points(api_key, opts \\ []) do
|
||||
base_url = Keyword.get(opts, :base_url, @default_base_url)
|
||||
|
||||
case request(:get, "#{base_url}/access_points", api_key) do
|
||||
{:ok, %{status: status, body: %{"data" => data}}} when status in 200..299 ->
|
||||
{:ok, data}
|
||||
|
||||
{:ok, %{status: 401}} ->
|
||||
{:error, :unauthorized}
|
||||
|
||||
{:ok, %{status: 403}} ->
|
||||
{:error, :forbidden}
|
||||
|
||||
{:ok, %{status: status, body: body}} ->
|
||||
{:error, {:unexpected_status, status, body}}
|
||||
|
||||
{:error, reason} ->
|
||||
{:error, reason}
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Fetches metrics for a specific access point.
|
||||
|
||||
Returns `{:ok, metrics_map}` on success.
|
||||
"""
|
||||
def get_access_point_metrics(api_key, ap_id, opts \\ []) do
|
||||
base_url = Keyword.get(opts, :base_url, @default_base_url)
|
||||
|
||||
case request(:get, "#{base_url}/access_points/#{ap_id}/metrics", api_key) do
|
||||
{:ok, %{status: status, body: %{"data" => data}}} when status in 200..299 ->
|
||||
{:ok, data}
|
||||
|
||||
{:ok, %{status: 401}} ->
|
||||
{:error, :unauthorized}
|
||||
|
||||
{:ok, %{status: 403}} ->
|
||||
{:error, :forbidden}
|
||||
|
||||
{:ok, %{status: status, body: body}} ->
|
||||
{:error, {:unexpected_status, status, body}}
|
||||
|
||||
{:error, reason} ->
|
||||
{:error, reason}
|
||||
end
|
||||
end
|
||||
|
||||
defp request(method, url, api_key) do
|
||||
Req.request(
|
||||
method: method,
|
||||
url: url,
|
||||
headers: [{"authorization", "Bearer #{api_key}"}, {"accept", "application/json"}],
|
||||
plug: {Req.Test, __MODULE__}
|
||||
)
|
||||
rescue
|
||||
exception ->
|
||||
{:error, Exception.message(exception)}
|
||||
end
|
||||
end
|
||||
78
test/towerops/preseem/client_test.exs
Normal file
78
test/towerops/preseem/client_test.exs
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
defmodule Towerops.Preseem.ClientTest do
|
||||
use ExUnit.Case, async: true
|
||||
|
||||
alias Towerops.Preseem.Client
|
||||
|
||||
describe "test_connection/1" do
|
||||
test "returns ok when API responds with 200" do
|
||||
Req.Test.stub(Client, fn conn ->
|
||||
Req.Test.json(conn, %{"status" => "ok", "account" => "test-isp"})
|
||||
end)
|
||||
|
||||
assert {:ok, %{"status" => "ok"}} = Client.test_connection("valid-api-key")
|
||||
end
|
||||
|
||||
test "returns error for 401 unauthorized" do
|
||||
Req.Test.stub(Client, fn conn ->
|
||||
conn
|
||||
|> Plug.Conn.put_status(401)
|
||||
|> Req.Test.json(%{"error" => "unauthorized"})
|
||||
end)
|
||||
|
||||
assert {:error, :unauthorized} = Client.test_connection("bad-key")
|
||||
end
|
||||
|
||||
test "returns error for 403 forbidden" do
|
||||
Req.Test.stub(Client, fn conn ->
|
||||
conn
|
||||
|> Plug.Conn.put_status(403)
|
||||
|> Req.Test.json(%{"error" => "forbidden"})
|
||||
end)
|
||||
|
||||
assert {:error, :forbidden} = Client.test_connection("restricted-key")
|
||||
end
|
||||
end
|
||||
|
||||
describe "list_access_points/1" do
|
||||
test "returns list of access points on success" do
|
||||
Req.Test.stub(Client, fn conn ->
|
||||
Req.Test.json(conn, %{
|
||||
"data" => [
|
||||
%{"id" => "ap-1", "name" => "Tower1-AP1", "ip" => "10.0.0.1"},
|
||||
%{"id" => "ap-2", "name" => "Tower1-AP2", "ip" => "10.0.0.2"}
|
||||
]
|
||||
})
|
||||
end)
|
||||
|
||||
assert {:ok, [ap1, ap2]} = Client.list_access_points("valid-key")
|
||||
assert ap1["id"] == "ap-1"
|
||||
assert ap2["id"] == "ap-2"
|
||||
end
|
||||
|
||||
test "returns error for 401" do
|
||||
Req.Test.stub(Client, fn conn ->
|
||||
conn |> Plug.Conn.put_status(401) |> Req.Test.json(%{"error" => "unauthorized"})
|
||||
end)
|
||||
|
||||
assert {:error, :unauthorized} = Client.list_access_points("bad-key")
|
||||
end
|
||||
end
|
||||
|
||||
describe "get_access_point_metrics/2" do
|
||||
test "returns metrics for an AP" do
|
||||
Req.Test.stub(Client, fn conn ->
|
||||
Req.Test.json(conn, %{
|
||||
"data" => %{
|
||||
"qoe_score" => 85.5,
|
||||
"capacity_score" => 72.0,
|
||||
"subscriber_count" => 42,
|
||||
"p95_latency" => 18.3
|
||||
}
|
||||
})
|
||||
end)
|
||||
|
||||
assert {:ok, metrics} = Client.get_access_point_metrics("valid-key", "ap-1")
|
||||
assert metrics["qoe_score"] == 85.5
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Reference in a new issue