Skip to content

Commit

Permalink
Restructue catalog code to allow flat catalog return
Browse files Browse the repository at this point in the history
  • Loading branch information
arbulu89 committed Mar 30, 2022
1 parent 5c8fb5b commit a5d179f
Show file tree
Hide file tree
Showing 12 changed files with 489 additions and 93 deletions.
6 changes: 2 additions & 4 deletions config/dev.exs
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,8 @@ config :trento, Trento.Scheduler,
]

config :trento, Trento.Integration.Telemetry, adapter: Trento.Integration.Telemetry.ToLogger

config :trento, Trento.Integration.Checks,
adapter: Trento.Integration.Checks.MockRunner,
runner_url: ""
config :trento, Trento.Integration.Checks, adapter: Trento.Integration.Checks.MockRunner
config :trento, Trento.Integration.Checks.Runner, runner_url: ""

# Do not include metadata nor timestamps in development logs
config :logger, :console, format: "[$level] $message\n"
Expand Down
2 changes: 0 additions & 2 deletions config/prod.exs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,5 @@ config :trento, TrentoWeb.Endpoint,
cache_static_manifest: "priv/static/cache_manifest.json",
server: true

config :trento, Trento.Integration.Checks, runner_url: System.get_env("RUNNER_URL")

# Do not print debug messages in production
# config :logger, level: :info
2 changes: 1 addition & 1 deletion config/runtime.exs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ if config_env() == :prod do
For example: http://localhost:8080
"""

config :trento, Trento.Integration.Checks, runner_url: runner_url
config :trento, Trento.Integration.Checks.Runner, runner_url: runner_url

# ## Using releases
#
Expand Down
7 changes: 2 additions & 5 deletions lib/trento/application/integration/checks/adapter/gen.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@ defmodule Trento.Integration.Checks.Gen do
) ::
:ok | {:error, any}

@callback get_runner_ready_content(runner_url :: String.t()) ::
{:ok, term} | {:error, any}

@callback get_catalog_content(runner_url :: String.t()) ::
{:ok, term} | {:error, any}
@callback get_catalog() ::
{:ok, map} | {:error, any}
end
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,7 @@ defmodule Trento.Integration.Checks.MockRunner do
end

@impl true
def get_runner_ready_content(_runner_url) do
{:ok, %{"ready" => true}}
end

@impl true
def get_catalog_content(_runner_url) do
def get_catalog do
{:ok, @catalog}
end

Expand Down
41 changes: 15 additions & 26 deletions lib/trento/application/integration/checks/adapter/runner.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,48 +5,37 @@ defmodule Trento.Integration.Checks.Runner do

@behaviour Trento.Integration.Checks.Gen

require Logger

@impl true
def request_execution(_execution_id, _cluster_id, _hosts, _selected_checks) do
:ok
end

@impl true
def get_runner_ready_content(runner_url) do
case HTTPoison.get("#{runner_url}/api/ready") do
{:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
Jason.decode(body)
def get_catalog do
runner_url = runner_url()

{:error, %HTTPoison.Error{reason: reason}} ->
Logger.error(
"Failed getting the runner 'ready' state. Reason: #{reason}",
error: reason
)
case HTTPoison.get("#{runner_url}/api/catalog") do
{:ok, %HTTPoison.Response{status_code: 200, body: catalog}} ->
Jason.decode(catalog)

{:error, reason}
{:ok, %HTTPoison.Response{status_code: 204}} ->
{:error, :not_ready}

_ ->
{:error, :unexpected_response}
end
end
{:error, %HTTPoison.Error{reason: :econnrefused}} ->
{:error, "Connection to the runner component on #{runner_url} was refused."}

@impl true
def get_catalog_content(runner_url) do
case HTTPoison.get("#{runner_url}/api/catalog") do
{:ok, %HTTPoison.Response{status_code: 200, body: catalog_raw}} ->
Jason.decode(catalog_raw)
{:error, %HTTPoison.Error{reason: :nxdomain}} ->
{:error,
"Connection url to the runner component host on #{runner_url} could not be resolved."}

{:error, %HTTPoison.Error{reason: reason}} ->
Logger.error(
"Failed to get the checks catalog from the runner. Reason: #{reason}",
error: reason
)

{:error, reason}

_ ->
{:error, :unexpected_response}
end
end

defp runner_url,
do: Application.fetch_env!(:trento, __MODULE__)[:runner_url]
end
58 changes: 23 additions & 35 deletions lib/trento/application/integration/checks/checks.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
defmodule Trento.Integration.Checks do
alias Trento.Integration.Checks.Models.Catalog
alias Trento.Integration.Checks.Models.{
Catalog,
FlatCatalog
}

@moduledoc """
Checks runner service integration
Expand All @@ -10,21 +13,14 @@ defmodule Trento.Integration.Checks do
do: adapter().request_execution(execution_id, cluster_id, hosts, selected_checks)

