Skip to content

Commit

Permalink
add integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mruoss committed Dec 15, 2023
1 parent eac0836 commit 44abea6
Show file tree
Hide file tree
Showing 12 changed files with 262 additions and 14 deletions.
1 change: 0 additions & 1 deletion .github/workflows/code_quality.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ on:

env:
MIX_ENV: test
KUBECONFIG: /home/runner/.kube/config

jobs:
code-quality:
Expand Down
52 changes: 52 additions & 0 deletions .github/workflows/integration.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: Integration Tests
on:
push:
branches: [main]
pull_request:
branches: [main]

env:
MIX_ENV: test
KUBECONFIG: /home/runner/.kube/config

jobs:
code-quality:
name: Integration Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4

- name: Setup elixir
id: beam
uses: erlef/setup-beam@v1
with:
version-file: .tool-versions
version-type: strict
install-rebar: true
install-hex: true

- name: Retrieve Build Cache
uses: actions/cache@v3
id: build-folder-cache
with:
path: _build/test
key: ${{ runner.os }}-${{ steps.beam.outputs.otp-version }}-${{ steps.beam.outputs.elixir-version }}-build-test-${{ hashFiles(format('{0}{1}', github.workspace, '/mix.lock')) }}

- name: Retrieve Mix Dependencies Cache
uses: actions/cache@v3
id: mix-cache
with:
path: deps
key: ${{ runner.os }}-${{ steps.beam.outputs.otp-version }}-${{ steps.beam.outputs.elixir-version }}-mix-${{ hashFiles(format('{0}{1}', github.workspace, '/mix.lock')) }}

- name: Install Mix Dependencies
run: mix deps.get

- uses: engineerd/[email protected]
id: kind
with:
version: v0.20.0
name: flame-integration-test

- name: Integration Tests
run: MIX_ENV=test mix test --only integration
16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,17 @@ end
Configure the flame backend in our configuration.

```elixir
# config.exs
if config_env() == :prod do
config :flame, :backend, FLAMEK8sBackend
config :flame, FLAMEK8sBackend, log: :debug
end
# application.ex
children = [
{FLAME.Pool,
name: MyApp.SamplePool,
backend: {FLAMEK8sBackend, insecure_skip_tls_verify: true},
min: 0,
max: 10,
max_concurrency: 5,
idle_shutdown_after: 30_000,
log: :debug}
]
```

## Prerequisites
Expand Down
3 changes: 3 additions & 0 deletions config/config.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import Config

config :flame, :terminator, log: :debug
2 changes: 0 additions & 2 deletions lib/flame_k8s_backend.ex
Original file line number Diff line number Diff line change
Expand Up @@ -318,8 +318,6 @@ defmodule FLAMEK8sBackend do

defp log(state, msg, metadata \\ [])

defp log(state, msg, metadata \\ [])

defp log(%FLAMEK8sBackend{log: false}, _, _), do: :ok

