https://github.com/zhongwm/cable
Functional, Practical, a scala ssh library
https://github.com/zhongwm/cable
scala scala-ssh scala-ssh-library ssh-config-scala ssh-proxying zio zio-ssh
Last synced: 5 months ago
JSON representation
Functional, Practical, a scala ssh library
- Host: GitHub
- URL: https://github.com/zhongwm/cable
- Owner: zhongwm
- Created: 2020-10-03T06:28:12.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2021-04-17T03:12:28.000Z (about 5 years ago)
- Last Synced: 2023-07-04T12:41:50.326Z (almost 3 years ago)
- Topics: scala, scala-ssh, scala-ssh-library, ssh-config-scala, ssh-proxying, zio, zio-ssh
- Language: Scala
- Homepage: https://github.com/zhongwm/cable
- Size: 411 KB
- Stars: 35
- Watchers: 4
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
[comment]: <> ([![Release Artifacts][Badge-MavenCentralReleases]][Link-MavenCentralReleases])
[comment]: <> ([![Badge-Scaladoc]][Link-Scaladoc])
# Cable - scala ssh library
## A SSH client lib that is Functional, Monadic
It's scala, It's purely functional, monadic.
## Practical, Functionality rich
Cable is functionality-rich, task-centric, succinct, handy.
Cable Supports ssh proxying, jumping over networks, tasks chaining.
We support $HOME/.ssh config as well as the global ssh client config.
#### Installation
```scala
libraryDependencies += "io.github.zhongwm" %% "cable" % "0.4.1"
```
### Supports ssh proxying, in a monadic way!
Your host behind a bastion machine? You have a series of remote tasks to deal with? no problem.
And connections are reused by multiple tasks for the same machine.
A DSL to represent composite ssh tasks.
#### Simple ssh task
```scala
import cable.zssh.TypeDef._
import HostConnS._
import cable.zssh.Zssh._
val simpleTask =
Action("192.168.99.100", password = Some("password"), action = scriptIO("sleep 5; ls /"))
```
Most of the parameters can be omitted only the hostname or address (the first parameter) is
required, We can use a private key instead of password, it can be your default .ssh rsa ssh key. Cable
will read your ssh key from that file and use that key for authentication.
#### Simple ssh task with multiple tasks on a same host or connection.
```scala
val simpleData =
Action(
"192.168.99.100"
action = scriptIO("hostname") <&>
scpUploadIO("build.sbt") <&
scpDownloadIO("/etc/issue")
)
```
#### Multiple ssh tasks example
To get multiple tasks on different hosts executed one after another, chain them up using `+:`.
```scala
val simpleListTasks =
Action("192.168.99.100", Some(privateKey), action = scriptIO("cat /etc/issue")) +:
Action("192.168.99.100", port = Some(2023), username=Some("user"), password=("password"), scpDownloadIO("/etc/issue"))
```
#### Nested ssh tasks example
With nested ssh tasks composing, parent level acts as the jumper host for the child tasks, also
parent level tasks get gets executed before the latter.
```scala
val simpleNestedTasks = Parental(
JustConnect("192.168.99.100", username=Some("user"), password=Some("password")),
Action("192.168.99.100" password = Some("password"), action = scpUploadIO("build.sbt"))
)
```
#### Compound example
```scala
val compoundTasks =
JustConnect("192.168.99.100", 2022, "user", "password") +:
Parental(
JustConnect("192.168.99.100", 2022, "user", "password" ),
Action("192.168.99.100", 2022, "user", "password", scriptIO("hostname")) +:
Action("192.168.99.100", 2022, "user", "password", scpUploadIO("build.sbt"))
) +:
Action("192.168.99.100", 2023, "user", "password", scpDownloadIO("/etc/issue"))
```
### Running
Tap on `run` to fire task execution. Result types are inferred and reflecting the task composition
structure.
```scala
val nestedResult = simpleNestedTasks.run() // Inferred type: NestedC[Unit, (Int, (Chunk[String], Chunk[String]))]
val listResult = simpleListTasks.run() // Inferred type: (Int, (Chunk[String], Chunk[String])) +|: (Int, (Chunk[String], Chunk[String]))
```
### Resource Safe
As we can see in the previous sample code, we don't need to concern about connections' management, yet it's safely managed.
Connections are guaranteed to be released correctly
#### Docs
[Documentation](wiki/Contents.md)
[To get started](src/test/scala/cable/zssh/ExecSpec.scala)
## Full Support for ZIO programming
Full support for ZIO composition, ready to be embedded into ZIO project,
compatible with ZIO ecosystem.
```scala
val action = {
scriptIO("hostname") <&>
scpUploadIO("build.sbt") <&
scpDownloadIO("/etc/issue")
}
val jumperLayer = Zssh.sessionL("192.168.99.100", 2022, username = Some("test"), password = Some("test"))
val jumpedLayer =
Zssh.jumpSessionL(jumperLayer, "192.168.99.100", 2023, Some("test"), Some("test"))
val layer2 =
((jumperLayer ++ Blocking.live) >>> Zssh.jumpAddressLayer("192.168.99.100", 2023)) ++ Blocking.live
val layer3 = layer2 >>> Zssh.jumpSshConnL(Some("test"), Some("test"))
val layer4 = (Zssh.clientLayer ++ layer3 ++ Blocking.live) >>> Zssh.sessionL
```
```scala
private val process = for {
connJump <- Zssh.make(
Left("192.168.99.100", 2022),
username = Some("test"),
password = Some("test")
)
rst <- connJump.sessionM { outerSession =>
Zssh.jumpTo("192.168.99.100", 2023)(outerSession) >>= { fwd =>
val conn = Zssh(Right(fwd.getBoundAddress), Some("test"), password = Some("test"))
conn.sessionM { innerSession =>
Zssh.script("hostname")(innerSession) <&>
Zssh.scpUpload("build.sbt")(innerSession) <&
Zssh.scpDownload("/etc/issue")(innerSession)
}
}
}
_ <- putStrLn(rst._1._2._1.mkString)
_ <- putStrLn(rst._1._2._2.mkString)
xc <- ZIO.succeed {
zio.ExitCode(rst._1._1)
}
} yield xc
```
## Efficient, fast
Based on mina-sshd-netty
## P.S.
This project is greatly inspired by a famous python project [ansible](https://ansible.com), which is
a very famous project in devops. This project strives to join the functional world and the devops
world in the field of remote host related tasks. Not all of them, not all of ansible, but in some way.
[comment]: <> ([Link-MavenCentralReleases]: https://repo1.maven.org/maven2/io/github/zhongwm/cable_2.13/ "Maven Central Releases")
[comment]: <> ([Badge-MavenCentralReleases]: https://maven-badges.herokuapp.com/maven-central/io.github.zhongwm/cable_2.13/badge.svg "Maven Central Release")
[comment]: <> ([Badge-Scaladoc]: https://javadoc-badge.appspot.com/io.github.zhongwm/cable_2.13.svg?label=scaladoc "Scaladoc")
[comment]: <> ([Link-Scaladoc]: https://javadoc.io/doc/io.github.zhongwm/cable_2.13/latest/cable/index.html)