Skip to content

Commit

Permalink
Porting SSH module to FAKE 5
Browse files Browse the repository at this point in the history
  • Loading branch information
ziadadeela committed Feb 2, 2022
1 parent 8766aba commit ec799b9
Show file tree
Hide file tree
Showing 11 changed files with 179 additions and 4 deletions.
15 changes: 15 additions & 0 deletions Fake.sln
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "Fake.DotNet.Xamarin", "src\
EndProject
Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "Fake.Net.Http", "src\app\Fake.Net.Http\Fake.Net.Http.fsproj", "{D24CEE35-B6C0-4C92-AE18-E80F90B69974}"
EndProject
Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "Fake.Net.SSH", "src\app\Fake.Net.SSH\Fake.Net.SSH.fsproj", "{5B2A7546-A441-45C9-8176-2872E2A30477}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{CCAC5CAB-03C8-4C11-ADBE-A0D05F6A4F18}"
EndProject
Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "Fake.Core.UnitTests", "src\test\Fake.Core.UnitTests\Fake.Core.UnitTests.fsproj", "{31A5759B-B562-43C0-A845-14EFA4091543}"
Expand Down Expand Up @@ -633,6 +635,18 @@ Global
{D24CEE35-B6C0-4C92-AE18-E80F90B69974}.Release|x64.Build.0 = Release|Any CPU
{D24CEE35-B6C0-4C92-AE18-E80F90B69974}.Release|x86.ActiveCfg = Release|Any CPU
{D24CEE35-B6C0-4C92-AE18-E80F90B69974}.Release|x86.Build.0 = Release|Any CPU
{5B2A7546-A441-45C9-8176-2872E2A30477}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5B2A7546-A441-45C9-8176-2872E2A30477}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5B2A7546-A441-45C9-8176-2872E2A30477}.Debug|x64.ActiveCfg = Debug|Any CPU
{5B2A7546-A441-45C9-8176-2872E2A30477}.Debug|x64.Build.0 = Debug|Any CPU
{5B2A7546-A441-45C9-8176-2872E2A30477}.Debug|x86.ActiveCfg = Debug|Any CPU
{5B2A7546-A441-45C9-8176-2872E2A30477}.Debug|x86.Build.0 = Debug|Any CPU
{5B2A7546-A441-45C9-8176-2872E2A30477}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5B2A7546-A441-45C9-8176-2872E2A30477}.Release|Any CPU.Build.0 = Release|Any CPU
{5B2A7546-A441-45C9-8176-2872E2A30477}.Release|x64.ActiveCfg = Release|Any CPU
{5B2A7546-A441-45C9-8176-2872E2A30477}.Release|x64.Build.0 = Release|Any CPU
{5B2A7546-A441-45C9-8176-2872E2A30477}.Release|x86.ActiveCfg = Release|Any CPU
{5B2A7546-A441-45C9-8176-2872E2A30477}.Release|x86.Build.0 = Release|Any CPU
{31A5759B-B562-43C0-A845-14EFA4091543}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{31A5759B-B562-43C0-A845-14EFA4091543}.Debug|Any CPU.Build.0 = Debug|Any CPU
{31A5759B-B562-43C0-A845-14EFA4091543}.Debug|x64.ActiveCfg = Debug|Any CPU
Expand Down Expand Up @@ -1261,6 +1275,7 @@ Global
{4BCE4F9C-8FC2-4207-81F1-20CB07D852DC} = {7BFFAE76-DEE9-417A-A79B-6A6644C4553A}
{13C1F95D-2FAD-4890-BF94-0AE7CF9AB2FC} = {7BFFAE76-DEE9-417A-A79B-6A6644C4553A}
{D24CEE35-B6C0-4C92-AE18-E80F90B69974} = {7BFFAE76-DEE9-417A-A79B-6A6644C4553A}
{5B2A7546-A441-45C9-8176-2872E2A30477} = {7BFFAE76-DEE9-417A-A79B-6A6644C4553A}
{31A5759B-B562-43C0-A845-14EFA4091543} = {CCAC5CAB-03C8-4C11-ADBE-A0D05F6A4F18}
{D8850C67-0542-427A-ABCB-92174EA42C95} = {7BFFAE76-DEE9-417A-A79B-6A6644C4553A}
{8D72BED1-BC02-4B23-A631-4849BD0FD3E1} = {7BFFAE76-DEE9-417A-A79B-6A6644C4553A}
Expand Down
1 change: 1 addition & 0 deletions build.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@ let dotnetAssemblyInfos =
"Fake.JavaScript.Yarn", "Running Yarn commands"
"Fake.JavaScript.TypeScript", "Running TypeScript compiler"
"Fake.Net.Http", "HTTP Client"
"Fake.Net.SSH", "SSH operations"
"Fake.netcore", "Command line tool"
"Fake.Runtime", "Core runtime features"
"Fake.Sql.DacPac", "Sql Server Data Tools DacPac operations (Obsolete: Use Fake.Sql.SqlPackage instead)"
Expand Down
1 change: 1 addition & 0 deletions help/templates/template.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@
<a href="/apidocs/v5/index.html#Fake.Net" class="navbar-link">Net</a>
<div class="navbar-dropdown" class="navbar-item">
<a href="/net-http.html" class="navbar-item">Http</a>
<a href="/apidocs/v5/fake-net-ssh.html" class="navbar-item">SSH</a>
</div>
</div>
<div class="navbar-item has-dropdown is-hoverable">
Expand Down
19 changes: 19 additions & 0 deletions src/app/Fake.Net.SSH/AssemblyInfo.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Auto-Generated by FAKE; do not edit
namespace System
open System.Reflection

