-
-
Notifications
You must be signed in to change notification settings - Fork 46
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
17 changed files
with
356 additions
and
34 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
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,59 @@ | ||
defmodule K8s.Middleware do | ||
@moduledoc "Interface for interacting with cluster middleware" | ||
|
||
alias K8s.Middleware.{Error, Request} | ||
|
||
@typedoc "Middleware type" | ||
@type type_t :: :request | :response | ||
|
||
@typedoc "List of middlewares" | ||
@type stack_t :: list(module()) | ||
|
||
@spec defaults(K8s.Middleware.type_t()) :: stack_t | ||
def defaults(:request) do | ||
[ | ||
Request.Initialize, | ||
Request.EncodeBody | ||
] | ||
end | ||
|
||
@doc "Retrieve a list of middleware registered to a cluster" | ||
@spec list(type_t, atom()) :: stack_t | ||
def list(:request, _cluster) do | ||
# TODO interact w/ registry | ||
defaults(:request) | ||
end | ||
|
||
@doc """ | ||
Applies middlewares registered to a `K8s.Cluster` to a `K8s.Middleware.Request` | ||
""" | ||
@spec run(Request.t()) :: {:ok, Request.t()} | {:error, Error.t()} | ||
def run(req) do | ||
middlewares = list(:request, req.cluster) | ||
|
||
result = | ||
Enum.reduce_while(middlewares, req, fn middleware, req -> | ||
case apply(middleware, :call, [req]) do | ||
{:ok, updated_request} -> | ||
{:cont, updated_request} | ||
|
||
{:error, error} -> | ||
{:halt, error(middleware, req, error)} | ||
end | ||
end) | ||
|
||
case result do | ||
%Request{} -> {:ok, result} | ||
%Error{} -> {:error, result} | ||
end | ||
end | ||
|
||
@spec error(module(), Request.t(), any()) :: Error.t() | ||
defp error(middleware, req, error) do | ||
%K8s.Middleware.Error{ | ||
middleware: middleware, | ||
error: error, | ||
request: req | ||
} | ||
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,17 @@ | ||
defmodule K8s.Middleware.Error do | ||
@moduledoc "Encapsulates middleware process errors" | ||
|
||
@typedoc """ | ||
Middleware processing error | ||
* `middleware` middleware module that caused the error | ||
* `request` `K8s.Middleware.Request` | ||
* `error` actual error, can be `any()` type | ||
""" | ||
@type t :: %__MODULE__{ | ||
request: K8s.Middleware.Request.t() | nil, | ||
middleware: module(), | ||
error: any() | ||
} | ||
defstruct [:request, :middleware, :error] | ||
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,41 @@ | ||
defmodule K8s.Middleware.Registry do | ||
@moduledoc "Cluster middleware registry" | ||
use Agent | ||
|
||
@spec start_link(Keyword.t()) :: Agent.on_start() | ||
def start_link(_opts) do | ||
Agent.start_link(fn -> %{} end, name: __MODULE__) | ||
end | ||
|
||
@doc "Adds a middleware to the end of the middleware stack" | ||
@spec add(atom, K8s.Middleware.type_t(), module()) :: :ok | ||
def add(cluster, type, middleware) do | ||
Agent.update(__MODULE__, fn registry -> | ||
cluster_middlewares = Map.get(registry, cluster, %{}) | ||
middleware_list = Map.get(cluster_middlewares, type, []) | ||
|
||
updated_middleware_list = middleware_list ++ [middleware] | ||
updated_cluster_middlewares = Map.put(cluster_middlewares, type, updated_middleware_list) | ||
|
||
put_in(registry, [cluster], updated_cluster_middlewares) | ||
end) | ||
end | ||
|
||
@doc "Sets/replaces the middleware stack" | ||
@spec set(atom, K8s.Middleware.type_t(), list(module())) :: :ok | ||
def set(cluster, type, middlewares) do | ||
Agent.update(__MODULE__, fn registry -> | ||
cluster_middlewares = Map.get(registry, cluster, %{}) | ||
updated_cluster_middlewares = Map.put(cluster_middlewares, type, middlewares) | ||
|
||
put_in(registry, [cluster], updated_cluster_middlewares) | ||
end) | ||
end | ||
|
||
@doc "Returns middleware stack for a cluster and (request or response)" | ||
@spec list(atom, K8s.Middleware.type_t()) :: K8s.Middleware.stack_t() | ||
def list(cluster, type) do | ||
registry = Agent.get(__MODULE__, & &1[cluster]) || %{} | ||
Map.get(registry, type, []) | ||
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,18 @@ | ||
defmodule K8s.Middleware.Request do | ||
@moduledoc "HTTP Request middleware" | ||
|
||
@typedoc "Middleware Request type" | ||
@type t :: %__MODULE__{ | ||
cluster: atom(), | ||
method: atom(), | ||
url: String.t(), | ||
body: String.t() | map() | list(map()) | nil, | ||
headers: Keyword.t() | nil, | ||
opts: Keyword.t() | nil | ||
} | ||
|
||
defstruct cluster: nil, method: nil, url: nil, body: nil, headers: [], opts: [] | ||
|
||
@doc "Request middleware callback" | ||
@callback call(t()) :: {:ok, t()} | {:error, any()} | ||
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,18 @@ | ||
# defmodule K8s.Middleware.Request.BaseURL do | ||
# @behaviour K8s.Middleware.Request | ||
|
||
# @doc """ | ||
|
||
# ## Examples | ||
# iex> conn = K8s.Conn.from_file("./test/support/kube-config.yaml") | ||
# ...> K8s.Cluster.Registry.add(:test_cluster, conn) | ||
# ...> request = %K8s.Middleware.Request{cluster: :test_cluster} | ||
# ...> K8s.Middleware.Request.BaseURL.call(request) | ||
# {:ok, %K8s.Middleware.Request{cluster: :test_cluster, url: "https://localhost:6443"}} | ||
# """ | ||
# @impl true | ||
# def call(%K8s.Middleware.Request{} = req) do | ||
# {:ok, url} <- Cluster.url_for(operation, cluster_name) | ||
# {:ok, req} | ||
# 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,25 @@ | ||
defmodule K8s.Middleware.Request.EncodeBody do | ||
@moduledoc """ | ||
Naive JSON body encoder. | ||
Encodes JSON payloads when given an modifiying HTTP verb, otherwise returns an empty string. | ||
""" | ||
@behaviour K8s.Middleware.Request | ||
alias K8s.Middleware.Request | ||
|
||
@impl true | ||
def call(%Request{method: method, body: body} = req) do | ||
case encode(body, method) do | ||
{:ok, encoded_body} -> | ||
req = %Request{req | body: encoded_body} | ||
{:ok, req} | ||
|
||
error -> | ||
error | ||
end | ||
end | ||
|
||
@spec encode(any(), atom()) :: {:ok, binary} | {:error, any} | ||
defp encode(body, http_method) when http_method in [:put, :patch, :post], do: Jason.encode(body) | ||
defp encode(_, _), do: {:ok, ""} | ||
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,19 @@ | ||
defmodule K8s.Middleware.Request.Initialize do | ||
@moduledoc """ | ||
Initializes a request with connection details (header and HTTPoison opts) from `K8s.Conn.RequestOptions` | ||
""" | ||
@behaviour K8s.Middleware.Request | ||
alias K8s.Middleware.Request | ||
|
||
@impl true | ||
def call(%Request{cluster: cluster, method: method, headers: headers, opts: opts} = req) do | ||
with {:ok, conn} <- K8s.Cluster.conn(cluster), | ||
{:ok, request_options} <- K8s.Conn.RequestOptions.generate(conn) do | ||
request_option_headers = K8s.http_provider().headers(method, request_options) | ||
updated_headers = Keyword.merge(headers, request_option_headers) | ||
updated_opts = Keyword.merge([ssl: request_options.ssl_options], opts) | ||
updated_request = %Request{req | headers: updated_headers, opts: updated_opts} | ||
{:ok, updated_request} | ||
end | ||
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
Oops, something went wrong.