defmodule Marea.Plugins.Run do
@moduledoc """
Execution subcommands: `marea run local`, `run release`, `run docker`.
Each command returns `{:cmd, shell_command}` so the parent shell takes
over for an interactive session (IEx, release start, docker run).
See the [Run Plugin](run.html) guide.
"""
use Malla.Plugin, plugin_deps: [Marea.Plugins.Base]
alias Marea.{Lib, Config}
## ===================================================================
## Args
## ===================================================================
defcb marea_config_args(args) do
alias Marea.Config.Args
subcommands = [
run: [
name: "run",
about: "Execute related operations",
subcommands: [
local: [
name: "local",
about: "Executes system with dev mix environment",
options: [
Args.cookie_option(),
Args.pos_option()
]
],
release: [
name: "release",
about: "Executes release",
options: [
Args.deploy_option(),
Args.release_option(),
Args.cookie_option(),
Args.pos_option()
]
],
docker: [
name: "docker",
about: "Executes release",
options: [
Args.deploy_option(),
Args.release_option(),
Args.cookie_option(),
Args.pos_option()
]
]
]
]
]
{:cont, [Args.add_subcommands(args, subcommands)]}
end
## ===================================================================
## Callbacks
## ===================================================================
defcb marea_cmd([:run | rest], %Config{} = config), do: run_cmd(rest, config)
defcb marea_cmd(_cmds, _config), do: :cont
## ===================================================================
## Commands
## ===================================================================
@doc """
Public so `Marea.Plugins.Build` can chain into it when `--run` is set
on `build release`. Returns the same `{:cmd, ...}` shape as the
command callback.
"""
@spec run_cmd([atom()], Config.t()) ::
{:cmd, String.t()} | {:cmd, String.t(), Config.t()} | :usage
def run_cmd([:local], config) do
cookie = config.options.cookie
pos = config.options.pos
node_name = if pos == 0, do: "marea", else: "marea_#{pos}"
cmd =
"ENV=dev TARGET=local " <>
"iex --name #{node_name}@127.0.0.1 --cookie \"#{cookie}\" -S mix run"
{:cmd, cmd}
end
def run_cmd([:release], config) do
{deploy, _deploy_data, release, _release_data} = Lib.get_release!(config)
pos = config.options.pos
node_name = if pos == 0, do: release, else: "#{release}_#{pos}"
node_host = "127.0.0.1"
httpd_port = to_string(3001 + pos)
vars = [
"NODE_HOST=#{node_host}",
"NODE_NAME=#{node_name}",
"RELEASE_COOKIE=#{config.options.cookie}",
"MAREA_RELEASE=#{release}",
"MAREA_DEPLOY=#{deploy}",
"MAREA_SYSTEM_PORT=#{httpd_port}"
]
cmd = "#{Enum.join(vars, " ")} _build/prod/rel/#{release}/bin/#{release} start_iex"
{:cmd, cmd, config}
end
def run_cmd([:docker], config) do
{deploy, _deploy_data, release, _release_data} = Lib.get_release!(config)
pos = config.options.pos
node_name = if pos == 0, do: release, else: "#{release}_#{pos}"
image_tag =
case config.values[:git_vsn] do
nil -> "latest"
vsn -> vsn
end
[
["deploy", deploy],
["release", release],
["pos", pos],
["node", node_name],
["image_tag", image_tag]
]
|> Lib.print_table("DOCKER RUN")
parts = [
"docker run",
"-ti",
"--rm",
"-e MAREA_RELEASE=#{release}",
"-e MAREA_DEPLOY=#{deploy}",
"-e NK_SYSTEM_PORT=0",
"--hostname #{node_name}",
"--name #{node_name}",
"--platform arm64",
"#{release}:#{image_tag}",
case config.options do
%{console: true} -> "/opt/#{release}/bin/#{release} start_iex"
_ -> ""
end
]
{:cmd, Enum.join(parts, " ")}
end
def run_cmd(_, _config), do: :usage
end