[<assembly: AssemblyTitleAttribute("FAKE - F# Make SSH operations")>]
[<assembly: AssemblyProductAttribute("FAKE - F# Make")>]
[<assembly: AssemblyVersionAttribute("5.21.1")>]
[<assembly: AssemblyInformationalVersionAttribute("5.21.1")>]
[<assembly: AssemblyFileVersionAttribute("5.21.1")>]
[<assembly: AssemblyMetadataAttribute("BuildDate","2022-01-31")>]
do ()

module internal AssemblyVersionInformation =
let [<Literal>] AssemblyTitle = "FAKE - F# Make SSH operations"
let [<Literal>] AssemblyProduct = "FAKE - F# Make"
let [<Literal>] AssemblyVersion = "5.21.1"
let [<Literal>] AssemblyInformationalVersion = "5.21.1"
let [<Literal>] AssemblyFileVersion = "5.21.1"
let [<Literal>] AssemblyMetadata_BuildDate = "2022-01-31"
23 changes: 23 additions & 0 deletions src/app/Fake.Net.SSH/Fake.Net.SSH.fsproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net472</TargetFrameworks>
<AssemblyName>Fake.Net.SSH</AssemblyName>
<OutputType>Library</OutputType>
</PropertyGroup>
<PropertyGroup>
<DefineConstants>$(DefineConstants)</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DefineConstants>$(DefineConstants);RELEASE</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Compile Include="AssemblyInfo.fs" />
<Compile Include="SSH.fs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Fake.Core.Environment\Fake.Core.Environment.fsproj" />
<ProjectReference Include="..\Fake.Core.Process\Fake.Core.Process.fsproj" />
<ProjectReference Include="..\Fake.Core.Trace\Fake.Core.Trace.fsproj" />
</ItemGroup>
<Import Project="..\..\..\.paket\Paket.Restore.targets" />
</Project>
63 changes: 63 additions & 0 deletions src/app/Fake.Net.SSH/SSH.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
namespace Fake.Net

open System
open Fake.Core

[<RequireQualifiedAccess>]
/// Contains a task which allows to perform SSH operations
module SSH =

