Current section

Files

Jump to
compox lib docker compose parser.ex
Raw

lib/docker/compose/parser.ex

defmodule Compox.Docker.Compose.Parser do
@moduledoc false
alias Compox.Docker.Services.Service
@typedoc """
Path to the `docker-compose.yml` file.
"""
@type docker_compose_path :: String.t()
@doc """
Parses a `docker compose` file and returns the list of
[services](`t:Compox.Docker.Service.t/0`).
See [Docker compose
specification](https://github.com/compose-spec/compose-spec/blob/master/spec.md)
for more information.
"""
@spec parse(docker_compose_path) :: {:ok, [Service.t()]} | {:error, term}
def parse(docker_compose_path) do
with {:ok, file} <- File.read(docker_compose_path),
{:ok, yaml} <- YamlElixir.read_from_string(file) do
{:ok, get_services(yaml)}
else
error -> error
end
end
#
# Private functions
#
@spec get_services(map) :: [Service.t()]
defp get_services(%{"services" => services}) do
Enum.map(services, &get_service/1)
end
defp get_services(_), do: []
@spec get_service(map) :: Service.t() | {:error, term}
defp get_service({service_name, %{"image" => image} = service_attrs}) do
attrs =
service_attrs
|> get_base_attrs()
|> Map.merge(%{
name: service_name,
image: image
})
struct(Service, attrs)
end
defp get_service({service_name, %{"build" => build_path} = service_attrs}) do
attrs =
service_attrs
|> get_base_attrs()
|> Map.merge(%{
name: service_name,
image: build_path
})
struct(Service, attrs)
end
defp get_service(service),
do: {:error, "Unknown service configuration: #{inspect(service)}"}
defp get_base_attrs(service_attrs) do
service_attrs
|> Map.take(["container_name"])
|> Enum.map(fn
{k, v} -> {String.to_atom(k), v}
end)
|> Enum.into(%{})
end
end