Skip to content

Commit

Permalink
add test for provisioning s3 bucket
Browse files Browse the repository at this point in the history
Signed-off-by: Zack Siri <[email protected]>
  • Loading branch information
zacksiri committed Nov 22, 2023
1 parent 20acf34 commit 63b66e9
Show file tree
Hide file tree
Showing 10 changed files with 132 additions and 44 deletions.
2 changes: 2 additions & 0 deletions config/test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ config :uplink, Uplink.Secret, "secretsomethingsixteen"

config :uplink, Uplink.Clients.Instellar, endpoint: "http://localhost/uplink"

config :uplink, :drivers, aws_s3: Uplink.Drivers.Bucket.AwsMock

# config :plug, :validate_header_keys_during_test, false
# Print only warnings and errors during test
config :logger, level: :warn
14 changes: 12 additions & 2 deletions lib/uplink/components/instance/provision.ex
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ defmodule Uplink.Components.Instance.Provision do
"generator" => %{"module" => module},
"credential" => credential_params
},
%{"component_id" => component_id, "variable_id" => variable_id}
%{"component_id" => component_id, "variable_id" => variable_id} =
job_args
) do
uuid = Ecto.UUID.generate()

Expand All @@ -32,8 +33,17 @@ defmodule Uplink.Components.Instance.Provision do

name = "#{component_type}-#{id}"

options =
job_args
|> Map.get("arguments", %{})
|> Enum.map(fn {k, v} -> {String.to_atom(k), v} end)

