-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: add build check status * feat: init status * fix: app startup * fix: call :check * feat: status state * fix: kub url * fix: kub url * fix: add alias * fix: build error & already exist * fix: credo * fix: format * fix: credo * fix: prod secret * fix: config * fix: test * fix: test * fix: dialyzer
- Loading branch information
Showing
7 changed files
with
313 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
defmodule Lenra.Kubernetes.Status do | ||
@moduledoc """ | ||
Lenra.Kubernetes.Status check status for kubernetes build | ||
""" | ||
use GenServer | ||
use SwarmNamed | ||
|
||
alias Lenra.Apps.Build | ||
alias LenraCommon.Errors.DevError | ||
alias LenraCommon.Errors.TechnicalError | ||
alias Lenra.{Apps, Repo} | ||
|
||
require Logger | ||
|
||
@check_delay 10_000 | ||
|
||
def start_link(opts) do | ||
case Keyword.fetch(opts, :build_id) do | ||
{:ok, build_id} -> | ||
GenServer.start_link(__MODULE__, opts, name: get_full_name({build_id})) | ||
|
||
:error -> | ||
raise DevError.exception(message: "Status need a build_id, a namespace and an job_name") | ||
end | ||
end | ||
|
||
def init(init_arg) do | ||
{:ok, build_id} = Keyword.fetch(init_arg, :build_id) | ||
{:ok, namespace} = Keyword.fetch(init_arg, :namespace) | ||
{:ok, job_name} = Keyword.fetch(init_arg, :job_name) | ||
|
||
{:ok, [build_id: build_id, namespace: namespace, job_name: job_name]} | ||
end | ||
|
||
def handle_info(:check, state) do | ||
case check_job_status(state) do | ||
:success -> check_and_update_build_status(state[:build_id], :success) | ||
:failure -> check_and_update_build_status(state[:build_id], :failure) | ||
:running -> Process.send_after(self(), :check, @check_delay) | ||
end | ||
|
||
{:noreply, state} | ||
end | ||
|
||
defp check_job_status(job) do | ||
Logger.debug("#{__MODULE__} Check job status for #{inspect(job)}") | ||
kubernetes_api_url = Application.fetch_env!(:lenra, :kubernetes_api_url) | ||
kubernetes_api_token = Application.fetch_env!(:lenra, :kubernetes_api_token) | ||
|
||
url = "#{kubernetes_api_url}/apis/batch/v1/namespaces/#{job[:namespace]}/jods/#{job[:job_name]}/status" | ||
|
||
headers = [{"Authorization", "Bearer #{kubernetes_api_token}"}] | ||
|
||
Finch.build(:get, url, headers) | ||
|> Finch.request(PipelineHttp) | ||
|> response() | ||
|> case do | ||
{:ok, body} -> | ||
body | ||
|> extract_job_status | ||
|> case do | ||
%{"succeeded" => 1} -> | ||
Logger.debug("#{__MODULE__} Check job #{inspect(job)} success") | ||
:success | ||
|
||
%{"failed" => 1} -> | ||
Logger.debug("#{__MODULE__} Check job #{inspect(job)} failure") | ||
:failure | ||
|
||
_error -> | ||
Logger.debug("#{__MODULE__} Check job #{inspect(job)} frunning") | ||
:running | ||
end | ||
|
||
{:error, reason} -> | ||
Logger.debug("#{__MODULE__} Error while fetching job status") | ||
{:error, reason} | ||
end | ||
end | ||
|
||
defp extract_job_status(response) do | ||
# Extract the job status from the response | ||
response["status"] | ||
end | ||
|
||
defp check_and_update_build_status(build_id, status) do | ||
build = Repo.get(Build, build_id) | ||
|
||
if build.status == status do | ||
{:stop, :normal, [], nil} | ||
else | ||
update_build_status(build, status) | ||
end | ||
end | ||
|
||
defp update_build_status(build, status) do | ||
Logger.debug("#{__MODULE__} Update build status tp #{status}") | ||
|
||
case Apps.update_build(build, %{status: status}) do | ||
{:ok, _res} -> | ||
update_deployment(build) | ||
{:stop, :normal, [], nil} | ||
|
||
{:error, _reason} -> | ||
Logger.error("#{__MODULE__} Error while updating build status") | ||
{:stop, :normal, [], nil} | ||
end | ||
end | ||
|
||
def update_deployment(build) do | ||
build.id | ||
|> Apps.get_deployement_for_build() | ||
|> Apps.update_deployement(%{status: :failure}) | ||
end | ||
|
||
defp response({:ok, %Finch.Response{status: 200, body: body}}) do | ||
{:ok, Jason.decode!(body)} | ||
end | ||
|
||
defp response({:ok, %Finch.Response{status: status_code, body: body}}) do | ||
case status_code do | ||
400 -> | ||
Logger.critical(TechnicalError.bad_request(body)) | ||
TechnicalError.bad_request_tuple(body) | ||
|
||
404 -> | ||
Logger.error(TechnicalError.error_404(body)) | ||
TechnicalError.error_404_tuple(body) | ||
|
||
500 -> | ||
Logger.critical(TechnicalError.bad_request(body)) | ||
TechnicalError.error_500_tuple(body) | ||
|
||
504 -> | ||
Logger.critical(TechnicalError.error_500_tuple(body)) | ||
TechnicalError.error_500_tuple(body) | ||
|
||
_err -> | ||
Logger.critical(TechnicalError.unknown_error(body)) | ||
TechnicalError.unknown_error_tuple(body) | ||
end | ||
end | ||
|
||
def terminate(_reason, state) do | ||
# Perform cleanup operations here, if needed | ||
{:ok, state} | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
defmodule Lenra.Kubernetes.StatusDynSup do | ||
@moduledoc """ | ||
Lenra.Kubernetes.StatusDynSup Manage status Genserver | ||
""" | ||
use DynamicSupervisor | ||
|
||
import Ecto.Query | ||
|
||
alias Lenra.Apps.Build | ||
alias Lenra.Kubernetes.Status | ||
alias Lenra.Repo | ||
|
||
require Logger | ||
|
||
def start_link(opts) do | ||
DynamicSupervisor.start_link(__MODULE__, opts, name: {:via, :swarm, __MODULE__}) | ||
end | ||
|
||
@impl true | ||
def init(_init_arg) do | ||
Logger.debug("#{__MODULE__} init") | ||
DynamicSupervisor.init(strategy: :one_for_one) | ||
end | ||
|
||
def start_build_status(build_id, namespace, job_name) do | ||
Logger.debug("#{__MODULE__} ensure start status for #{inspect([build_id, namespace, job_name])}") | ||
|
||
case start_child(build_id, namespace, job_name) do | ||
{:ok, pid} -> | ||
Logger.info("Lenra.Kubernetes.Status started") | ||
Process.send_after(pid, :check, 10_000) | ||
{:ok, pid} | ||
|
||
{:error, {:already_started, pid}} -> | ||
{:ok, pid} | ||
|
||
err -> | ||
Logger.critical(inspect(err)) | ||
err | ||
end | ||
end | ||
|
||
defp start_child(build_id, namespace, job_name) do | ||
init_value = [ | ||
build_id: build_id, | ||
namespace: namespace, | ||
job_name: job_name | ||
] | ||
|
||
DynamicSupervisor.start_child({:via, :swarm, __MODULE__}, {Status, init_value}) | ||
end | ||
|
||
def init_status do | ||
kubernetes_build_namespace = Application.fetch_env!(:lenra, :kubernetes_build_namespace) | ||
|
||
builds = | ||
Repo.all( | ||
from( | ||
b in Build, | ||
where: b.status == :pending | ||
) | ||
) | ||
|
||
Map.new(builds, fn build -> | ||
preloaded_build = Repo.preload(build, :application) | ||
|
||
build_name = "build-#{preloaded_build.application.service_name}-#{build.build_number}" | ||
|
||
start_build_status(build.id, kubernetes_build_namespace, build_name) | ||
end) | ||
end | ||
end |
Oops, something went wrong.