defp log(%FLAMEK8sBackend{log: level}, msg, metadata) do
Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ defmodule FlameK8sBackend.MixProject do
# Run "mix help deps" to learn about dependencies.
defp deps do
[
{:flame, "~> 0.1.6"},
{:flame, github: "phoenixframework/flame"},
{:req, "~> 0.4.5"},
{:credo, "~> 1.7", only: [:dev, :test], runtime: false},
{:mix_test_watch, "~> 1.0", only: [:dev, :test], runtime: false},
Expand Down
8 changes: 4 additions & 4 deletions mix.lock
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
%{
"bunt": {:hex, :bunt, "0.2.1", "e2d4792f7bc0ced7583ab54922808919518d0e57ee162901a16a1b6664ef3b14", [:mix], [], "hexpm", "a330bfb4245239787b15005e66ae6845c9cd524a288f0d141c148b02603777a5"},
"castore": {:hex, :castore, "1.0.4", "ff4d0fb2e6411c0479b1d965a814ea6d00e51eb2f58697446e9c41a97d940b28", [:mix], [], "hexpm", "9418c1b8144e11656f0be99943db4caf04612e3eaecefb5dae9a2a87565584f8"},
"castore": {:hex, :castore, "1.0.5", "9eeebb394cc9a0f3ae56b813459f990abb0a3dedee1be6b27fdb50301930502f", [:mix], [], "hexpm", "8d7c597c3e4a64c395980882d4bca3cebb8d74197c590dc272cfd3b6a6310578"},
"credo": {:hex, :credo, "1.7.1", "6e26bbcc9e22eefbff7e43188e69924e78818e2fe6282487d0703652bc20fd62", [:mix], [{:bunt, "~> 0.2.1", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "e9871c6095a4c0381c89b6aa98bc6260a8ba6addccf7f6a53da8849c748a58a2"},
"earmark_parser": {:hex, :earmark_parser, "1.4.39", "424642f8335b05bb9eb611aa1564c148a8ee35c9c8a8bba6e129d51a3e3c6769", [:mix], [], "hexpm", "06553a88d1f1846da9ef066b87b57c6f605552cfbe40d20bd8d59cc6bde41944"},
"ex_doc": {:hex, :ex_doc, "0.30.9", "d691453495c47434c0f2052b08dd91cc32bc4e1a218f86884563448ee2502dd2", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "d7aaaf21e95dc5cddabf89063327e96867d00013963eadf2c6ad135506a8bc10"},
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
"finch": {:hex, :finch, "0.16.0", "40733f02c89f94a112518071c0a91fe86069560f5dbdb39f9150042f44dcfb1a", [: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", "f660174c4d519e5fec629016054d60edd822cdfe2b7270836739ac2f97735ec5"},
"flame": {:hex, :flame, "0.1.6", "d657bb9c9103597ad9dcfac1f3ef728ac79ee38419d44bb1179e7b80a5015c6e", [:mix], [{:req, "~> 0.4.5", [hex: :req, repo: "hexpm", optional: false]}], "hexpm", "bd3f2c444d7df9823cf26bc4a5299a56656da3b0b7f0e80269b25a071eb4ff6c"},
"flame": {:git, "https://github.com/phoenixframework/flame.git", "a99467d65443ab96a7e21e4cf645664678647c72", []},
"hpax": {:hex, :hpax, "0.1.2", "09a75600d9d8bbd064cdd741f21fc06fc1f4cf3d0fcc335e5aa19be1a7235c84", [:mix], [], "hexpm", "2c87843d5a23f5f16748ebe77969880e29809580efdaccd615cd3bed628a8c13"},
"jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"},
"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"},
Expand All @@ -17,11 +17,11 @@
"mint": {:hex, :mint, "1.5.2", "4805e059f96028948870d23d7783613b7e6b0e2fb4e98d720383852a760067fd", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "d77d9e9ce4eb35941907f1d3df38d8f750c357865353e21d335bdcdf6d892a02"},
"mint_web_socket": {:hex, :mint_web_socket, "1.0.3", "aab42fff792a74649916236d0b01f560a0b3f03ca5dea693c230d1c44736b50e", [:mix], [{:mint, ">= 1.4.1 and < 2.0.0-0", [hex: :mint, repo: "hexpm", optional: false]}], "hexpm", "ca3810ca44cc8532e3dce499cc17f958596695d226bb578b2fbb88c09b5954b0"},
"mix_test_watch": {:hex, :mix_test_watch, "1.1.1", "eee6fc570d77ad6851c7bc08de420a47fd1e449ef5ccfa6a77ef68b72e7e51ad", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}], "hexpm", "f82262b54dee533467021723892e15c3267349849f1f737526523ecba4e6baae"},
"nimble_options": {:hex, :nimble_options, "1.0.2", "92098a74df0072ff37d0c12ace58574d26880e522c22801437151a159392270e", [:mix], [], "hexpm", "fd12a8db2021036ce12a309f26f564ec367373265b53e25403f0ee697380f1b8"},
"nimble_options": {:hex, :nimble_options, "1.1.0", "3b31a57ede9cb1502071fade751ab0c7b8dbe75a9a4c2b5bbb0943a690b63172", [:mix], [], "hexpm", "8bbbb3941af3ca9acc7835f5655ea062111c9c27bcac53e004460dfd19008a99"},
"nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"},
"nimble_pool": {:hex, :nimble_pool, "1.0.0", "5eb82705d138f4dd4423f69ceb19ac667b3b492ae570c9f5c900bb3d2f50a847", [:mix], [], "hexpm", "80be3b882d2d351882256087078e1b1952a28bf98d0a287be87e4a24a710b67a"},
"poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm", "dad79704ce5440f3d5a3681c8590b9dc25d1a561e8f5a9c995281012860901e3"},
"req": {:hex, :req, "0.4.7", "70a9b3866bf9962bab48b3b6471e2677dc211e381d971ef7c199c138b4cfeba8", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.9", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "1c1272996241c0ea9d5a6bb383ec37ec9c948ae3cedff32dc62a6c4d6476f5d8"},
"req": {:hex, :req, "0.4.8", "2b754a3925ddbf4ad78c56f30208ced6aefe111a7ea07fb56c23dccc13eb87ae", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.9", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "7146e51d52593bb7f20d00b5308a5d7d17d663d6e85cd071452b613a8277100c"},
"telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"},
"yamerl": {:hex, :yamerl, "0.10.0", "4ff81fee2f1f6a46f1700c0d880b24d193ddb74bd14ef42cb0bcf46e81ef2f8e", [:rebar3], [], "hexpm", "346adb2963f1051dc837a2364e4acf6eb7d80097c0f53cbdc3046ec8ec4b4e6e"},
"yaml_elixir": {:hex, :yaml_elixir, "2.9.0", "9a256da867b37b8d2c1ffd5d9de373a4fda77a32a45b452f1708508ba7bbcb53", [:mix], [{:yamerl, "~> 0.10", [hex: :yamerl, repo: "hexpm", optional: false]}], "hexpm", "0cb0e7d4c56f5e99a6253ed1a670ed0e39c13fc45a6da054033928607ac08dfc"},
Expand Down
20 changes: 20 additions & 0 deletions test/integration/Dockerfile.integration
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

FROM hexpm/elixir:1.15.7-erlang-26.1.2-debian-buster-20231009

ENV MIX_ENV=test \
MIX_HOME=/opt/mix \
HEX_HOME=/opt/hex

RUN mix local.hex --force && \
mix local.rebar --force && \
apt-get update && apt-get install -y git

WORKDIR /app

COPY . .

RUN mix deps.get --only-prod && \
mix deps.clean --unused && \
mix deps.compile

CMD ["sh", "-c", "iex --name ${RELEASE_NODE} --cookie nosecret -S mix run -e 'FlameK8sBackend.IntegrationTestRunner.runner()'"]
54 changes: 54 additions & 0 deletions test/integration/integration_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
defmodule FlameK8sBackend.IntegrationTest do
use ExUnit.Case

setup_all do
{clusters_out, exit_code} = System.cmd("kind", ~w(get clusters))
assert 0 == exit_code, "kind is not installed. Please install kind."

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")
assert 0 == exit_code, "Could not create kind cluster 'flame-integration-test'"
end

Mix.Shell.IO.cmd(
"docker build -f test/integration/Dockerfile.integration . -t flamek8sbackend:integration"
)

Mix.Shell.IO.cmd(
"kind load docker-image --name flame-integration-test flamek8sbackend:integration"
)

Mix.Shell.IO.cmd("kubectl config set-context 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")

on_exit(fn ->
Mix.Shell.IO.cmd("kubectl delete -f test/integration/manifest.yaml")
end)

:ok
end

defp assert_logs_eventually(_pattern, timeout) when timeout < 0 do
:not_found
end

defp assert_logs_eventually(pattern, timeout) do
with {logs, 0} <- System.cmd("kubectl", ~w"-n integration logs integration"),
true <- Regex.match?(pattern, logs) do
:ok
else
_ ->
Process.sleep(300)
assert_logs_eventually(pattern, timeout - 300)
end
end

@tag :integration
test "check the logs" do
assert :ok == assert_logs_eventually(~r/Result is :flame_ok/, 30_000),
"Logs were not found"
end
end
81 changes: 81 additions & 0 deletions test/integration/manifest.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
---
apiVersion: v1
kind: Namespace
metadata:
name: integration
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: integration
namespace: integration
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: integration
name: pod-mgr
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["create", "get", "list", "delete", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: integration-pod-mgr
namespace: integration
subjects:
- kind: ServiceAccount
name: integration
namespace: integration
roleRef:
kind: Role
name: pod-mgr
apiGroup: rbac.authorization.k8s.io
---
apiVersion: v1
kind: Pod
metadata:
name: integration
namespace: integration
labels:
app: flame_test
spec:
serviceAccountName: integration
containers:
- name: integration
image: flamek8sbackend:integration
command: ["sh", "-c"]
args: ["iex --name flame_test@$(POD_IP) --cookie nosecret -S mix run -e FlameK8sBackend.IntegrationTestRunner.run_flame"]
resources:
requests:
cpu: 300m
memory: 300Mi
limits:
cpu: 300m
memory: 300Mi
env:
- name: POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
- name: POD_IP
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: status.podIP
- name: RELEASE_DISTRIBUTION
value: name
- name: RELEASE_NODE
value: flame_test@$(POD_IP)
ports:
- containerPort: 80
name: integration
restartPolicy: Always
2 changes: 1 addition & 1 deletion test/test_helper.exs
Original file line number Diff line number Diff line change
@@ -1 +1 @@
ExUnit.start()
ExUnit.start(exclude: [:integration])
35 changes: 35 additions & 0 deletions test_support/integration_test_runner.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
defmodule FlameK8sBackend.IntegrationTestRunner do
require Logger

def setup() do
Application.ensure_all_started(:flame)

children = [{
FLAME.Pool,
name: IntegrationTest.Runner,
min: 0,
max: 2,
idle_shutdown_after: 1_000,
backend: {FLAMEK8sBackend, insecure_skip_tls_verify: true},
log: :debug
}]

Supervisor.start_link(children, strategy: :one_for_one)
end

def run_flame() do
setup()

result =
FLAME.call(IntegrationTest.Runner, fn ->
:flame_ok
end)

Logger.info("Result is #{inspect(result)}")
end

def runner() do
setup()
Process.sleep(60_000)
end
end

0 comments on commit 44abea6

Please sign in to comment.