Current section

Files

Jump to
libcluster_consul lib strategy consul multisite.ex
Raw

lib/strategy/consul/multisite.ex

defmodule Cluster.Strategy.Consul.Multisite do
@moduledoc """
This endpoint grab nodes from multiple datacenters using a list of Consul
endpoints.
"""
@behaviour Cluster.Strategy.Consul
import Cluster.Logger
alias Cluster.Strategy.{Consul, State}
@impl true
def get_nodes(%State{topology: topology, config: config} = state) do
datacenters =
case Keyword.get(config, :datacenters, :all) do
:all ->
list_all_datacenters(topology, config)
datacenters when is_list(datacenters) ->
datacenters
end
endpoints = Keyword.fetch!(config, :endpoints)
datacenters
|> Enum.flat_map(fn datacenter ->
config =
config
|> Keyword.put(:dc, datacenter)
Enum.flat_map(endpoints, fn
{endpoint, opts} ->
endpoint.get_nodes(%{state | config: Keyword.merge(config, opts)})
endpoint ->
endpoint.get_nodes(state)
end)
end)
end
defp list_all_datacenters(topology, config) do
url =
config
|> Consul.base_url()
|> Map.put(:path, "/v1/catalog/datacenters")
|> to_string()
headers =
config
|> Consul.headers()
case :httpc.request(:get, {to_charlist(url), headers}, [], []) do
{:ok, {{_version, 200, _status}, _headers, body}} ->
body
|> Jason.decode!()
{:ok, {{_version, code, status}, _headers, body}} ->
warn(
topology,
"cannot query Consul (#{code} #{status}): #{inspect(body)}"
)
[]
{:error, reason} ->
error(topology, "request to Consul failed!: #{inspect(reason)}")
[]
end
end
end