defmodule Helmex do @moduledoc """ Execute helm CLI commands. ## Examples iex> Helmex.init(kubeconfig: "/path/to/kube/config") ...> |> Helmex.Repo.add("kvaps", "https://kvaps.github.io/charts") ...> |> Helmex.call() ## Global options Option | Type :------ | :------ `:burst-limit` | value `:debug` | flag `:kubeconfig` | value `:namespace` | value """ alias Helmex.Helm alias Helmex.Option @global_options %{ debug: %Option{name: "--debug"}, burst_limit: %Option{name: "--burst-limit", require_arg: true}, kubeconfig: %Option{name: "--kubeconfig", require_arg: true}, namespace: %Option{name: "--namespace", require_arg: true} } @type result :: {:ok, String.t()} | {:error, String.t()} defdelegate install(helm, name, chart, opts \\ []), to: Helmex.Install @doc """ Initialize helm command with an optional global flags ## Examples iex> Helmex.init() %Helmex.Helm{command: nil, global_options: [], options: [], args: []} iex> Helmex.init(kubeconfig: "/path/to/the/kube/config") %Helmex.Helm{ command: nil, global_options: [ %Helmex.Option{ name: "--kubeconfig", require_arg: true, value: "/path/to/the/kube/config" } ], options: [], args: [] } """ @spec init(opts :: keyword) :: Helm.t() def init(opts \\ []) do %Helm{global_options: parse_options(opts, @global_options)} end @doc """ Executes the helm command """ @spec call(helm :: Helm.t()) :: result() def call(%Helm{command: nil}), do: raise(ArgumentError, "Please specify the helm command") def call(%Helm{} = helm) do case Rambo.run(helm_path(), build_args(helm)) do {:ok, %Rambo{out: out}} -> {:ok, out} {:error, %Rambo{err: err}} -> {:error, err} {:error, reason} -> {:error, reason} end end @doc """ Filter and parse raw options into the %Helmex.Option structs """ def parse_options(opts, allowed_options) do opts |> Enum.filter(&filter_options(&1, allowed_options)) |> Enum.map(fn {opt, val} -> option = Map.get(allowed_options, opt) if option.require_arg do %Option{option | value: val} else option end end) end defp filter_options({option, _value}, allowed_options), do: Map.has_key?(allowed_options, option) defp build_args(%Helm{ global_options: global_options, options: options, command: cmd, args: args }) do [ [ [Enum.map(global_options, &build_options/1) | [cmd]] | args ] | Enum.map(options, &build_options/1) ] |> List.flatten() end defp build_options(%Option{name: name, require_arg: false}) do ~w(#{name}) end defp build_options(%Option{name: name, value: value, require_arg: true}) do ~w(#{name} #{value}) end defp helm_path do case Application.get_env(:helmex, :helm_path, nil) do nil -> System.find_executable("helm") path -> path end end end