diff --git a/lib/uplink/components/instance/enqueue.ex b/lib/uplink/components/instance/enqueue.ex new file mode 100644 index 00000000..c2361d19 --- /dev/null +++ b/lib/uplink/components/instance/enqueue.ex @@ -0,0 +1,40 @@ +defmodule Uplink.Components.Instance.Enqueue do + alias Uplink.Components.Instance.Modify + alias Uplink.Components.Instance.Provision + + def job( + component_id, + %{ + "arguments" => argument_params, + "component_instance_id" => component_instance_id, + "variable_id" => variable_id + } + ) do + %{ + component_id: component_id, + variable_id: variable_id, + component_instance_id: component_instance_id, + arguments: argument_params + } + |> Modify.new() + |> Oban.insert() + end + + def job( + component_id, + %{ + "arguments" => argument_params, + "variable_id" => variable_id + } + ) do + %{ + component_id: component_id, + variable_id: variable_id, + arguments: argument_params + } + |> Provision.new() + |> Oban.insert() + end + + def job(_, _), do: {:error, :unprocessable_entity} +end diff --git a/lib/uplink/components/router.ex b/lib/uplink/components/router.ex index ade77442..59eb9d00 100644 --- a/lib/uplink/components/router.ex +++ b/lib/uplink/components/router.ex @@ -5,7 +5,7 @@ defmodule Uplink.Components.Router do alias Uplink.Secret alias Uplink.Members - alias Uplink.Components.Instance.Provision + alias Uplink.Components.Instance.Enqueue plug :match @@ -19,32 +19,16 @@ defmodule Uplink.Components.Router do plug :dispatch post "/:component_id/instances" do - %{ - "actor" => actor_params, - "arguments" => argument_params, - "variable_id" => variable_id - } = conn.body_params - - job_params = - if component_instance_id = - Map.get(conn.body_params, "component_instance_id") do - Modify.new(%{ - component_id: component_id, - variable_id: variable_id, - component_instance_id: component_instance_id, - arguments: argument_params - }) - else - Provision.new(%{ - component_id: component_id, - variable_id: variable_id, - arguments: argument_params - }) - end + %{"actor" => actor_params} = conn.body_params with {:ok, %Members.Actor{}} <- Members.get_or_create_actor(actor_params), - {:ok, job} <- Oban.insert(job_params) do + {:ok, job} <- Enqueue.job(component_id, conn.body_params) do json(conn, :created, %{id: job.id}) + else + {:error, :unprocessable_entity = error} -> + json(conn, error, %{ + error: %{message: "invalid parameters for component instance job"} + }) end end end diff --git a/test/uplink/components/router_test.exs b/test/uplink/components/router_test.exs index cd50175d..8c16ac4f 100644 --- a/test/uplink/components/router_test.exs +++ b/test/uplink/components/router_test.exs @@ -8,31 +8,53 @@ defmodule Uplink.Components.RouterTest do @opts Router.init([]) - @valid_body Jason.encode!(%{ - "actor" => %{ - "provider" => "instellar", - "identifier" => "zacksiri", - "id" => "1" - }, - "variable_id" => "1", - "arguments" => %{} - }) + @valid_provision_body Jason.encode!(%{ + "actor" => %{ + "provider" => "instellar", + "identifier" => "zacksiri", + "id" => "1" + }, + "variable_id" => "1", + "arguments" => %{} + }) + + @valid_modify_body Jason.encode!(%{ + "actor" => %{ + "provider" => "instellar", + "identifier" => "zacksiri", + "id" => "1" + }, + "component_instance_id" => "1", + "variable_id" => "1", + "arguments" => %{} + }) + + @incomplete_body Jason.encode!(%{ + "actor" => %{ + "provider" => "instellar", + "identifier" => "zacksiri", + "id" => "1" + }, + "arguments" => %{} + }) setup do :ok = Ecto.Adapters.SQL.Sandbox.checkout(Uplink.Repo) + end - signature = - :crypto.mac(:hmac, :sha256, Uplink.Secret.get(), @valid_body) - |> Base.encode16() - |> String.downcase() + describe "provision" do + setup do + signature = + :crypto.mac(:hmac, :sha256, Uplink.Secret.get(), @valid_provision_body) + |> Base.encode16() + |> String.downcase() - {:ok, signature: signature} - end + {:ok, signature: signature} + end - describe "create component instance provisioning job" do - test "successfully", %{signature: signature} do + test "successfully enqueue provision job", %{signature: signature} do conn = - conn(:post, "/1/instances", @valid_body) + conn(:post, "/1/instances", @valid_provision_body) |> put_req_header("x-uplink-signature-256", "sha256=#{signature}") |> put_req_header("content-type", "application/json") |> Router.call(@opts) @@ -47,4 +69,58 @@ defmodule Uplink.Components.RouterTest do ) end end + + describe "modify" do + setup do + signature = + :crypto.mac(:hmac, :sha256, Uplink.Secret.get(), @valid_modify_body) + |> Base.encode16() + |> String.downcase() + + {:ok, signature: signature} + end + + test "successfully enqueue modify job", %{signature: signature} do + conn = + conn(:post, "/1/instances", @valid_modify_body) + |> put_req_header("x-uplink-signature-256", "sha256=#{signature}") + |> put_req_header("content-type", "application/json") + |> Router.call(@opts) + + assert conn.status == 201 + + assert %{"data" => %{"id" => _job_id}} = Jason.decode!(conn.resp_body) + + assert_enqueued( + worker: Instance.Modify, + args: %{ + "component_instance_id" => "1", + "variable_id" => "1", + "component_id" => "1", + "arguments" => %{} + } + ) + end + end + + describe "error" do + setup do + signature = + :crypto.mac(:hmac, :sha256, Uplink.Secret.get(), @incomplete_body) + |> Base.encode16() + |> String.downcase() + + {:ok, signature: signature} + end + + test "error message", %{signature: signature} do + conn = + conn(:post, "/1/instances", @incomplete_body) + |> put_req_header("x-uplink-signature-256", "sha256=#{signature}") + |> put_req_header("content-type", "application/json") + |> Router.call(@opts) + + assert conn.status == 422 + end + end end