diff --git a/.formatter.exs b/.formatter.exs index d2cda26..d9f62cc 100644 --- a/.formatter.exs +++ b/.formatter.exs @@ -1,4 +1,4 @@ # Used by "mix format" [ - inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] + inputs: ["{mix,.formatter}.exs", "{config,lib,test,test_support}/**/*.{ex,exs}"] ] diff --git a/.rtx.toml b/.mise.toml similarity index 75% rename from .rtx.toml rename to .mise.toml index 75c9d05..90db7d4 100644 --- a/.rtx.toml +++ b/.mise.toml @@ -1 +1,2 @@ +[env] env_file = '.env' diff --git a/CHANGELOG.md b/CHANGELOG.md index ac32e9e..24710cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,10 +10,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - +### Fixed + +- Set `RELEASE_COOKIE`, `RELEASE_DISTRIBUTION` and `RELEASE_NODE` on runner pod if not set [#50](https://github.com/mruoss/flame_k8s_backend/issues/50), [#53](https://github.com/mruoss/flame_k8s_backend/pull/53) ## [0.5.4] - 2024-09-11 + + ### Changed - Upgrade to FLAME 0.5.0 diff --git a/lib/flame_k8s_backend/runner_pod_template.ex b/lib/flame_k8s_backend/runner_pod_template.ex index e6f0094..0143dd9 100644 --- a/lib/flame_k8s_backend/runner_pod_template.ex +++ b/lib/flame_k8s_backend/runner_pod_template.ex @@ -293,11 +293,16 @@ defmodule FLAMEK8sBackend.RunnerPodTemplate do ) ] |> put_new_env("PHX_SERVER", "false") + |> put_new_env("RELEASE_SECRET", Node.get_cookie()) + |> put_new_env("RELEASE_DISTRIBUTION", "name") + |> put_new_env("RELEASE_NODE", "flame_runner@$(POD_IP)") end) end) end) end + defp put_new_env(env, _name, :nocookie), do: env + defp put_new_env(env, name, value) do case get_in(env, [Access.filter(&(&1["name"] == name))]) do [] -> [%{"name" => name, "value" => value} | env] diff --git a/mix.lock b/mix.lock index 4dd2c9f..c79f67a 100644 --- a/mix.lock +++ b/mix.lock @@ -1,12 +1,12 @@ %{ "bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"}, "castore": {:hex, :castore, "1.0.7", "b651241514e5f6956028147fe6637f7ac13802537e895a724f90bf3e36ddd1dd", [:mix], [], "hexpm", "da7785a4b0d2a021cd1292a60875a784b6caef71e76bf4917bdee1f390455cf5"}, - "credo": {:hex, :credo, "1.7.7", "771445037228f763f9b2afd612b6aa2fd8e28432a95dbbc60d8e03ce71ba4446", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "8bc87496c9aaacdc3f90f01b7b0582467b69b4bd2441fe8aae3109d843cc2f2e"}, + "credo": {:hex, :credo, "1.7.8", "9722ba1681e973025908d542ec3d95db5f9c549251ba5b028e251ad8c24ab8c5", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "cb9e87cc64f152f3ed1c6e325e7b894dea8f5ef2e41123bd864e3cd5ceb44968"}, "earmark_parser": {:hex, :earmark_parser, "1.4.41", "ab34711c9dc6212dda44fcd20ecb87ac3f3fce6f0ca2f28d4a00e4154f8cd599", [:mix], [], "hexpm", "a81a04c7e34b6617c2792e291b5a2e57ab316365c2644ddc553bb9ed863ebefa"}, "ex_doc": {:hex, :ex_doc, "0.34.2", "13eedf3844ccdce25cfd837b99bea9ad92c4e511233199440488d217c92571e8", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "5ce5f16b41208a50106afed3de6a2ed34f4acfd65715b82a0b84b49d995f95c1"}, - "file_system": {:hex, :file_system, "1.0.0", "b689cc7dcee665f774de94b5a832e578bd7963c8e637ef940cd44327db7de2cd", [:mix], [], "hexpm", "6752092d66aec5a10e662aefeed8ddb9531d79db0bc145bb8c40325ca1d8536d"}, + "file_system": {:hex, :file_system, "1.0.1", "79e8ceaddb0416f8b8cd02a0127bdbababe7bf4a23d2a395b983c1f8b3f73edd", [:mix], [], "hexpm", "4414d1f38863ddf9120720cd976fce5bdde8e91d8283353f0e31850fa89feb9e"}, "finch": {:hex, :finch, "0.18.0", "944ac7d34d0bd2ac8998f79f7a811b21d87d911e77a786bc5810adb75632ada4", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6 or ~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "69f5045b042e531e53edc2574f15e25e735b522c37e2ddb766e15b979e03aa65"}, - "flame": {:hex, :flame, "0.4.0", "bf86dff472455753f96496d9d6a0a6a411b4de3788def4429a8cea30a5927df1", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: true]}, {:jason, ">= 0.0.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "98f0c28fef992592c0d10f854b38ac4b8c1242d8576605af75f6eb56e309a115"}, + "flame": {:hex, :flame, "0.5.1", "339130ed9dff761efc1b2c001839e6d16aa9af291a1e155d8c14fa9b42c03caa", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: true]}, {:jason, ">= 0.0.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "b09ac62b187f40fa7f959d6faca58aae0e575ff21435a8afd79727b8e5631085"}, "hpax": {:hex, :hpax, "0.2.0", "5a58219adcb75977b2edce5eb22051de9362f08236220c9e859a47111c194ff5", [:mix], [], "hexpm", "bea06558cdae85bed075e6c036993d43cd54d447f76d8190a8db0dc5893fa2f1"}, "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, "k8s": {:hex, :k8s, "2.5.0", "16ceef480cf1503ad561529ef93c87d921b4baa29d73ee16cebae13d37e218f4", [:mix], [{:castore, "~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: false]}, {:mint_web_socket, "~> 1.0", [hex: :mint_web_socket, repo: "hexpm", optional: false]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:yaml_elixir, "~> 2.8", [hex: :yaml_elixir, repo: "hexpm", optional: false]}], "hexpm", "c46032a4eef273000d32608efbc2edbdfde480d5f24df69e0938daa01026d1eb"}, diff --git a/test/flame_k8s_backend/runner_pod_template_test.exs b/test/flame_k8s_backend/runner_pod_template_test.exs index a29f934..a8e92df 100644 --- a/test/flame_k8s_backend/runner_pod_template_test.exs +++ b/test/flame_k8s_backend/runner_pod_template_test.exs @@ -49,7 +49,11 @@ defmodule FLAMEK8sBackend.RunnerPodTemplateTest do end pod_manifest = MUT.manifest(parent_pod_manifest, callback, make_ref()) + + # sets defaults for required ENV vars: assert get_in(pod_manifest, env_var_access("PHX_SERVER")) == ["false"] + assert get_in(pod_manifest, env_var_access("RELEASE_DISTRIBUTION")) == ["name"] + assert get_in(pod_manifest, env_var_access("RELEASE_NODE")) == ["flame_runner@$(POD_IP)"] end test "should return pod manifest with data form callback", %{ @@ -230,7 +234,6 @@ defmodule FLAMEK8sBackend.RunnerPodTemplateTest do template_opts = %MUT{env: [%{"name" => "FOO", "value" => "bar"}], add_parent_env: false} pod_manifest = MUT.manifest(parent_pod_manifest, template_opts, make_ref()) - assert get_in(pod_manifest, env_var_access("RELEASE_NODE")) == [] assert get_in(pod_manifest, env_var_access("FOO")) == ["bar"] assert get_in(pod_manifest, app_container_access("envFrom")) == [] end diff --git a/test/integration/integration_test.exs b/test/integration/integration_test.exs index 37f938b..23fa263 100644 --- a/test/integration/integration_test.exs +++ b/test/integration/integration_test.exs @@ -8,24 +8,35 @@ defmodule FlameK8sBackend.IntegrationTest do if not (clusters_out |> String.split("\n", trim: true) |> Enum.member?("flame-integration-test")) do - exit_code = Mix.Shell.IO.cmd("kind create cluster --name flame-integration-test") + exit_code = + System.cmd("kind", ~w(create cluster --name flame-integration-test), + stderr_to_stdout: true + ) + assert 0 == exit_code, "Could not create kind cluster 'flame-integration-test'" end - Mix.Shell.IO.cmd( - "docker build -f test/integration/Dockerfile . -t flamek8sbackend:integration" + System.cmd( + "docker", + ~w(build -f test/integration/Dockerfile . -t flamek8sbackend:integration), + stderr_to_stdout: true + ) + + System.cmd( + "kind", + ~w(load docker-image --name flame-integration-test flamek8sbackend:integration), + stderr_to_stdout: true ) - Mix.Shell.IO.cmd( - "kind load docker-image --name flame-integration-test flamek8sbackend:integration" + System.cmd("kubectl", ~w(config set-context --current kind-flame-integration-test), + stderr_to_stdout: true ) - Mix.Shell.IO.cmd("kubectl config set-context --current kind-flame-integration-test") - Mix.Shell.IO.cmd("kubectl delete -f test/integration/manifest.yaml") - Mix.Shell.IO.cmd("kubectl apply -f test/integration/manifest.yaml") + System.cmd("kubectl", ~w(delete -f test/integration/manifest.yaml), stderr_to_stdout: true) + System.cmd("kubectl", ~w(apply -f test/integration/manifest.yaml), stderr_to_stdout: true) on_exit(fn -> - Mix.Shell.IO.cmd("kubectl delete -f test/integration/manifest.yaml") + System.cmd("kubectl", ~w(delete -f test/integration/manifest.yaml), stderr_to_stdout: true) end) :ok @@ -46,9 +57,19 @@ defmodule FlameK8sBackend.IntegrationTest do end end + # Integration test setup builds a docker image which starts the FLAME pools + # defined in FlameK8sBackend.IntegrationTestRunner and starts a runner for + #  each pool. It then logs the result. These checks "just" check that the logs + #  statements are actually visible on the pod logs: @tag :integration - test "check the logs" do + test "Pod shows the log statement with the result of the first runner " do assert :ok == assert_logs_eventually(~r/Result is :flame_ok/, 30_000), "Logs were not found" end + + @tag :integration + test "Pod shows the log statement with the result of the first runner" do + assert :ok == assert_logs_eventually(~r/Result is "foobar"/, 30_000), + "Logs were not found" + end end diff --git a/test_support/integration_test_runner.ex b/test_support/integration_test_runner.ex index 019c3d4..870856d 100644 --- a/test_support/integration_test_runner.ex +++ b/test_support/integration_test_runner.ex @@ -1,11 +1,24 @@ defmodule FlameK8sBackend.IntegrationTestRunner do require Logger + import YamlElixir.Sigil + def setup() do Application.ensure_all_started(:flame) - children = [{ - FLAME.Pool, + pod_template_callback = fn _ -> + ~y""" + spec: + containers: + - env: + - name: "FOO" + value: "foobar" + """ + end + + children = [ + { + FLAME.Pool, name: IntegrationTest.Runner, min: 0, max: 2, @@ -16,7 +29,21 @@ defmodule FlameK8sBackend.IntegrationTestRunner do backend: FLAMEK8sBackend, track_resources: true, log: :debug - }] + }, + { + FLAME.Pool, + name: IntegrationTest.CallbackRunner, + min: 0, + max: 2, + max_concurrency: 10, + boot_timeout: :timer.minutes(3), + idle_shutdown_after: :timer.minutes(1), + timeout: :infinity, + backend: {FLAMEK8sBackend, runner_pod_tpl: pod_template_callback}, + track_resources: true, + log: :debug + } + ] Supervisor.start_link(children, strategy: :one_for_one) end @@ -24,12 +51,13 @@ defmodule FlameK8sBackend.IntegrationTestRunner do def run_flame() do setup() - result = - FLAME.call(IntegrationTest.Runner, fn -> - :flame_ok - end) - - Logger.info("Result is #{inspect(result)}") + [ + {IntegrationTest.Runner, fn -> :flame_ok end}, + {IntegrationTest.CallbackRunner, fn -> System.get_env("FOO") end} + ] + |> Enum.map(fn {pool, fun} -> Task.async(fn -> FLAME.call(pool, fun) end) end) + |> Task.await_many(:infinity) + |> Enum.each(fn result -> Logger.info("Result is #{inspect(result)}") end) end def runner() do