/// The SSH parameter type.
type SSHParams =
{ /// Path of the scp.exe
ToolPath : string
/// Path of the private key file (optional)
PrivateKeyPath : string
/// remote User
RemoteUser : string
RemoteHost : string
RemotePort : string
}

/// The SSH default parameters
let SSHDefaults : SSHParams =
{ ToolPath = if Environment.isMono then "ssh" else "ssh.exe"
RemoteUser = "fake"
RemoteHost = "localhost"
RemotePort = "22"
PrivateKeyPath = null
}

let private getTarget sshParams =
match sshParams.RemotePort with
| "22" -> $"%s{sshParams.RemoteUser}@%s{sshParams.RemoteHost}"
| _ -> $"%s{sshParams.RemoteUser}@%s{sshParams.RemoteHost}:%s{sshParams.RemotePort}"

let private getPrivateKey privateKeyPath =
if String.IsNullOrEmpty privateKeyPath then "" else $"-i \"%s{privateKeyPath}\""

let buildArguments sshParams command =
let target = sshParams |> getTarget
let privateKey = sshParams.PrivateKeyPath |> getPrivateKey
$"%s{privateKey} %s{target} %s{Args.toWindowsCommandLine [command]}" |> String.trim

/// Performs a command via SSH.
/// ## Parameters
///
/// - `setParams` - Function used to manipulate the default SSHParams value.
/// - `command` - The target path. Can be something like user@host:directory/TargetFile or a local path.
///
/// ## Sample
///
/// SSH (fun p -> { p with ToolPath = "tools/ssh.exe" }) command
let SSH setParams command =
let (sshParams : SSHParams) = setParams SSHDefaults
let target = sshParams |> getTarget
let args = buildArguments sshParams command

Trace.tracefn $"%s{sshParams.ToolPath} %s{args}"

let result = CreateProcess.fromRawCommandLine sshParams.ToolPath args
|> CreateProcess.withTimeout(TimeSpan.MaxValue)
|> Proc.run
if result.ExitCode <> 0 then failwithf $"Error during SSH. Target: %s{target} Command: %s{command}"
4 changes: 4 additions & 0 deletions src/app/Fake.Net.SSH/paket.references
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
group netcore

FSharp.Core
NETStandard.Library
3 changes: 3 additions & 0 deletions src/legacy/FakeLib/FakeLib.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,9 @@
<Compile Include="..\..\app\Fake.Net.Http\Http.fs">
<Link>Fake.Net.Http/Http.fs</Link>
</Compile>
<Compile Include="..\..\app\Fake.Net.SSH\SSH.fs">
<Link>Fake.Net.SSH/SSH.fs</Link>
</Compile>
<Compile Include="..\..\app\Fake.Core.Xml\Xml.fs">
<Link>Fake.Core.Xml/Xml.fs</Link>
</Compile>
Expand Down
8 changes: 4 additions & 4 deletions src/legacy/FakeLib/SSHHelper.fs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
[<AutoOpen>]
[<System.Obsolete("This API is obsolete. There is no alternative in FAKE 5 yet. You can help by porting this module.")>]
[<System.Obsolete("Use the Fake.Net.SSH module instead.")>]
/// Conatins a task which allows to perform SSH operations
module Fake.SSHHelper