with {:ok, credential} <-
Drivers.perform(module, %{"credential" => credential_params}),
Drivers.perform(
module,
%{"credential" => credential_params},
options
),
{:ok, component_instance_attributes} <-
Instellar.create_component_instance(component_id, %{
"variable_id" => variable_id,
Expand Down
16 changes: 11 additions & 5 deletions lib/uplink/drivers.ex
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
defmodule Uplink.Drivers do
@drivers %{
@drivers Application.compile_env(:uplink, :drivers, [])

@driver_mapping %{
"database/postgresql" => __MODULE__.Database.Postgresql,
"bucket/aws" => __MODULE__.Bucket.Aws
"bucket/aws-s3" => Keyword.get(@drivers, :aws_s3, __MODULE__.Bucket.Aws)
}

def perform(module, params) do
driver = Map.fetch!(@drivers, module)
driver.perform(params)
defmodule Behaviour do
@callback perform(map(), Keyword.t()) :: {:ok, map()}
end

def perform(module, params, options) do
driver = Map.fetch!(@driver_mapping, module)
driver.perform(params, options)
end
end
7 changes: 5 additions & 2 deletions lib/uplink/drivers/bucket.ex
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
defmodule Uplink.Drivers.Bucket do
defmodule Aws do
@behaviour Uplink.Drivers.Behaviour

def perform(%{"credential" => credential_params}, options \\ []) do
credential_params = Map.put(credential_params, "type", "component")

with {:ok, master_credential} <-
Formation.S3.Credential.create(credential_params),
{:ok, generated_credential} <-
Formation.Aws.Bucket.create_credential_and_bucket(
master_credential, options
Formation.Aws.create_credential_and_bucket(
master_credential,
options
) do
{:ok, generated_credential}
end
Expand Down
7 changes: 6 additions & 1 deletion lib/uplink/drivers/database.ex
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
defmodule Uplink.Drivers.Database do
defmodule Postgresql do
@behaviour Uplink.Drivers.Behaviour

def perform(%{"credential" => credential_params}, options \\ []) do
with {:ok, master_credential} <-
Formation.Postgresql.Credential.create(credential_params),
{:ok, generated_credential} <-
Formation.Postgresql.create_user_and_database(master_credential, options) do
Formation.Postgresql.create_user_and_database(
master_credential,
options
) do
{:ok, generated_credential}
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/uplink/packages/instance/upgrade.ex
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ defmodule Uplink.Packages.Instance.Upgrade do
defp handle_error(comment, %Job{attempt: _attempt, args: args}),
do: deactivate_and_boot(args, comment: comment)

defp deactivate_and_boot(args, options \\ []) do
defp deactivate_and_boot(args, options) do
args
|> Map.merge(%{
"mode" => "deactivate_and_boot",
Expand Down
6 changes: 3 additions & 3 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,7 @@ defmodule Uplink.MixProject do
# Rest Client
{:req, "~> 0.4"},

# File System
{:file_system, "~> 0.2.10"},
# Clustering
{:libcluster, "~> 3.0"},

# Downstream
Expand All @@ -66,14 +65,15 @@ defmodule Uplink.MixProject do
{:x509, "~> 0.8.4"},

# Infrastructure
{:formation, "~> 0.11"},
{:formation, path: "../formation"},
{:lexdee, "~> 2.3"},
{:plug_cowboy, "~> 2.0"},
{:reverse_proxy_plug, "~> 2.1"},
{:mint_web_socket, "~> 1.0.2"},

# Test
{:bypass, "~> 2.1", only: :test},
{:mox, "~> 1.0", only: :test},
{:dialyxir, "~> 1.0", only: [:dev], runtime: false}
# {:dep_from_hexpm, "~> 0.3.0"},
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
Expand Down
7 changes: 4 additions & 3 deletions mix.lock
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
%{
"aws": {:hex, :aws, "0.13.3", "d2e932c2588e2b15fca04f345dfced6e07b81d6534e65783de23190c57891df7", [:mix], [{:aws_signature, "~> 0.3", [hex: :aws_signature, repo: "hexpm", optional: false]}, {:finch, "~> 0.13", [hex: :finch, repo: "hexpm", optional: true]}, {:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "4ad46a204370d3ef8eab102776a00070ec6fcc4414db7f6b39f3fc0d99564e18"},
"aws_signature": {:hex, :aws_signature, "0.3.1", "67f369094cbd55ffa2bbd8cc713ede14b195fcfb45c86665cd7c5ad010276148", [:rebar3], [], "hexpm", "50fc4dc1d1f7c2d0a8c63f455b3c66ecd74c1cf4c915c768a636f9227704a674"},
"bypass": {:hex, :bypass, "2.1.0", "909782781bf8e20ee86a9cabde36b259d44af8b9f38756173e8f5e2e1fabb9b1", [:mix], [{:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: false]}, {:ranch, "~> 1.3", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "d9b5df8fa5b7a6efa08384e9bbecfe4ce61c77d28a4282f79e02f1ef78d96b80"},
"castore": {:hex, :castore, "0.1.22", "4127549e411bedd012ca3a308dede574f43819fe9394254ca55ab4895abfa1a2", [:mix], [], "hexpm", "c17576df47eb5aa1ee40cc4134316a99f5cad3e215d5c77b8dd3cfef12a22cac"},
"certifi": {:hex, :certifi, "2.12.0", "2d1cca2ec95f59643862af91f001478c9863c2ac9cb6e2f89780bfd8de987329", [:rebar3], [], "hexpm", "ee68d85df22e554040cdb4be100f33873ac6051387baf6a8f6ce82272340ff1c"},
"connection": {:hex, :connection, "1.1.0", "ff2a49c4b75b6fb3e674bfc5536451607270aac754ffd1bdfe175abe4a6d7a68", [:mix], [], "hexpm", "722c1eb0a418fbe91ba7bd59a47e28008a189d47e37e0e7bb85585a016b2869c"},
"cowboy": {:hex, :cowboy, "2.10.0", "ff9ffeff91dae4ae270dd975642997afe2a1179d94b1887863e43f681a203e26", [:make, :rebar3], [{:cowlib, "2.12.1", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "3afdccb7183cc6f143cb14d3cf51fa00e53db9ec80cdcd525482f5e99bc41d6b"},
"cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"},
"cowlib": {:hex, :cowlib, "2.12.1", "a9fa9a625f1d2025fe6b462cb865881329b5caff8f1854d1cbc9f9533f00e1e1", [:make, :rebar3], [], "hexpm", "163b73f6367a7341b33c794c4e88e7dbfe6498ac42dcd69ef44c5bc5507c8db0"},
Expand All @@ -15,9 +16,8 @@
"ecto_sql": {:hex, :ecto_sql, "3.10.1", "6ea6b3036a0b0ca94c2a02613fd9f742614b5cfe494c41af2e6571bb034dd94c", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.10.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16.0 or ~> 0.17.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f6a25bdbbd695f12c8171eaff0851fa4c8e72eec1e98c7364402dda9ce11c56b"},
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
"eventful": {:hex, :eventful, "0.2.3", "dc795c95b2d00d90b3a5d58c66bd0188b39be08b9da61a743ac40186fd313034", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "a1607d9d98ebc45e47573a81c11adfb571259a1db900748c6bee2dc25e5e171c"},
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
"finch": {:hex, :finch, "0.16.0", "40733f02c89f94a112518071c0a91fe86069560f5dbdb39f9150042f44dcfb1a", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6 or ~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f660174c4d519e5fec629016054d60edd822cdfe2b7270836739ac2f97735ec5"},
"formation": {:hex, :formation, "0.12.5", "8e85c63846979616dede203fd599a53cdbb48ed9bf4531108bf8cf68ec37bf80", [:mix], [{:ecto, "~> 3.10", [hex: :ecto, repo: "hexpm", optional: false]}, {:lexdee, "~> 2.3", [hex: :lexdee, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.17.1", [hex: :postgrex, repo: "hexpm", optional: false]}], "hexpm", "bb22f0d64f084edbca21b7627bacb8d51a844efbb42233c5308bc3361c957f24"},
"formation": {:hex, :formation, "0.13.0", "4fd41648d96545dee600b3633397fcff6ddc5778d501a760466aee17a1db2e43", [:mix], [{:aws, "~> 0.13.0", [hex: :aws, repo: "hexpm", optional: false]}, {:ecto, "~> 3.10", [hex: :ecto, repo: "hexpm", optional: false]}, {:finch, "~> 0.16.0", [hex: :finch, repo: "hexpm", optional: false]}, {:lexdee, "~> 2.3", [hex: :lexdee, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.17.1", [hex: :postgrex, repo: "hexpm", optional: false]}], "hexpm", "aab41fc1ee7a2bd448d8d57880d4aa0a90f7fa7c99f1a14de9b9d2ae62ae3e8b"},
"hackney": {:hex, :hackney, "1.20.1", "8d97aec62ddddd757d128bfd1df6c5861093419f8f7a4223823537bad5d064e2", [:rebar3], [{:certifi, "~> 2.12.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "fe9094e5f1a2a2c0a7d10918fee36bfec0ec2a979994cff8cfe8058cd9af38e3"},
"hpax": {:hex, :hpax, "0.1.2", "09a75600d9d8bbd064cdd741f21fc06fc1f4cf3d0fcc335e5aa19be1a7235c84", [:mix], [], "hexpm", "2c87843d5a23f5f16748ebe77969880e29809580efdaccd615cd3bed628a8c13"},
"httpoison": {:hex, :httpoison, "1.8.2", "9eb9c63ae289296a544842ef816a85d881d4a31f518a0fec089aaa744beae290", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "2bb350d26972e30c96e2ca74a1aaf8293d61d0742ff17f01e0279fef11599921"},
Expand All @@ -30,6 +30,7 @@
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"},
"mint": {:hex, :mint, "1.5.1", "8db5239e56738552d85af398798c80648db0e90f343c8469f6c6d8898944fb6f", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "4a63e1e76a7c3956abd2c72f370a0d0aecddc3976dea5c27eccbecfa5e7d5b1e"},
"mint_web_socket": {:hex, :mint_web_socket, "1.0.3", "aab42fff792a74649916236d0b01f560a0b3f03ca5dea693c230d1c44736b50e", [:mix], [{:mint, ">= 1.4.1 and < 2.0.0-0", [hex: :mint, repo: "hexpm", optional: false]}], "hexpm", "ca3810ca44cc8532e3dce499cc17f958596695d226bb578b2fbb88c09b5954b0"},
"mox": {:hex, :mox, "1.1.0", "0f5e399649ce9ab7602f72e718305c0f9cdc351190f72844599545e4996af73c", [:mix], [], "hexpm", "d44474c50be02d5b72131070281a5d3895c0e7a95c780e90bc0cfe712f633a13"},
"nebulex": {:hex, :nebulex, "2.5.1", "8ffbde30643e76d6cec712281ca68ab05f73170de9e758a39bc7e4e6987f608f", [:mix], [{:decorator, "~> 1.4", [hex: :decorator, repo: "hexpm", optional: true]}, {:shards, "~> 1.1", [hex: :shards, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "8d0d3800d98c68ee19b229b7fe35fac0192ab5963a573612cf74a388e083bccf"},
"nimble_options": {:hex, :nimble_options, "1.0.2", "92098a74df0072ff37d0c12ace58574d26880e522c22801437151a159392270e", [:mix], [], "hexpm", "fd12a8db2021036ce12a309f26f564ec367373265b53e25403f0ee697380f1b8"},
"nimble_pool": {:hex, :nimble_pool, "1.0.0", "5eb82705d138f4dd4423f69ceb19ac667b3b492ae570c9f5c900bb3d2f50a847", [:mix], [], "hexpm", "80be3b882d2d351882256087078e1b1952a28bf98d0a287be87e4a24a710b67a"},
Expand Down
2 changes: 2 additions & 0 deletions test/scenarios/mocks.ex
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
Mox.defmock(Uplink.Drivers.Bucket.AwsMock, for: Uplink.Drivers.Behaviour)

defmodule Uplink.TaskSupervisorMock do
def async_nolink(_supervisor, fun),
do: fun.()
Expand Down
113 changes: 86 additions & 27 deletions test/uplink/components/instance/provision_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,7 @@ defmodule Uplink.Components.Instance.ProvisionTest do

alias Uplink.Components.Instance

@get_component_response %{
"data" => %{
"attributes" => %{
"generator" => %{"module" => "database/postgresql"},
"credential" => %{
"username" => System.get_env("POSTGRES_USERNAME"),
"password" => System.get_env("POSTGRES_PASSWORD"),
"host" => System.get_env("POSTGRES_HOST"),
"port" => "5432",
"ssl" => false
}
}
}
}

@create_component_instance_response %{
"data" => %{
"attributes" => %{
"id" => 1,
"current_state" => "active"
}
}
}
import Mox

setup do
bypass = Bypass.open()
Expand All @@ -40,14 +18,27 @@ defmodule Uplink.Components.Instance.ProvisionTest do
{:ok, bypass: bypass}
end

describe "perform" do
describe "database postgresql" do
test "provisions new postgresql database", %{bypass: bypass} do
Bypass.expect_once(bypass, "GET", "/uplink/self/components/1", fn conn ->
conn
|> Plug.Conn.put_resp_header("content-type", "application/json")
|> Plug.Conn.resp(
200,
Jason.encode!(@get_component_response)
Jason.encode!(%{
"data" => %{
"attributes" => %{
"generator" => %{"module" => "database/postgresql"},
"credential" => %{
"username" => System.get_env("POSTGRES_USERNAME"),
"password" => System.get_env("POSTGRES_PASSWORD"),
"host" => System.get_env("POSTGRES_HOST"),
"port" => "5432",
"ssl" => false
}
}
}
})
)
end)

Expand All @@ -60,18 +51,86 @@ defmodule Uplink.Components.Instance.ProvisionTest do
|> Plug.Conn.put_resp_header("content-type", "application/json")
|> Plug.Conn.resp(
201,
Jason.encode!(@create_component_instance_response)
Jason.encode!(%{
"data" => %{
"attributes" => %{
"id" => 1,
"current_state" => "active"
}
}
})
)
end
)

assert {:ok, result} =
perform_job(Instance.Provision, %{
component_id: "1",
variable_id: "1"
variable_id: "1",
arguments: %{"something" => "blah"}
})

assert %{"id" => 1} = result
end
end

describe "aws s3 bucket" do
test "provision aws s3 bucket", %{bypass: bypass} do
Uplink.Drivers.Bucket.AwsMock
|> expect(:perform, fn _params, options ->
assert [acl: "private"] == options

{:ok, %Formation.S3.Credential{}}
end)

Bypass.expect_once(bypass, "GET", "/uplink/self/components/1", fn conn ->
conn
|> Plug.Conn.put_resp_header("content-type", "application/json")
|> Plug.Conn.resp(
200,
Jason.encode!(%{
"data" => %{
"attributes" => %{
"generator" => %{"module" => "bucket/aws-s3"},
"credential" => %{
"username" => "someaccesskey",
"password" => "somesecretkey",
"host" => "s3.amazonaws.com",
"resource" => "us-east-1"
}
}
}
})
)
end)

Bypass.expect_once(
bypass,
"POST",
"/uplink/self/components/1/instances",
fn conn ->
conn
|> Plug.Conn.put_resp_header("content-type", "application/json")
|> Plug.Conn.resp(
201,
Jason.encode!(%{
"data" => %{
"attributes" => %{
"id" => 1,
"current_state" => "active"
}
}
})
)
end
)

assert {:ok, _result} =
perform_job(Instance.Provision, %{
component_id: "1",
variable_id: "1",
arguments: %{"acl" => "private"}
})
end
end
end

0 comments on commit 63b66e9

Please sign in to comment.