Skip to content

Commit

Permalink
Add connect/2
Browse files Browse the repository at this point in the history
  • Loading branch information
tlux committed May 10, 2019
1 parent 74f27ea commit 896626e
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 23 deletions.
10 changes: 10 additions & 0 deletions lib/sftp_client.ex
Original file line number Diff line number Diff line change
Expand Up @@ -142,11 +142,21 @@ defmodule SFTPClient do
run(Operations.Connect, :connect!, [config_or_opts])
end

@doc delegate_to: {Operations.Connect, :connect!, 2}
def connect!(config_or_opts, fun) do
run(Operations.Connect, :connect!, [config_or_opts, fun])
end

@doc delegate_to: {Operations.Connect, :connect, 1}
def connect(config_or_opts) do
run(Operations.Connect, :connect, [config_or_opts])
end

@doc delegate_to: {Operations.Connect, :connect, 2}
def connect(config_or_opts, fun) do
run(Operations.Connect, :connect, [config_or_opts, fun])
end

@doc delegate_to: {Operations.DeleteDir, :delete_dir!, 2}
def delete_dir!(conn, path) do
run(Operations.DeleteDir, :delete_dir!, [conn, path])
Expand Down
60 changes: 37 additions & 23 deletions lib/sftp_client/operations/connect.ex
Original file line number Diff line number Diff line change
Expand Up @@ -52,37 +52,51 @@ defmodule SFTPClient.Operations.Connect do
end

@doc """
Connects to an SSH server and opens an SFTP channel. Raises when the
connection fails.
## Options
Connects to an SSH server and opens an SFTP channel, then runs the function
and closes the connection when finished. Accepts the same options as
`connect/1`.
"""
@spec connect(
Config.t() | Keyword.t() | %{optional(atom) => any},
(Conn.t() -> any)
) :: any | {:error, any}
def connect(config_or_opts, fun) do
with {:ok, conn} <- connect(config_or_opts) do
run_callback(conn, fun)
end
end

* `:host` (required) - The host of the SFTP server.
* `:port` - The port of the SFTP server, defaults to 22.
* `:user` - The user to authenticate as, when omitted tries to determine the
current user.
* `:password` - The password for the user.
* `:user_dir` - The directory to read private keys from.
* `:dsa_pass_phrase` - The passphrase for an DSA private key from the
specified user dir.
* `:rsa_pass_phrase` - The passphrase for an RSA private key from the
specified user dir.
* `:ecdsa_pass_phrase` - The passphrase for an ECDSA private key from the
specified user dir.
* `:private_key_path` - The path to the private key to use for authentication.
* `:private_key_pass_phrase` - The passphrase that is used to decrypt the
specified private key.
* `:inet` - The IP version to use, either `:inet` (default) or `:inet6`.
* `:sftp_vsn` - The SFTP version to be used.
* `:connect_timeout` - The connection timeout in milliseconds (defaults to
5000 ms), can be set to `:infinity` to disable timeout.
@doc """
Connects to an SSH server and opens an SFTP channel. Accepts the same options
as `connect/1`. Raises when the connection fails.
"""
@spec connect!(Config.t() | Keyword.t() | %{optional(atom) => any}) ::
Conn.t() | no_return
def connect!(config_or_opts) do
config_or_opts |> connect() |> may_bang!()
end

@doc """
Connects to an SSH server and opens an SFTP channel, then runs the function
and closes the connection when finished. Accepts the same options as
`connect/1`. Raises when the connection fails.
"""
@spec connect!(
Config.t() | Keyword.t() | %{optional(atom) => any},
(Conn.t() -> any)
) :: any | no_return
def connect!(config_or_opts, fun) do
config_or_opts
|> connect!()
|> run_callback(fun)
end

defp run_callback(conn, fun) do
fun.(conn)
after
SFTPClient.disconnect(conn)
end

defp validate_config(config) do
config
|> Map.from_struct()
Expand Down
73 changes: 73 additions & 0 deletions test/sftp_client/operations/connect_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ defmodule SFTPClient.Operations.ConnectTest do
import Mox

alias SFTPClient.Adapter.SFTP.Mock, as: SFTPMock
alias SFTPClient.Adapter.SSH.Mock, as: SSHMock
alias SFTPClient.Config
alias SFTPClient.Conn
alias SFTPClient.ConnError
Expand Down Expand Up @@ -150,6 +151,41 @@ defmodule SFTPClient.Operations.ConnectTest do
end
end

describe "connect/2" do
test "success", %{opts: opts} do
SFTPMock
|> expect(:start_channel, fn 'test-host', 23, ^opts ->
{:ok, :channel_pid_stub, :conn_ref_stub}
end)
|> expect(:stop_channel, fn :channel_pid_stub -> :ok end)

expect(SSHMock, :close, fn :conn_ref_stub -> :ok end)

conn = %Conn{
config: @config,
channel_pid: :channel_pid_stub,
conn_ref: :conn_ref_stub
}

assert Connect.connect(@config, fn ^conn -> :result end) == :result
end

test "connection error", %{opts: opts} do
message = 'Unable to connect using the available authentication methods'

expect(SFTPMock, :start_channel, fn 'test-host', 23, ^opts ->
{:error, message}
end)

assert Connect.connect(@config, fn _conn ->
send(self(), :fun_called)
:result
end) == {:error, %ConnError{message: to_string(message)}}

refute_received :fun_called
end
end

describe "connect!/1" do
test "connect with SFTPClient.Config", %{opts: opts} do
expect(SFTPMock, :start_channel, fn 'test-host', 23, ^opts ->
Expand Down Expand Up @@ -225,4 +261,41 @@ defmodule SFTPClient.Operations.ConnectTest do
fn -> Connect.connect!(config) end
end
end

describe "connect!/2" do
test "success", %{opts: opts} do
SFTPMock
|> expect(:start_channel, fn 'test-host', 23, ^opts ->
{:ok, :channel_pid_stub, :conn_ref_stub}
end)
|> expect(:stop_channel, fn :channel_pid_stub -> :ok end)

expect(SSHMock, :close, fn :conn_ref_stub -> :ok end)

conn = %Conn{
config: @config,
channel_pid: :channel_pid_stub,
conn_ref: :conn_ref_stub
}

assert Connect.connect!(@config, fn ^conn -> :result end) == :result
end

test "connection error", %{opts: opts} do
message = 'Unable to connect using the available authentication methods'

expect(SFTPMock, :start_channel, fn 'test-host', 23, ^opts ->
{:error, message}
end)

assert_raise ConnError, to_string(message), fn ->
Connect.connect!(@config, fn _conn ->
send(self(), :fun_called)
:result
end)
end

refute_received :fun_called
end
end
end
18 changes: 18 additions & 0 deletions test/sftp_client_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,15 @@ defmodule SFTPClientTest do
end
end

describe "connect!/2" do
test "delegate to Operations.Connect" do
assert_delegate_to_operation(Operations.Connect, :connect!, [
:config_or_opts_stub,
:fun_stub
])
end
end

describe "connect/1" do
test "delegate to Operations.Connect" do
assert_delegate_to_operation(Operations.Connect, :connect, [
Expand All @@ -49,6 +58,15 @@ defmodule SFTPClientTest do
end
end

describe "connect/2" do
test "delegate to Operations.Connect" do
assert_delegate_to_operation(Operations.Connect, :connect, [
:config_or_opts_stub,
:fun_stub
])
end
end

describe "delete_dir!/2" do
test "delegate to Operations.DeleteDir" do
assert_delegate_to_operation(Operations.DeleteDir, :delete_dir!, [
Expand Down

0 comments on commit 896626e

Please sign in to comment.