/// The SSH parameter type.
[<CLIMutable>]
[<System.Obsolete("This API is obsolete. There is no alternative in FAKE 5 yet. You can help by porting this module.")>]
[<System.Obsolete("Use the Fake.Net.SSH module instead.")>]
type SSHParams =
{ /// Path of the scp.exe
ToolPath : string
Expand All @@ -19,7 +19,7 @@ type SSHParams =


/// The SSH default parameters
[<System.Obsolete("This API is obsolete. There is no alternative in FAKE 5 yet. You can help by porting this module.")>]
[<System.Obsolete("Use the Fake.Net.SSH module instead.")>]
let SSHDefaults : SSHParams =
{ ToolPath = if isMono then "ssh" else "ssh.exe"
RemoteUser = "fake"
Expand All @@ -37,7 +37,7 @@ let SSHDefaults : SSHParams =
/// ## Sample
///
/// SSH (fun p -> { p with ToolPath = "tools/ssh.exe" }) command
[<System.Obsolete("This API is obsolete. There is no alternative in FAKE 5 yet. You can help by porting this module.")>]
[<System.Obsolete("Use the Fake.Net.SSH module instead.")>]
let SSH setParams command =
let (p : SSHParams) = setParams SSHDefaults
let target =
Expand Down
2 changes: 2 additions & 0 deletions src/test/Fake.Core.UnitTests/Fake.Core.UnitTests.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<ProjectReference Include="..\..\app\Fake.DotNet.Testing.VSTest\Fake.DotNet.Testing.VSTest.fsproj" />
<ProjectReference Include="..\..\app\Fake.IO.Zip\Fake.IO.Zip.fsproj" />
<ProjectReference Include="..\..\app\Fake.IO.FileSystem\Fake.IO.FileSystem.fsproj" />
<ProjectReference Include="..\..\app\Fake.Net.SSH\Fake.Net.SSH.fsproj" />
<ProjectReference Include="..\..\app\Fake.Testing.Fixie\Fake.Testing.Fixie.fsproj" />
<ProjectReference Include="..\..\app\Fake.Tools.GitVersion\Fake.Tools.GitVersion.fsproj" />
<ProjectReference Include="..\..\app\Fake.Tools.Git\Fake.Tools.Git.fsproj" />
Expand Down Expand Up @@ -76,6 +77,7 @@
<Compile Include="Fake.Core.Context.fs" />
<Compile Include="Fake.Core.FakeVar.fs" />
<Compile Include="Fake.Runtime.fs" />
<Compile Include="Fake.Net.SSH.fs" />
<Compile Include="Fake.Tools.GitVersion.fs" />
<Compile Include="Fake.Tools.Octo.fs" />
<Compile Include="Fake.Sql.SqlPackage.fs" />
Expand Down
44 changes: 44 additions & 0 deletions src/test/Fake.Core.UnitTests/Fake.Net.SSH.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
module Fake.Net.SSHTests

open Expecto
open Fake.Net

[<Tests>]
let tests =
testList "Fake.Net.SSH.Tests" [
testCase "Test all arguments are mapped correctly" <| fun _ ->
let args: SSH.SSHParams =
{ ToolPath = "ssh"
RemoteUser = "fake-user"
RemoteHost = "localhost"
RemotePort = "22"
PrivateKeyPath = "private-key-path" }
let sshCommand = "pwd"
let cmd = SSH.buildArguments args sshCommand

Expect.equal cmd "-i \"private-key-path\" fake-user@localhost pwd" "expected proper arguments formatting"

testCase "Test ssh target is mapped correctly when a custom port is used" <| fun _ ->
let args: SSH.SSHParams =
{ ToolPath = "ssh"
RemoteUser = "fake-user"
RemoteHost = "localhost"
RemotePort = "2222"
PrivateKeyPath = null }
let sshCommand = "pwd"
let cmd = SSH.buildArguments args sshCommand

Expect.equal cmd "fake-user@localhost:2222 pwd" "expected proper arguments formatting"

testCase "Test PrivateKeyPath is mapped correctly when it's empty" <| fun _ ->
let args: SSH.SSHParams =
{ ToolPath = "ssh"
RemoteUser = "fake-user"
RemoteHost = "localhost"
RemotePort = "22"
PrivateKeyPath = null }
let sshCommand = "pwd"
let cmd = SSH.buildArguments args sshCommand

Expect.equal cmd "fake-user@localhost pwd" "expected proper arguments formatting"
]

0 comments on commit ec799b9

Please sign in to comment.