@spec get_catalog ::
{:ok, Catalog.t()} | {:error, any}
{:ok, FlatCatalog.t()} | {:error, any}
def get_catalog do
case is_catalog_ready(runner_url()) do
:ok ->
get_catalog_content(runner_url())
case adapter().get_catalog() do
{:ok, catalog} ->
FlatCatalog.new(%{checks: catalog})

{:error, reason} ->
{:error, reason}
end
end

defp is_catalog_ready(runner_url) do
case adapter().get_runner_ready_content(runner_url) do
{:ok, content} ->
handle_catalog_ready(content)
{:error, :not_ready} ->
{:error, "The catalog is still being built. Try again in some moments"}

{:error, reason} ->
{:error, reason}
Expand All @@ -34,42 +30,34 @@ defmodule Trento.Integration.Checks do
end
end

defp get_catalog_content(runner_url) do
case adapter().get_catalog_content(runner_url) do
@spec get_catalog_by_provider ::
{:ok, Catalog.t()} | {:error, any}
def get_catalog_by_provider do
case get_catalog() do
{:ok, content} ->
normalize_catalog(content)
group_by_provider_by_group(content.checks)

{:error, reason} ->
{:error, reason}

_ ->
{:error, :unexpected_response}
end
end

defp handle_catalog_ready(%{"ready" => true}), do: :ok

defp handle_catalog_ready(%{"ready" => false}),
do: {:error, "The catalog is still being built."}

defp normalize_catalog(catalog_raw) do
defp group_by_provider_by_group(flat_catalog) do
normalized_catalog =
catalog_raw
|> Enum.group_by(&Map.take(&1, ["provider"]), &Map.drop(&1, ["provider"]))
|> Enum.map(fn {key, value} -> Map.put(key, "groups", group_by_groups(value)) end)
flat_catalog
|> Enum.map(&Map.from_struct/1)
|> Enum.group_by(&Map.take(&1, [:provider]), &Map.drop(&1, [:provider]))
|> Enum.map(fn {key, value} -> Map.put(key, :groups, group_by_group(value)) end)

Catalog.new(%{providers: normalized_catalog})
end

defp group_by_groups(groups) do
defp group_by_group(groups) do
groups
|> Enum.group_by(&Map.take(&1, ["group"]), &Map.drop(&1, ["group"]))
|> Enum.map(fn {key, value} -> Map.put(key, "checks", value) end)
|> Enum.group_by(&Map.take(&1, [:group]), &Map.drop(&1, [:group]))
|> Enum.map(fn {key, value} -> Map.put(key, :checks, value) end)
end

defp adapter,
do: Application.fetch_env!(:trento, __MODULE__)[:adapter]

defp runner_url,
do: Application.fetch_env!(:trento, __MODULE__)[:runner_url]
end
17 changes: 17 additions & 0 deletions lib/trento/application/integration/checks/models/flat_catalog.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
defmodule Trento.Integration.Checks.Models.FlatCatalog do
@moduledoc """
Flat checks catalog
"""

@required_fields [
:checks
]

use Trento.Type

alias Trento.Integration.Checks.Models.FlatCheck

deftype do
embeds_many :checks, FlatCheck
end
end
29 changes: 29 additions & 0 deletions lib/trento/application/integration/checks/models/flat_check.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
defmodule Trento.Integration.Checks.Models.FlatCheck do
@moduledoc """
Flat catalog check
"""

@required_fields [
:id,
:provider,
:group,
:name,
:description,
:remediation,
:implementation,
:labels
]

use Trento.Type

deftype do
field :id, :string
field :provider, Ecto.Enum, values: [:azure, :aws, :gcp, :dev, :unknown]
field :group, :string
field :name, :string
field :description, :string
field :remediation, :string
field :implementation, :string
field :labels, :string
end
end
14 changes: 13 additions & 1 deletion lib/trento_web/controllers/catalog_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,20 @@ defmodule TrentoWeb.CatalogController do
alias Trento.Integration.Checks

@spec checks_catalog(Plug.Conn.t(), map) :: Plug.Conn.t()
def checks_catalog(conn, _) do
def checks_catalog(conn, %{"flat" => ""}) do
case Checks.get_catalog() do
{:ok, catalog} ->
json(conn, catalog.checks)

{:error, reason} ->
conn
|> put_status(:bad_request)
|> json(%{error: reason})
end
end

def checks_catalog(conn, _) do
case Checks.get_catalog_by_provider() do
{:ok, catalog} ->
json(conn, catalog.providers)

Expand Down
Loading

0 comments on commit a5d179f

Please sign in to comment.