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