Packages
altworx_runbox
13.0.2
25.0.0
24.0.0
23.1.0
23.0.0
22.2.0
22.1.0
22.0.0
21.2.0
21.1.2
21.1.1
21.1.0
21.0.0
20.0.0
19.0.0
18.0.0
17.2.0
17.1.0
17.0.1
17.0.0
16.2.0
16.1.0
16.0.0
15.0.0
14.1.0
14.0.1
14.0.0
13.0.3
13.0.2
13.0.1
13.0.0
12.1.0
12.0.0
11.0.1
11.0.0
10.0.0
9.0.0
8.0.0
7.0.1
7.0.0
6.0.0
5.0.0
4.0.0
3.0.0
2.1.0
2.0.0
1.4.1
1.4.0
1.3.0
1.2.0
1.1.0
1.0.0
0.1.3
0.1.2
0.1.1
0.1.0
Runbox is a library for running Altworx scenarios.
Current section
Files
Jump to
Current section
Files
lib/runbox/scenario_release.ex
defmodule Runbox.ScenarioRelease do
@moduledoc group: :internal
@moduledoc """
Module for inspecting a scenario release.
"""
alias Runbox.Scenario
alias Runbox.ScenarioTemplate
alias Runbox.Slave
defmodule SlaveFunc do
require Logger
@moduledoc group: :internal
@moduledoc """
Functions which are called on the scenario slave via RPC from the master
node.
"""
alias Runbox.Scenario.TemplateInspector
alias Runbox.Scenario.Type
@spec release_info([module] | nil) :: [Scenario.t()]
def release_info(modules \\ nil) do
modules_to_scenarios(modules || release_modules())
end
@doc """
Returns list of scenarios in release.
"""
@spec scenarios :: [scenario_id :: String.t()]
def scenarios do
release_modules()
|> Enum.filter(&Scenario.manifest_module?/1)
|> Enum.flat_map(fn manifest_mod ->
with {:ok, manifest} <- scenario_manifest_info(manifest_mod),
:ok <- validate_scenario_type(manifest.type, manifest_mod) do
[manifest.id]
else
:error ->
[]
end
end)
end
@doc """
Returns all modules of the scenario app.
"""
@spec release_modules() :: [module()]
def release_modules do
scenario_app = Application.fetch_env!(:runbox, :scenario_app)
case :application.get_key(scenario_app, :modules) do
{:ok, modules} -> modules
:undefined -> []
end
end
defp modules_to_scenarios(modules) do
modules
|> Enum.filter(&Scenario.manifest_module?/1)
|> Enum.flat_map(fn manifest_mod ->
with {:ok, manifest} <- scenario_manifest_info(manifest_mod),
:ok <- validate_scenario_type(manifest.type, manifest_mod) do
opts = scenario_opts(manifest_mod)
templates = scenario_templates(modules, manifest_mod, manifest)
[
%Scenario{
manifest: manifest,
opts: opts,
templates: templates
}
]
else
:error ->
[]
end
end)
end
defp scenario_templates(modules, manifest_mod, manifest) do
template_modules = Enum.filter(modules, &Scenario.template_module?(&1, manifest_mod))
%{template_inspector: inspector_mod} = Scenario.get_impl_for(manifest.type)
Enum.flat_map(template_modules, fn mod ->
if valid_template?(inspector_mod, mod) do
info = template_info(inspector_mod, mod)
[%ScenarioTemplate{module: mod, info: info}]
else
[]
end
end)
end
defp validate_scenario_type(type, manifest_mod) do
if type in Type.all_types() do
:ok
else
Logger.error(
"Ignoring manifest module #{inspect(manifest_mod)} because it has invalid type '#{type}'"
)
:error
end
end
defp scenario_manifest_info(manifest_mod) do
{:ok, manifest_mod.get_info()}
catch
kind, value ->
Logger.error(
"Error reading info of manifest #{inspect(manifest_mod)}: #{inspect({kind, value})}"
)
Logger.error("Ignoring manifest module #{inspect(manifest_mod)}")
:error
end
defp scenario_opts(manifest_mod) do
if Code.ensure_loaded?(manifest_mod) && function_exported?(manifest_mod, :on_start, 0) do
%{on_start: {manifest_mod, :on_start, []}}
else
%{}
end
end
defp valid_template?(inspector_mod, template_mod) do
TemplateInspector.valid_template?(inspector_mod, template_mod)
end
defp template_info(inspector_mod, template_mod) do
TemplateInspector.template_info(inspector_mod, template_mod)
end
end
@doc """
Retrieves information about scenarios in a release.
"""
@spec release_info(String.t()) :: {:ok, [Scenario.t()]} | {:error, term()}
def release_info(release_dir) do
Slave.with_slave(release_dir, fn slave ->
Slave.call(slave, SlaveFunc, :release_info, [])
end)
end
end