From 27424e56991b8ac0ed0e7b79a8e17f7f4f1fcfd8 Mon Sep 17 00:00:00 2001 From: Jean-Louis Huynen Date: Fri, 21 Jun 2024 15:23:37 +0200 Subject: [PATCH] chg: [cruds] decoupling redisinstance - moving to connections --- lib/cocktailparty/catalog.ex | 2 +- lib/cocktailparty/dynamic_supervisor_boot.ex | 8 +- lib/cocktailparty/input.ex | 34 +++++++- lib/cocktailparty/input/connection.ex | 4 +- .../input/connection_behaviour.ex | 4 + lib/cocktailparty/input/connection_type.ex | 9 +++ lib/cocktailparty/input/redis.ex | 16 ++++ lib/cocktailparty/input/stomp.ex | 16 ++++ lib/cocktailparty/sink_catalog.ex | 2 +- .../admin/connection_controller.ex | 79 +++++++++++++++---- .../controllers/admin/connection_html.ex | 1 + .../connection_html/connection_form.html.heex | 9 ++- .../admin/connection_html/edit.html.heex | 2 +- .../admin/connection_html/new.html.heex | 2 +- .../admin/connection_html/show.html.heex | 27 +++++++ .../controllers/admin/sink_controller.ex | 8 +- .../controllers/admin/sink_html.ex | 2 +- .../admin/sink_html/edit.html.heex | 2 +- .../admin/sink_html/index.html.heex | 6 +- .../controllers/admin/sink_html/new.html.heex | 2 +- .../admin/sink_html/show.html.heex | 3 +- .../admin/sink_html/sink_form.html.heex | 9 +-- .../controllers/admin/source_controller.ex | 18 +++-- .../controllers/admin/source_html.ex | 2 +- .../controllers/sink_html.ex | 1 + .../controllers/sink_html/edit.html.heex | 2 +- .../controllers/sink_html/new.html.heex | 2 +- .../controllers/sink_html/sink_form.html.heex | 1 - .../controllers/source_html.ex | 2 +- .../controllers/source_html/edit.html.heex | 2 +- .../controllers/source_html/index.html.heex | 8 +- .../controllers/source_html/new.html.heex | 2 +- .../controllers/source_html/show.html.heex | 4 +- .../source_html/source_form.html.heex | 12 +-- mix.exs | 6 +- mix.lock | 3 + .../connection_controller_test.exs | 2 - 37 files changed, 233 insertions(+), 81 deletions(-) create mode 100644 lib/cocktailparty/input/connection_behaviour.ex create mode 100644 lib/cocktailparty/input/connection_type.ex create mode 100644 lib/cocktailparty/input/redis.ex create mode 100644 lib/cocktailparty/input/stomp.ex diff --git a/lib/cocktailparty/catalog.ex b/lib/cocktailparty/catalog.ex index 601b5a1..f5d781a 100644 --- a/lib/cocktailparty/catalog.ex +++ b/lib/cocktailparty/catalog.ex @@ -141,7 +141,7 @@ defmodule Cocktailparty.Catalog do """ def create_source(attrs \\ %{}) do - Cocktailparty.Input.get_connection!(attrs["connection_id"]) + Cocktailparty.Input.get_connection_map!(attrs["connection_id"]) |> Ecto.build_assoc(:sources) |> change_source(attrs) |> Repo.insert() diff --git a/lib/cocktailparty/dynamic_supervisor_boot.ex b/lib/cocktailparty/dynamic_supervisor_boot.ex index fd2da30..a7b65fc 100644 --- a/lib/cocktailparty/dynamic_supervisor_boot.ex +++ b/lib/cocktailparty/dynamic_supervisor_boot.ex @@ -1,9 +1,9 @@ defmodule Cocktailparty.DynamicSupervisorBoot do - alias Cocktailparty.Input.Connection + # alias Cocktailparty.Input.Connection use Supervisor require Logger - import Cocktailparty.Input + # import Cocktailparty.Input def start_link(init_arg) do Supervisor.start_link(__MODULE__, init_arg, name: __MODULE__) @@ -20,8 +20,8 @@ defmodule Cocktailparty.DynamicSupervisorBoot do Logger.info("Connection Dynamic Supervisor Task started") # When starting we check what inputs are available # for each instance, we start a redix connection along with a broker gen_server - list_connections() - |> Enum.each(fn x -> Connection.start(x) end) + # list_connections() + # |> Enum.each(fn x -> Connection.start(x) end) end} ] diff --git a/lib/cocktailparty/input.ex b/lib/cocktailparty/input.ex index b90076d..9bb05a9 100644 --- a/lib/cocktailparty/input.ex +++ b/lib/cocktailparty/input.ex @@ -66,7 +66,7 @@ defmodule Cocktailparty.Input do end @doc """ - Gets a single connection. + Gets a single connection -- with config as a text field Raises `Ecto.NoResultsError` if the connection does not exist. @@ -79,9 +79,37 @@ defmodule Cocktailparty.Input do ** (Ecto.NoResultsError) """ - def get_connection!(id) do + def get_connection_text!(id) do instance = Repo.get!(Connection, id) - Map.put(instance, :connected, connected?(instance)) + + instance + |> Map.put(:connected, connected?(instance)) + |> Map.put(:config, config_to_yaml(instance.config)) + end + + @doc """ + Gets a single connection -- with config as a map + + Raises `Ecto.NoResultsError` if the connection does not exist. + + ## Examples + + iex> get_connection!(123) + %Connection{} + + iex> get_connection!(456) + ** (Ecto.NoResultsError) + + """ + def get_connection_map!(id) do + instance = Repo.get!(Connection, id) + + instance + |> Map.put(:connected, connected?(instance)) + end + + def config_to_yaml(config) do + Ymlr.document!(config) end @doc """ diff --git a/lib/cocktailparty/input/connection.ex b/lib/cocktailparty/input/connection.ex index 54f4e12..47b6d68 100644 --- a/lib/cocktailparty/input/connection.ex +++ b/lib/cocktailparty/input/connection.ex @@ -39,8 +39,8 @@ defmodule Cocktailparty.Input.Connection do spec_redix = {Redix, - host: rc.config.hostname, - port: rc.config.port, + host: Map.get(rc.config, "hostname"), + port: Map.get(rc.config, "port"), name: {:global, "redix_" <> Integer.to_string(rc.id)}} # TODO remove the nested name (impacts catalog.ex) diff --git a/lib/cocktailparty/input/connection_behaviour.ex b/lib/cocktailparty/input/connection_behaviour.ex new file mode 100644 index 0000000..88cdf58 --- /dev/null +++ b/lib/cocktailparty/input/connection_behaviour.ex @@ -0,0 +1,4 @@ +defmodule Cocktailparty.Input.ConnectionBehavior do + @callback start_link(config :: map) :: {:ok, pid} | {:error, term} + @callback validate_config(config :: map) :: :ok | {:error, String.t()} +end diff --git a/lib/cocktailparty/input/connection_type.ex b/lib/cocktailparty/input/connection_type.ex new file mode 100644 index 0000000..50b8711 --- /dev/null +++ b/lib/cocktailparty/input/connection_type.ex @@ -0,0 +1,9 @@ +defmodule Cocktailparty.Input.ConnectionTypes do + @connection_types [ + {"Redis", "redis"}, + {"STOMP", "stomp"} + # Add other connection types here + ] + + def all, do: @connection_types +end diff --git a/lib/cocktailparty/input/redis.ex b/lib/cocktailparty/input/redis.ex new file mode 100644 index 0000000..c7ceaea --- /dev/null +++ b/lib/cocktailparty/input/redis.ex @@ -0,0 +1,16 @@ +defmodule Cocktailparty.Input.Redis do + @behaviour Cocktailparty.Input.ConnectionBehavior + + def start_link(_config) do + # Implement Redis connection logic + end + + def validate_config(config) do + required_keys = ["hostname", "port"] + + case Enum.all?(required_keys, &Map.has_key?(config, &1)) do + true -> :ok + false -> {:error, "Missing required keys in config"} + end + end +end diff --git a/lib/cocktailparty/input/stomp.ex b/lib/cocktailparty/input/stomp.ex new file mode 100644 index 0000000..866c148 --- /dev/null +++ b/lib/cocktailparty/input/stomp.ex @@ -0,0 +1,16 @@ +defmodule Cocktailparty.Input.Stomp do + @behaviour Cocktailparty.Input.ConnectionBehavior + + def start_link(_config) do + # Implement rabbitmq stomp connection logic + end + + def validate_config(config) do + required_keys = ["hostname", "port", "username", "password"] + + case Enum.all?(required_keys, &Map.has_key?(config, &1)) do + true -> :ok + false -> {:error, "Missing required keys in config"} + end + end +end diff --git a/lib/cocktailparty/sink_catalog.ex b/lib/cocktailparty/sink_catalog.ex index a8736b2..a0a6746 100644 --- a/lib/cocktailparty/sink_catalog.ex +++ b/lib/cocktailparty/sink_catalog.ex @@ -154,7 +154,7 @@ defmodule Cocktailparty.SinkCatalog do """ def create_sink(attrs \\ %{}) do - Cocktailparty.Input.get_connection!(attrs["connection_id"]) + Cocktailparty.Input.get_connection_map!(attrs["connection_id"]) |> Ecto.build_assoc(:sinks) |> change_sink(attrs) |> Repo.insert() diff --git a/lib/cocktailparty_web/controllers/admin/connection_controller.ex b/lib/cocktailparty_web/controllers/admin/connection_controller.ex index 30a25ad..3563d89 100644 --- a/lib/cocktailparty_web/controllers/admin/connection_controller.ex +++ b/lib/cocktailparty_web/controllers/admin/connection_controller.ex @@ -3,6 +3,7 @@ defmodule CocktailpartyWeb.Admin.ConnectionController do alias Cocktailparty.Input alias Cocktailparty.Input.Connection + alias Cocktailparty.Input.ConnectionTypes def index(conn, _params) do connections = Input.list_connections() @@ -11,51 +12,97 @@ defmodule CocktailpartyWeb.Admin.ConnectionController do def new(conn, _params) do changeset = Input.change_connection(%Connection{}) - render(conn, :new, changeset: changeset) + connection_types = ConnectionTypes.all() + render(conn, :new, changeset: changeset, connection_types: connection_types) end def create(conn, %{"connection" => connection_params}) do - case Input.create_connection(connection_params) do + {:ok, config_str} = Map.fetch(connection_params, "config") + config = YamlElixir.read_from_string!(config_str) + + case Input.create_connection(Map.put(connection_params, "config", config)) do {:ok, connection} -> # TODO: handle errors - Cocktailparty.Input.Connection.start(connection) + # Cocktailparty.Input.Connection.start(connection) conn |> put_flash(:info, "Connection created successfully.") |> redirect(to: ~p"/admin/connections/#{connection}") {:error, %Ecto.Changeset{} = changeset} -> - render(conn, :new, changeset: changeset) + txt_config = Ymlr.document!(changeset.changes.config) + new_changes = Map.put(changeset.changes, :config, txt_config) + new_changeset = Map.put(changeset, :changes, new_changes) + + connection_types = ConnectionTypes.all() + + render(conn, :new, changeset: new_changeset, connection_types: connection_types) end end def show(conn, %{"id" => id}) do - connection = Input.get_connection!(id) + connection = Input.get_connection_map!(id) render(conn, :show, connection: connection) end def edit(conn, %{"id" => id}) do - connection = Input.get_connection!(id) + connection = Input.get_connection_text!(id) changeset = Input.change_connection(connection) - render(conn, :edit, connection: connection, changeset: changeset) + connection_types = ConnectionTypes.all() + + render(conn, :edit, + connection: connection, + changeset: changeset, + connection_types: connection_types + ) end def update(conn, %{"id" => id, "connection" => connection_params}) do - connection = Input.get_connection!(id) + connection = Input.get_connection_text!(id) - case Input.update_connection(connection, connection_params) do - {:ok, connection} -> - conn - |> put_flash(:info, "Connection updated successfully.") - |> redirect(to: ~p"/admin/connections/#{connection}") + # TODO wip + yaml_config = connection_params["config"] - {:error, %Ecto.Changeset{} = changeset} -> - render(conn, :edit, connection: connection, changeset: changeset) + case YamlElixir.read_from_string(yaml_config) do + {:ok, config_map} -> + connection_params = Map.put(connection_params, "config", config_map) + # dbg(config_map) + # dbg(connection_params) + + # case Catalog.update_connection(connection, connection_params) do + # {:ok, _connection} -> + # conn + # |> put_flash(:info, "Connection updated successfully.") + # |> redirect(to: Routes.connection_path(conn, :index)) + # {:error, changeset} -> + # render(conn, "edit.html", connection: connection, changeset: changeset) + # end + + # {:error, reason} -> + # conn + # |> put_flash(:error, "Failed to parse YAML: #{reason}") + # |> render("edit.html", connection: connection, changeset: Connection.changeset(connection, connection_params)) + + case Input.update_connection(connection, connection_params) do + {:ok, connection} -> + conn + |> put_flash(:info, "Connection updated successfully.") + |> redirect(to: ~p"/admin/connections/#{connection}") + + {:error, %Ecto.Changeset{} = changeset} -> + connection_types = ConnectionTypes.all() + + render(conn, :edit, + connection: connection, + changeset: changeset, + connection_types: connection_types + ) + end end end def delete(conn, %{"id" => id}) do - connection = Input.get_connection!(id) + connection = Input.get_connection_map!(id) {:ok, _connection} = Input.delete_connection(connection) Input.Connection.terminate(connection) diff --git a/lib/cocktailparty_web/controllers/admin/connection_html.ex b/lib/cocktailparty_web/controllers/admin/connection_html.ex index 2a0164d..24c3a09 100644 --- a/lib/cocktailparty_web/controllers/admin/connection_html.ex +++ b/lib/cocktailparty_web/controllers/admin/connection_html.ex @@ -7,6 +7,7 @@ defmodule CocktailpartyWeb.Admin.ConnectionHTML do Renders a connection form. """ attr :changeset, Ecto.Changeset, required: true + attr :connection_types, :list, required: true attr :action, :string, required: true def connection_form(assigns) diff --git a/lib/cocktailparty_web/controllers/admin/connection_html/connection_form.html.heex b/lib/cocktailparty_web/controllers/admin/connection_html/connection_form.html.heex index 7dcddd1..3d3cf00 100644 --- a/lib/cocktailparty_web/controllers/admin/connection_html/connection_form.html.heex +++ b/lib/cocktailparty_web/controllers/admin/connection_html/connection_form.html.heex @@ -3,10 +3,15 @@ Oops, something went wrong! Please check the errors below. <.input field={f[:name]} type="text" label="Name" /> - <.input field={f[:port]} type="text" label="port" /> + <.input + field={f[:type]} + type="select" + label="Type" + options={Enum.map(@connection_types, fn {label, string} -> {label, string} end)} + /> <.input field={f[:enabled]} type="checkbox" label="Enabled" /> <.input field={f[:sink]} type="checkbox" label="Sink" /> - <.input field={f[:config]} type="text" label="config" /> + <.input field={f[:config]} type="textarea" label="Config" /> <:actions> <.button>Save connection diff --git a/lib/cocktailparty_web/controllers/admin/connection_html/edit.html.heex b/lib/cocktailparty_web/controllers/admin/connection_html/edit.html.heex index a05e941..a13114c 100644 --- a/lib/cocktailparty_web/controllers/admin/connection_html/edit.html.heex +++ b/lib/cocktailparty_web/controllers/admin/connection_html/edit.html.heex @@ -3,6 +3,6 @@ <:subtitle>Use this form to manage connection records in your database. -<.connection_form changeset={@changeset} action={~p"/admin/connections/#{@connection}"} /> +<.connection_form changeset={@changeset} action={~p"/admin/connections/#{@connection}"} connection_types={@connection_types} /> <.back navigate={~p"/admin/connections"}>Back to connections diff --git a/lib/cocktailparty_web/controllers/admin/connection_html/new.html.heex b/lib/cocktailparty_web/controllers/admin/connection_html/new.html.heex index 6371935..c4a1e36 100644 --- a/lib/cocktailparty_web/controllers/admin/connection_html/new.html.heex +++ b/lib/cocktailparty_web/controllers/admin/connection_html/new.html.heex @@ -3,6 +3,6 @@ <:subtitle>Use this form to manage connection records in your database. -<.connection_form changeset={@changeset} action={~p"/admin/connections"} /> +<.connection_form changeset={@changeset} action={~p"/admin/connections"} connection_types={@connection_types} /> <.back navigate={~p"/admin/connections"}>Back to connections diff --git a/lib/cocktailparty_web/controllers/admin/connection_html/show.html.heex b/lib/cocktailparty_web/controllers/admin/connection_html/show.html.heex index c578a92..545823a 100644 --- a/lib/cocktailparty_web/controllers/admin/connection_html/show.html.heex +++ b/lib/cocktailparty_web/controllers/admin/connection_html/show.html.heex @@ -28,6 +28,33 @@ offline + <%!-- <:item title="Config"><%= @connection.config %> --%> + + <:item title="Config"> + + + + + + + + + <%= for {key, value} <- @connection.config do %> + + + + + <% end %> +
keyvalue
+
+ <%= key %> +
+
+
+ <%= value %> +
+
+ <.back navigate={~p"/admin/connections"}>Back to connections diff --git a/lib/cocktailparty_web/controllers/admin/sink_controller.ex b/lib/cocktailparty_web/controllers/admin/sink_controller.ex index 280b1fe..3149cc5 100644 --- a/lib/cocktailparty_web/controllers/admin/sink_controller.ex +++ b/lib/cocktailparty_web/controllers/admin/sink_controller.ex @@ -24,7 +24,7 @@ defmodule CocktailpartyWeb.Admin.SinkController do |> redirect(to: ~p"/admin/connections") _ -> - render(conn, :new, changeset: changeset, redis_instances: instances, users: users) + render(conn, :new, changeset: changeset, connections: instances, users: users) end end @@ -41,7 +41,7 @@ defmodule CocktailpartyWeb.Admin.SinkController do # get list of users users = SinkCatalog.list_authorized_users() - render(conn, :new, changeset: changeset, redis_instances: instances, users: users) + render(conn, :new, changeset: changeset, connections: instances, users: users) end end @@ -70,7 +70,7 @@ defmodule CocktailpartyWeb.Admin.SinkController do render(conn, :edit, sink: sink, changeset: changeset, - redis_instances: instances, + connections: instances, users: users ) end @@ -94,7 +94,7 @@ defmodule CocktailpartyWeb.Admin.SinkController do render(conn, :edit, sink: sink, changeset: changeset, - redis_instances: instances, + connections: instances, users: users ) end diff --git a/lib/cocktailparty_web/controllers/admin/sink_html.ex b/lib/cocktailparty_web/controllers/admin/sink_html.ex index 2629c3b..b21249f 100644 --- a/lib/cocktailparty_web/controllers/admin/sink_html.ex +++ b/lib/cocktailparty_web/controllers/admin/sink_html.ex @@ -8,7 +8,7 @@ defmodule CocktailpartyWeb.Admin.SinkHTML do """ attr :changeset, Ecto.Changeset, required: true attr :action, :string, required: true - attr :redis_instances, :list, required: true + attr :connections, :list, required: true attr :users, :list, required: true def sink_form(assigns) diff --git a/lib/cocktailparty_web/controllers/admin/sink_html/edit.html.heex b/lib/cocktailparty_web/controllers/admin/sink_html/edit.html.heex index 172844a..f8b7655 100644 --- a/lib/cocktailparty_web/controllers/admin/sink_html/edit.html.heex +++ b/lib/cocktailparty_web/controllers/admin/sink_html/edit.html.heex @@ -6,7 +6,7 @@ <.sink_form changeset={@changeset} action={~p"/admin/sinks/#{@sink}"} - redis_instances={@redis_instances} + connections={@connections} users={@users} /> diff --git a/lib/cocktailparty_web/controllers/admin/sink_html/index.html.heex b/lib/cocktailparty_web/controllers/admin/sink_html/index.html.heex index 4d2051c..b4e5aa6 100644 --- a/lib/cocktailparty_web/controllers/admin/sink_html/index.html.heex +++ b/lib/cocktailparty_web/controllers/admin/sink_html/index.html.heex @@ -9,12 +9,10 @@ <.table id="sinks" rows={@sinks} row_click={&JS.navigate(~p"/admin/sinks/#{&1}")}> <:col :let={sink} label="Name"><%= sink.name %> - <:col :let={sink} label="Description"><%= sink.description %> <:col :let={sink} label="Type"><%= sink.type %> - <:col :let={sink} label="Channel"><%= sink.channel %> <:col :let={sink} label="User"><%= sink.user.email %> - <:col :let={sink} label="Redis instance"> - <%= sink.redis_instance.name %> + <:col :let={sink} label="Connection"> + <%= sink.connection.name %> <:action :let={sink}>
diff --git a/lib/cocktailparty_web/controllers/admin/sink_html/new.html.heex b/lib/cocktailparty_web/controllers/admin/sink_html/new.html.heex index 972bdc2..e7ac0d8 100644 --- a/lib/cocktailparty_web/controllers/admin/sink_html/new.html.heex +++ b/lib/cocktailparty_web/controllers/admin/sink_html/new.html.heex @@ -6,7 +6,7 @@ <.sink_form changeset={@changeset} action={~p"/admin/sinks"} - redis_instances={@redis_instances} + connections={@connections} users={@users} /> diff --git a/lib/cocktailparty_web/controllers/admin/sink_html/show.html.heex b/lib/cocktailparty_web/controllers/admin/sink_html/show.html.heex index 1e56d02..a39094b 100644 --- a/lib/cocktailparty_web/controllers/admin/sink_html/show.html.heex +++ b/lib/cocktailparty_web/controllers/admin/sink_html/show.html.heex @@ -13,8 +13,7 @@ <:item title="Id"><%= @sink.id %> <:item title="Description"><%= @sink.description %> <:item title="Type"><%= @sink.type %> - <:item title="Channel"><%= @sink.channel %> - <:item title="Redis instance"><%= @sink.redis_instance.name %> + <:item title="Connection"><%= @sink.connection.name %> <:item title="User"><%= @sink.user.email %> diff --git a/lib/cocktailparty_web/controllers/admin/sink_html/sink_form.html.heex b/lib/cocktailparty_web/controllers/admin/sink_html/sink_form.html.heex index 03509b9..2ad5fb4 100644 --- a/lib/cocktailparty_web/controllers/admin/sink_html/sink_form.html.heex +++ b/lib/cocktailparty_web/controllers/admin/sink_html/sink_form.html.heex @@ -5,14 +5,11 @@ <.input field={f[:name]} type="text" label="Name" /> <.input field={f[:description]} type="text" label="Description" /> <.input field={f[:type]} type="text" label="Type" /> - <.input field={f[:channel]} type="text" label="Channel" /> <.input - field={f[:redis_instance_id]} + field={f[:connection_id]} type="select" - label="Redis instance" - options={ - Enum.map(@redis_instances, fn redis_instance -> {redis_instance.name, redis_instance.id} end) - } + label="Connection" + options={Enum.map(@connections, fn connection -> {connection.name, connection.id} end)} /> <.input field={f[:user_id]} diff --git a/lib/cocktailparty_web/controllers/admin/source_controller.ex b/lib/cocktailparty_web/controllers/admin/source_controller.ex index c9a910e..f0d0f22 100644 --- a/lib/cocktailparty_web/controllers/admin/source_controller.ex +++ b/lib/cocktailparty_web/controllers/admin/source_controller.ex @@ -21,25 +21,31 @@ defmodule CocktailpartyWeb.Admin.SourceController do case instances do [] -> conn - |> put_flash(:error, "A redis instance is required to create a source.") + |> put_flash(:error, "A connection is required to create a source.") |> redirect(to: ~p"/admin/connections") _ -> - render(conn, :new, changeset: changeset, redis_instances: instances) + render(conn, :new, changeset: changeset, connections: instances) end end def create(conn, %{"source" => source_params}) do - case Catalog.create_source(source_params) do + {:ok, config_str} = Map.fetch(source_params, "config") + config = YamlElixir.read_from_string!(config_str) + case Catalog.create_source(Map.put(source_params, "config", config)) do {:ok, source} -> conn |> put_flash(:info, "Source created successfully.") |> redirect(to: ~p"/admin/sources/#{source}") {:error, %Ecto.Changeset{} = changeset} -> + txt_config = Ymlr.document!(changeset.changes.config) + new_changes = Map.put(changeset.changes, :config, txt_config) + new_changeset = Map.put(changeset, :changes, new_changes) + # get list of redis instances instances = Input.list_connections() - render(conn, :new, changeset: changeset, redis_instances: instances) + render(conn, :new, changeset: new_changeset, connections: instances) end end @@ -97,7 +103,7 @@ defmodule CocktailpartyWeb.Admin.SourceController do |> redirect(to: ~p"/admin/connections") _ -> - render(conn, :edit, source: source, changeset: changeset, redis_instances: instances) + render(conn, :edit, source: source, changeset: changeset, connections: instances) end end @@ -113,7 +119,7 @@ defmodule CocktailpartyWeb.Admin.SourceController do |> redirect(to: ~p"/admin/sources/#{source}") {:error, %Ecto.Changeset{} = changeset} -> - render(conn, :edit, source: source, changeset: changeset, redis_instances: instances) + render(conn, :edit, source: source, changeset: changeset, connections: instances) end end diff --git a/lib/cocktailparty_web/controllers/admin/source_html.ex b/lib/cocktailparty_web/controllers/admin/source_html.ex index 98a013a..d2413a6 100644 --- a/lib/cocktailparty_web/controllers/admin/source_html.ex +++ b/lib/cocktailparty_web/controllers/admin/source_html.ex @@ -8,7 +8,7 @@ defmodule CocktailpartyWeb.Admin.SourceHTML do """ attr :changeset, Ecto.Changeset, required: true attr :action, :string, required: true - attr :redis_instances, :list, required: true + attr :connections, :list, required: true def source_form(assigns) end diff --git a/lib/cocktailparty_web/controllers/sink_html.ex b/lib/cocktailparty_web/controllers/sink_html.ex index 57200b6..0f49d54 100644 --- a/lib/cocktailparty_web/controllers/sink_html.ex +++ b/lib/cocktailparty_web/controllers/sink_html.ex @@ -8,6 +8,7 @@ defmodule CocktailpartyWeb.SinkHTML do """ attr :changeset, Ecto.Changeset, required: true attr :action, :string, required: true + attr :connections, :list, required: true def sink_form(assigns) end diff --git a/lib/cocktailparty_web/controllers/sink_html/edit.html.heex b/lib/cocktailparty_web/controllers/sink_html/edit.html.heex index 895df90..1dc9fe4 100644 --- a/lib/cocktailparty_web/controllers/sink_html/edit.html.heex +++ b/lib/cocktailparty_web/controllers/sink_html/edit.html.heex @@ -3,6 +3,6 @@ <:subtitle>Use this form to manage sink records in your database. -<.sink_form changeset={@changeset} action={~p"/sinks/#{@sink}"} /> +<.sink_form changeset={@changeset} action={~p"/sinks/#{@sink}"} connections={@connections} /> <.back navigate={~p"/sinks"}>Back to sinks diff --git a/lib/cocktailparty_web/controllers/sink_html/new.html.heex b/lib/cocktailparty_web/controllers/sink_html/new.html.heex index 8fdaf7c..8b52120 100644 --- a/lib/cocktailparty_web/controllers/sink_html/new.html.heex +++ b/lib/cocktailparty_web/controllers/sink_html/new.html.heex @@ -3,6 +3,6 @@ <:subtitle>Use this form to manage sink records in your database. -<.sink_form changeset={@changeset} action={~p"/sinks"} /> +<.sink_form changeset={@changeset} action={~p"/sinks"} connections={@connections} /> <.back navigate={~p"/sinks"}>Back to sinks diff --git a/lib/cocktailparty_web/controllers/sink_html/sink_form.html.heex b/lib/cocktailparty_web/controllers/sink_html/sink_form.html.heex index 3a2b4db..a8141d9 100644 --- a/lib/cocktailparty_web/controllers/sink_html/sink_form.html.heex +++ b/lib/cocktailparty_web/controllers/sink_html/sink_form.html.heex @@ -5,7 +5,6 @@ <.input field={f[:name]} type="text" label="Name" /> <.input field={f[:description]} type="text" label="Description" /> <.input field={f[:type]} type="text" label="Type" /> - <.input field={f[:channel]} type="text" label="Channel" /> <:actions> <.button>Save Sink diff --git a/lib/cocktailparty_web/controllers/source_html.ex b/lib/cocktailparty_web/controllers/source_html.ex index 3836fb1..8bb7868 100644 --- a/lib/cocktailparty_web/controllers/source_html.ex +++ b/lib/cocktailparty_web/controllers/source_html.ex @@ -8,7 +8,7 @@ defmodule CocktailpartyWeb.SourceHTML do """ attr :changeset, Ecto.Changeset, required: true attr :action, :string, required: true - attr :redis_instances, :list, required: true + attr :connections, :list, required: true def source_form(assigns) end diff --git a/lib/cocktailparty_web/controllers/source_html/edit.html.heex b/lib/cocktailparty_web/controllers/source_html/edit.html.heex index c050daa..36e6b70 100644 --- a/lib/cocktailparty_web/controllers/source_html/edit.html.heex +++ b/lib/cocktailparty_web/controllers/source_html/edit.html.heex @@ -6,7 +6,7 @@ <.source_form changeset={@changeset} action={~p"/admin/sources/#{@source}"} - redis_instances={@redis_instances} + connections={@connections} /> <.back navigate={~p"/admin/sources"}>Back to sources diff --git a/lib/cocktailparty_web/controllers/source_html/index.html.heex b/lib/cocktailparty_web/controllers/source_html/index.html.heex index eb0d797..1df7901 100644 --- a/lib/cocktailparty_web/controllers/source_html/index.html.heex +++ b/lib/cocktailparty_web/controllers/source_html/index.html.heex @@ -14,11 +14,9 @@ row_click={&JS.navigate(~p"/admin/sources/#{&1}")} > <:col :let={source} label="Name"><%= source.name %> - <:col :let={source} label="Description"><%= source.description %> <:col :let={source} label="Type"><%= source.type %> - <:col :let={source} label="Channel"><%= source.channel %> - <:col :let={source} :if={@is_admin} label="Redis instance"> - <%= source.redis_instance.name %> + <:col :let={source} :if={@is_admin} label="Connection"> + <%= source.connection.name %> <:col :let={source} label="Public"> @@ -39,9 +37,7 @@ <.table :if={!@is_admin} id="sources" rows={@sources} row_click={&JS.navigate(~p"/sources/#{&1}")}> <:col :let={source} label="Name"><%= source.name %> - <:col :let={source} label="Description"><%= source.description %> <:col :let={source} label="Type"><%= source.type %> - <:col :let={source} label="Channel"><%= source.channel %> <:col :let={source} label="Public"><%= if source.public, do: "🗹", else: "☐" %> <%!-- TODO REMOVE --%> <:col :let={source} label="Subscribed"> diff --git a/lib/cocktailparty_web/controllers/source_html/new.html.heex b/lib/cocktailparty_web/controllers/source_html/new.html.heex index 7d8115c..a57529a 100644 --- a/lib/cocktailparty_web/controllers/source_html/new.html.heex +++ b/lib/cocktailparty_web/controllers/source_html/new.html.heex @@ -6,7 +6,7 @@ <.source_form changeset={@changeset} action={~p"/admin/sources"} - redis_instances={@redis_instances} + connections={@connections} /> <.back navigate={~p"/admin/sources"}>Back to sources diff --git a/lib/cocktailparty_web/controllers/source_html/show.html.heex b/lib/cocktailparty_web/controllers/source_html/show.html.heex index 55e3123..9549b9b 100644 --- a/lib/cocktailparty_web/controllers/source_html/show.html.heex +++ b/lib/cocktailparty_web/controllers/source_html/show.html.heex @@ -56,10 +56,8 @@ <.list> <:item title="Name"><%= @source.name %> <:item title="Id"><%= @source.id %> - <:item title="Description"><%= @source.description %> <:item title="Type"><%= @source.type %> - <:item title="Channel"><%= @source.channel %> - <:item :if={@is_admin} title="Redis instance"><%= @source.redis_instance.name %> + <:item :if={@is_admin} title="Connection"><%= @source.connection.name %> <:item title="Public"> <.icon :if={@source.public} name="hero-check" /> diff --git a/lib/cocktailparty_web/controllers/source_html/source_form.html.heex b/lib/cocktailparty_web/controllers/source_html/source_form.html.heex index 9c41e1e..97b2d71 100644 --- a/lib/cocktailparty_web/controllers/source_html/source_form.html.heex +++ b/lib/cocktailparty_web/controllers/source_html/source_form.html.heex @@ -4,16 +4,16 @@ <.input field={f[:name]} type="text" label="Name" /> <.input field={f[:description]} type="text" label="Description" /> + <%!-- TODO types should be tied to the connection --%> <.input field={f[:type]} type="text" label="Type" /> - <.input field={f[:channel]} type="text" label="Channel" /> <.input - field={f[:redis_instance_id]} + field={f[:connection_id]} type="select" - label="Redis instance" - options={ - Enum.map(@redis_instances, fn redis_instance -> {redis_instance.name, redis_instance.id} end) - } + label="Connection" + options={Enum.map(@connections, fn connection -> {connection.name, connection.id} end)} /> + <.input field={f[:config]} type="textarea" label="Config" /> + <.input type="checkbox" field={f[:public]} label="Public" /> <:actions> <.button>Save Source diff --git a/mix.exs b/mix.exs index e5f39c0..e7f00b1 100644 --- a/mix.exs +++ b/mix.exs @@ -76,7 +76,11 @@ defmodule Cocktailparty.MixProject do {:libcluster, "~> 3.3"}, {:tzdata, "~> 1.1.1"}, # STOMP support - {:barytherium, "~> 0.7.0"} + {:barytherium, "~> 0.7.0"}, + # YAML parsing + {:yaml_elixir, "~> 2.9.0"}, + # YAML encoding + {:ymlr, "~> 5.0"} ] end diff --git a/mix.lock b/mix.lock index 6493786..8c50c64 100644 --- a/mix.lock +++ b/mix.lock @@ -63,4 +63,7 @@ "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, "websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"}, "websock_adapter": {:hex, :websock_adapter, "0.5.5", "9dfeee8269b27e958a65b3e235b7e447769f66b5b5925385f5a569269164a210", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "4b977ba4a01918acbf77045ff88de7f6972c2a009213c515a445c48f224ffce9"}, + "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"}, + "ymlr": {:hex, :ymlr, "5.1.3", "a8061add5a378e20272a31905be70209a5680fdbe0ad51f40cb1af4bdd0a010b", [:mix], [], "hexpm", "8663444fa85101a117887c170204d4c5a2182567e5f84767f0071cf15f2efb1e"}, } diff --git a/test/cocktailparty_web/controllers/connection_controller_test.exs b/test/cocktailparty_web/controllers/connection_controller_test.exs index 5364699..e628179 100644 --- a/test/cocktailparty_web/controllers/connection_controller_test.exs +++ b/test/cocktailparty_web/controllers/connection_controller_test.exs @@ -2,8 +2,6 @@ defmodule CocktailpartyWeb.ConnectionControllerTest do use CocktailpartyWeb.ConnCase import Cocktailparty.InputFixtures - import Cocktailparty.UserManagementFixtures - alias CocktailpartyWeb.UserAuth @create_attrs %{enabled: true, name: "some name", uri: "some uri"} @update_attrs %{enabled: false, name: "some updated name", uri: "some updated uri"}