mirror of
https://github.com/veeso/termscp.git
synced 2025-12-06 17:15:35 -08:00
feat: kube protocol support (#267)
This commit is contained in:
committed by
GitHub
parent
cf529c1678
commit
f757336d75
@@ -42,6 +42,7 @@ Released on ??
|
||||
|
||||
- [Issue 226](https://github.com/veeso/termscp/issues/226): Use ssh-agent
|
||||
- [Issue 241](https://github.com/veeso/termscp/issues/241): Jump to next entry after select
|
||||
- [Issue 242](https://github.com/veeso/termscp/issues/242): Added `Kube` protocol support
|
||||
- [Issue 255](https://github.com/veeso/termscp/issues/255): New keybindings `Ctrl + Shift + A` to deselect all files
|
||||
- [Issue 256](https://github.com/veeso/termscp/issues/256): Filter files in current folder. You can now filter files by pressing `/`. Both wildmatch and regex are accepted to filter files.
|
||||
- [Issue 257](https://github.com/veeso/termscp/issues/257): CLI remote args cannot handle '@' in the username
|
||||
|
||||
464
Cargo.lock
generated
464
Cargo.lock
generated
@@ -263,7 +263,7 @@ dependencies = [
|
||||
"rust-ini",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"time 0.3.36",
|
||||
"time",
|
||||
"url",
|
||||
]
|
||||
|
||||
@@ -299,9 +299,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.21.2"
|
||||
version = "0.21.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d"
|
||||
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
@@ -454,17 +454,17 @@ checksum = "77e53693616d3075149f4ead59bdeecd204ac6b8192d8969757601b74bddf00f"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.26"
|
||||
version = "0.4.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5"
|
||||
checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
"num-traits",
|
||||
"time 0.1.45",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
"winapi 0.3.9",
|
||||
"windows-targets 0.52.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -591,7 +591,7 @@ dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"crossterm_winapi",
|
||||
"libc",
|
||||
"mio 0.8.8",
|
||||
"mio 0.8.11",
|
||||
"parking_lot 0.12.1",
|
||||
"signal-hook",
|
||||
"signal-hook-mio",
|
||||
@@ -607,7 +607,7 @@ dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"crossterm_winapi",
|
||||
"libc",
|
||||
"mio 0.8.8",
|
||||
"mio 0.8.11",
|
||||
"parking_lot 0.12.1",
|
||||
"signal-hook",
|
||||
"signal-hook-mio",
|
||||
@@ -689,6 +689,12 @@ dependencies = [
|
||||
"parking_lot_core 0.9.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "data-encoding"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2"
|
||||
|
||||
[[package]]
|
||||
name = "dbus"
|
||||
version = "0.9.7"
|
||||
@@ -1181,7 +1187,7 @@ checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1230,6 +1236,30 @@ version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
|
||||
|
||||
[[package]]
|
||||
name = "headers"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "322106e6bd0cba2d5ead589ddb8150a13d7c4217cf80d7c4f682ca994ccc6aa9"
|
||||
dependencies = [
|
||||
"base64 0.21.7",
|
||||
"bytes",
|
||||
"headers-core",
|
||||
"http 1.1.0",
|
||||
"httpdate",
|
||||
"mime",
|
||||
"sha1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "headers-core"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4"
|
||||
dependencies = [
|
||||
"http 1.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.1"
|
||||
@@ -1299,9 +1329,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "1.0.0"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea"
|
||||
checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
@@ -1326,7 +1356,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"http 1.0.0",
|
||||
"http 1.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1337,7 +1367,7 @@ checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-util",
|
||||
"http 1.0.0",
|
||||
"http 1.1.0",
|
||||
"http-body 1.0.0",
|
||||
"pin-project-lite",
|
||||
]
|
||||
@@ -1387,7 +1417,7 @@ dependencies = [
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
"futures-util",
|
||||
"http 1.0.0",
|
||||
"http 1.1.0",
|
||||
"http-body 1.0.0",
|
||||
"httparse",
|
||||
"itoa",
|
||||
@@ -1397,6 +1427,26 @@ dependencies = [
|
||||
"want",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-http-proxy"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d06dbdfbacf34d996c6fb540a71a684a7aae9056c71951163af8a8a4c07b9a4"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-util",
|
||||
"headers",
|
||||
"http 1.1.0",
|
||||
"hyper 1.4.0",
|
||||
"hyper-rustls",
|
||||
"hyper-util",
|
||||
"pin-project-lite",
|
||||
"rustls-native-certs",
|
||||
"tokio",
|
||||
"tokio-rustls",
|
||||
"tower-service",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-rustls"
|
||||
version = "0.27.2"
|
||||
@@ -1404,10 +1454,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"http 1.0.0",
|
||||
"http 1.1.0",
|
||||
"hyper 1.4.0",
|
||||
"hyper-util",
|
||||
"log",
|
||||
"rustls 0.23.11",
|
||||
"rustls-native-certs",
|
||||
"rustls-pki-types",
|
||||
"tokio",
|
||||
"tokio-rustls",
|
||||
@@ -1415,6 +1467,19 @@ dependencies = [
|
||||
"webpki-roots 0.26.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-timeout"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793"
|
||||
dependencies = [
|
||||
"hyper 1.4.0",
|
||||
"hyper-util",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
"tower-service",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-tls"
|
||||
version = "0.5.0"
|
||||
@@ -1437,7 +1502,7 @@ dependencies = [
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
"futures-util",
|
||||
"http 1.0.0",
|
||||
"http 1.1.0",
|
||||
"http-body 1.0.0",
|
||||
"hyper 1.4.0",
|
||||
"pin-project-lite",
|
||||
@@ -1618,6 +1683,34 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jsonpath-rust"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19d8fe85bd70ff715f31ce8c739194b423d79811a19602115d611a3ec85d6200"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"once_cell",
|
||||
"pest",
|
||||
"pest_derive",
|
||||
"regex",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "k8s-openapi"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19501afb943ae5806548bc3ebd7f3374153ca057a38f480ef30adfde5ef09755"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"chrono",
|
||||
"serde",
|
||||
"serde-value",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kernel32-sys"
|
||||
version = "0.2.2"
|
||||
@@ -1642,6 +1735,72 @@ dependencies = [
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kube"
|
||||
version = "0.92.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "231c5a5392d9e2a9b0d923199760d3f1dd73b95288f2871d16c7c90ba4954506"
|
||||
dependencies = [
|
||||
"k8s-openapi",
|
||||
"kube-client",
|
||||
"kube-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kube-client"
|
||||
version = "0.92.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f4bf54135062ff60e2a0dfb3e7a9c8e931fc4a535b4d6bd561e0a1371321c61"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"bytes",
|
||||
"chrono",
|
||||
"either",
|
||||
"futures",
|
||||
"home",
|
||||
"http 1.1.0",
|
||||
"http-body 1.0.0",
|
||||
"http-body-util",
|
||||
"hyper 1.4.0",
|
||||
"hyper-http-proxy",
|
||||
"hyper-rustls",
|
||||
"hyper-timeout",
|
||||
"hyper-util",
|
||||
"jsonpath-rust",
|
||||
"k8s-openapi",
|
||||
"kube-core",
|
||||
"pem",
|
||||
"rand",
|
||||
"rustls 0.23.11",
|
||||
"rustls-pemfile",
|
||||
"secrecy",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_yaml",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tokio-tungstenite",
|
||||
"tokio-util",
|
||||
"tower",
|
||||
"tower-http",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kube-core"
|
||||
version = "0.92.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40fb9bd8141cbc0fe6b0d9112d371679b4cb607b45c31dd68d92e40864a12975"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"form_urlencoded",
|
||||
"http 1.1.0",
|
||||
"k8s-openapi",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy-regex"
|
||||
version = "2.5.0"
|
||||
@@ -1789,7 +1948,7 @@ dependencies = [
|
||||
"dirs-next",
|
||||
"objc-foundation",
|
||||
"objc_id",
|
||||
"time 0.3.36",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1897,13 +2056,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.8"
|
||||
version = "0.8.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
|
||||
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"wasi",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
@@ -2237,6 +2396,15 @@ version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
||||
|
||||
[[package]]
|
||||
name = "ordered-float"
|
||||
version = "2.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ordered-multimap"
|
||||
version = "0.6.0"
|
||||
@@ -2358,12 +2526,67 @@ dependencies = [
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pem"
|
||||
version = "3.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
|
||||
|
||||
[[package]]
|
||||
name = "pest"
|
||||
version = "2.7.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"thiserror",
|
||||
"ucd-trie",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_derive"
|
||||
version = "2.7.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_generator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_generator"
|
||||
version = "2.7.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_meta",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.52",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_meta"
|
||||
version = "2.7.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"pest",
|
||||
"sha2 0.10.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "1.1.5"
|
||||
@@ -2706,6 +2929,27 @@ dependencies = [
|
||||
"users",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "remotefs-kube"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d6fea485470d4504bb9d7572e2fdee09866b3031331cc49e0eca2e2e31975d9"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"futures-util",
|
||||
"k8s-openapi",
|
||||
"kube",
|
||||
"lazy-regex 3.1.0",
|
||||
"log",
|
||||
"path-slash 0.2.1",
|
||||
"remotefs",
|
||||
"tar",
|
||||
"tempfile",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "remotefs-smb"
|
||||
version = "0.2.0"
|
||||
@@ -2744,7 +2988,7 @@ checksum = "e88503e1cd53067ab639150625718bb8d88e6bcd1e165205de0d941beca66bde"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"bytestring",
|
||||
"http 1.0.0",
|
||||
"http 1.1.0",
|
||||
"httpdate",
|
||||
"indexmap 2.2.5",
|
||||
"log",
|
||||
@@ -2754,7 +2998,7 @@ dependencies = [
|
||||
"remotefs",
|
||||
"rustydav",
|
||||
"thiserror",
|
||||
"time 0.3.36",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2763,7 +3007,7 @@ version = "0.11.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55"
|
||||
dependencies = [
|
||||
"base64 0.21.2",
|
||||
"base64 0.21.7",
|
||||
"bytes",
|
||||
"encoding_rs",
|
||||
"futures-core",
|
||||
@@ -2805,7 +3049,7 @@ dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"http 1.0.0",
|
||||
"http 1.1.0",
|
||||
"http-body 1.0.0",
|
||||
"http-body-util",
|
||||
"hyper 1.4.0",
|
||||
@@ -2893,7 +3137,7 @@ dependencies = [
|
||||
"attohttpc",
|
||||
"aws-creds",
|
||||
"aws-region",
|
||||
"base64 0.21.2",
|
||||
"base64 0.21.7",
|
||||
"bytes",
|
||||
"cfg-if 1.0.0",
|
||||
"hex",
|
||||
@@ -2909,7 +3153,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"sha2 0.10.7",
|
||||
"thiserror",
|
||||
"time 0.3.36",
|
||||
"time",
|
||||
"url",
|
||||
]
|
||||
|
||||
@@ -2966,6 +3210,7 @@ version = "0.23.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4828ea528154ae444e5a642dbb7d5623354030dc9822b83fd9bb79683c7399d0"
|
||||
dependencies = [
|
||||
"log",
|
||||
"once_cell",
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
@@ -2974,6 +3219,19 @@ dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-native-certs"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a88d6d420651b496bdd98684116959239430022a115c1240e6c3993be0b15fba"
|
||||
dependencies = [
|
||||
"openssl-probe",
|
||||
"rustls-pemfile",
|
||||
"rustls-pki-types",
|
||||
"schannel",
|
||||
"security-framework",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-pemfile"
|
||||
version = "2.1.2"
|
||||
@@ -3066,6 +3324,16 @@ dependencies = [
|
||||
"untrusted",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "secrecy"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "secret-service"
|
||||
version = "3.0.1"
|
||||
@@ -3158,6 +3426,16 @@ dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde-value"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c"
|
||||
dependencies = [
|
||||
"ordered-float",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.197"
|
||||
@@ -3212,6 +3490,19 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_yaml"
|
||||
version = "0.9.34+deprecated"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
|
||||
dependencies = [
|
||||
"indexmap 2.2.5",
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
"unsafe-libyaml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serial_test"
|
||||
version = "3.0.0"
|
||||
@@ -3289,7 +3580,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"mio 0.8.8",
|
||||
"mio 0.8.11",
|
||||
"signal-hook",
|
||||
]
|
||||
|
||||
@@ -3326,7 +3617,7 @@ checksum = "acee08041c5de3d5048c8b3f6f13fafb3026b24ba43c6a695a0c76179b844369"
|
||||
dependencies = [
|
||||
"log",
|
||||
"termcolor",
|
||||
"time 0.3.36",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3531,7 +3822,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "termscp"
|
||||
version = "0.13.0"
|
||||
version = "0.14.0"
|
||||
dependencies = [
|
||||
"argh",
|
||||
"bitflags 2.4.2",
|
||||
@@ -3557,6 +3848,7 @@ dependencies = [
|
||||
"remotefs",
|
||||
"remotefs-aws-s3",
|
||||
"remotefs-ftp",
|
||||
"remotefs-kube",
|
||||
"remotefs-smb",
|
||||
"remotefs-ssh",
|
||||
"remotefs-webdav",
|
||||
@@ -3568,6 +3860,7 @@ dependencies = [
|
||||
"ssh2-config",
|
||||
"tempfile",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"toml",
|
||||
"tui-realm-stdlib",
|
||||
"tuirealm",
|
||||
@@ -3620,17 +3913,6 @@ dependencies = [
|
||||
"digest 0.9.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi 0.10.0+wasi-snapshot-preview1",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.36"
|
||||
@@ -3690,21 +3972,33 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.29.1"
|
||||
version = "1.38.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da"
|
||||
checksum = "eb2caba9f80616f438e09748d5acda951967e1ea58508ef53d9c6402485a46df"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"backtrace",
|
||||
"bytes",
|
||||
"libc",
|
||||
"mio 0.8.8",
|
||||
"mio 0.8.11",
|
||||
"num_cpus",
|
||||
"pin-project-lite",
|
||||
"socket2 0.4.9",
|
||||
"signal-hook-registry",
|
||||
"socket2 0.5.7",
|
||||
"tokio-macros",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-macros"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.52",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-native-tls"
|
||||
version = "0.3.1"
|
||||
@@ -3726,6 +4020,18 @@ dependencies = [
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-tungstenite"
|
||||
version = "0.23.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c6989540ced10490aaf14e6bad2e3d33728a2813310a0c71d1574304c49631cd"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"log",
|
||||
"tokio",
|
||||
"tungstenite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.7.8"
|
||||
@@ -3796,8 +4102,29 @@ dependencies = [
|
||||
"pin-project",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower-http"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5"
|
||||
dependencies = [
|
||||
"base64 0.21.7",
|
||||
"bitflags 2.4.2",
|
||||
"bytes",
|
||||
"http 1.1.0",
|
||||
"http-body 1.0.0",
|
||||
"http-body-util",
|
||||
"mime",
|
||||
"pin-project-lite",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3819,6 +4146,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"log",
|
||||
"pin-project-lite",
|
||||
"tracing-attributes",
|
||||
"tracing-core",
|
||||
@@ -3900,12 +4228,36 @@ dependencies = [
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tungstenite"
|
||||
version = "0.23.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e2e2ce1e47ed2994fd43b04c8f618008d4cabdd5ee34027cf14f9d918edd9c8"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"bytes",
|
||||
"data-encoding",
|
||||
"http 1.1.0",
|
||||
"httparse",
|
||||
"log",
|
||||
"rand",
|
||||
"sha1",
|
||||
"thiserror",
|
||||
"utf-8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
|
||||
|
||||
[[package]]
|
||||
name = "ucd-trie"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9"
|
||||
|
||||
[[package]]
|
||||
name = "uds_windows"
|
||||
version = "1.0.2"
|
||||
@@ -3959,6 +4311,12 @@ version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
|
||||
|
||||
[[package]]
|
||||
name = "unsafe-libyaml"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.9.0"
|
||||
@@ -3992,6 +4350,12 @@ dependencies = [
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utf-8"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.15"
|
||||
@@ -4035,12 +4399,6 @@ dependencies = [
|
||||
"try-lock",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
@@ -4635,7 +4993,7 @@ dependencies = [
|
||||
"indexmap 2.2.5",
|
||||
"memchr",
|
||||
"thiserror",
|
||||
"time 0.3.36",
|
||||
"time",
|
||||
"zopfli",
|
||||
]
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
authors = ["Christian Visintin <christian.visintin@veeso.dev>"]
|
||||
categories = ["command-line-utilities"]
|
||||
description = "termscp is a feature rich terminal file transfer and explorer with support for SCP/SFTP/FTP/S3"
|
||||
description = "termscp is a feature rich terminal file transfer and explorer with support for SCP/SFTP/FTP/Kube/S3/WebDAV"
|
||||
edition = "2021"
|
||||
homepage = "https://termscp.veeso.dev"
|
||||
include = ["src/**/*", "LICENSE", "README.md", "CHANGELOG.md"]
|
||||
@@ -16,7 +16,7 @@ license = "MIT"
|
||||
name = "termscp"
|
||||
readme = "README.md"
|
||||
repository = "https://github.com/veeso/termscp"
|
||||
version = "0.13.0"
|
||||
version = "0.14.0"
|
||||
|
||||
[package.metadata.rpm]
|
||||
package = "termscp"
|
||||
@@ -61,6 +61,7 @@ remotefs-aws-s3 = { version = "^0.2.4", default-features = false, features = [
|
||||
"find",
|
||||
"rustls",
|
||||
] }
|
||||
remotefs-kube = "0.2"
|
||||
remotefs-webdav = "^0.1.1"
|
||||
rpassword = "^7.0"
|
||||
self_update = { version = "^0.41", default-features = false, features = [
|
||||
@@ -75,6 +76,7 @@ simplelog = "^0.12"
|
||||
ssh2-config = "^0.2"
|
||||
tempfile = "^3.4"
|
||||
thiserror = "^1"
|
||||
tokio = { version = "1", features = ["rt"] }
|
||||
toml = "^0.8"
|
||||
tui-realm-stdlib = "^1.3.1"
|
||||
tuirealm = "^1.9.1"
|
||||
|
||||
@@ -127,7 +127,7 @@
|
||||
|
||||
## About termscp 🖥
|
||||
|
||||
Termscp is a feature rich terminal file transfer and explorer, with support for SCP/SFTP/FTP/S3. So basically is a terminal utility with an TUI to connect to a remote server to retrieve and upload files and to interact with the local file system. It is **Linux**, **MacOS**, **FreeBSD**, **NetBSD** and **Windows** compatible.
|
||||
Termscp is a feature rich terminal file transfer and explorer, with support for SCP/SFTP/FTP/Kube/S3/WebDAV. So basically is a terminal utility with an TUI to connect to a remote server to retrieve and upload files and to interact with the local file system. It is **Linux**, **MacOS**, **FreeBSD**, **NetBSD** and **Windows** compatible.
|
||||
|
||||

|
||||
|
||||
@@ -139,6 +139,7 @@ Termscp is a feature rich terminal file transfer and explorer, with support for
|
||||
- **SFTP**
|
||||
- **SCP**
|
||||
- **FTP** and **FTPS**
|
||||
- **Kube**
|
||||
- **S3**
|
||||
- **SMB**
|
||||
- **WebDAV**
|
||||
@@ -277,6 +278,7 @@ termscp is powered by these awesome projects:
|
||||
- [crossterm](https://github.com/crossterm-rs/crossterm)
|
||||
- [edit](https://github.com/milkey-mouse/edit)
|
||||
- [keyring-rs](https://github.com/hwchen/keyring-rs)
|
||||
- [kube](https://github.com/kube-rs/kube)
|
||||
- [open-rs](https://github.com/Byron/open-rs)
|
||||
- [pavao](https://github.com/veeso/pavao)
|
||||
- [remotefs](https://github.com/veeso/remotefs-rs)
|
||||
|
||||
4
dist/build/freebsd.sh
vendored
4
dist/build/freebsd.sh
vendored
@@ -34,9 +34,9 @@ rm manifest
|
||||
echo -e "name: \"termscp\"" > manifest
|
||||
echo -e "version: $VERSION" >> manifest
|
||||
echo -e "origin: veeso/termscp" >> manifest
|
||||
echo -e "comment: \"A feature rich terminal UI file transfer and explorer with support for SCP/SFTP/FTP/S3\"" >> manifest
|
||||
echo -e "comment: \"A feature rich terminal UI file transfer and explorer with support for SCP/SFTP/FTP/Kube/S3/WebDAV\"" >> manifest
|
||||
echo -e "desc: <<EOD\n\
|
||||
A feature rich terminal UI file transfer and explorer with support for SCP/SFTP/FTP/S3\n\
|
||||
A feature rich terminal UI file transfer and explorer with support for SCP/SFTP/FTP/Kube/S3/WebDAV\n\
|
||||
EOD\n\
|
||||
arch: \"amd64\"\n\
|
||||
www: \"https://termscp.veeso.dev/termscp/\"\n\
|
||||
|
||||
@@ -132,7 +132,7 @@
|
||||
|
||||
## Über termscp 🖥
|
||||
|
||||
Termscp ist ein funktionsreicher Terminal-Dateitransfer und Explorer mit Unterstützung für SCP/SFTP/FTP/S3. Im Grunde handelt es sich also um ein Terminal-Dienstprogramm mit einer TUI, um eine Verbindung zu einem Remote-Server herzustellen, um Dateien abzurufen und hochzuladen und mit dem lokalen Dateisystem zu interagieren. Es ist **Linux**, **MacOS**, **FreeBSD** und **Windows** kompatibel.
|
||||
Termscp ist ein funktionsreicher Terminal-Dateitransfer und Explorer mit Unterstützung für SCP/SFTP/FTP/Kube/S3/WebDAV. Im Grunde handelt es sich also um ein Terminal-Dienstprogramm mit einer TUI, um eine Verbindung zu einem Remote-Server herzustellen, um Dateien abzurufen und hochzuladen und mit dem lokalen Dateisystem zu interagieren. Es ist **Linux**, **MacOS**, **FreeBSD** und **Windows** kompatibel.
|
||||
|
||||

|
||||
|
||||
@@ -144,6 +144,7 @@ Termscp ist ein funktionsreicher Terminal-Dateitransfer und Explorer mit Unterst
|
||||
- **SFTP**
|
||||
- **SCP**
|
||||
- **FTP** und **FTPS**
|
||||
- **Kube**
|
||||
- **S3**
|
||||
- **SMB**
|
||||
- **WebDAV**
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
- [Verwendung ❓](#verwendung-)
|
||||
- [Adressargument 🌎](#adressargument-)
|
||||
- [AWS S3 Adressargument](#aws-s3-adressargument)
|
||||
- [Kube-Adressargument](#kube-adressargument)
|
||||
- [SMB Adressargument](#smb-adressargument)
|
||||
- [Wie das Passwort bereitgestellt werden kann 🔐](#wie-das-passwort-bereitgestellt-werden-kann-)
|
||||
- [Unterbefehle](#unterbefehle)
|
||||
@@ -127,6 +128,14 @@ z.B.
|
||||
s3://buckethead@eu-central-1:default:/assets
|
||||
```
|
||||
|
||||
#### Kube-Adressargument
|
||||
|
||||
Falls Sie eine Verbindung zu Kube herstellen möchten, verwenden Sie die folgende Syntax
|
||||
|
||||
```txt
|
||||
kube://<container>@<pod></path>
|
||||
```
|
||||
|
||||
#### SMB Adressargument
|
||||
|
||||
SMB hat eine andere Syntax für CLI-Adressargumente, die je nach System unterschiedlich ist:
|
||||
|
||||
@@ -132,7 +132,7 @@
|
||||
|
||||
## Sobre termscp 🖥
|
||||
|
||||
Termscp es un explorador y transferencia de archivos de terminal rico en funciones, con apoyo para SCP/SFTP/FTP/S3. Básicamente, es una utilidad de terminal con una TUI para conectarse a un servidor remoto para recuperar y cargar archivos e interactuar con el sistema de archivos local. Es compatible con **Linux**, **MacOS**, **FreeBSD** y **Windows**.
|
||||
Termscp es un explorador y transferencia de archivos de terminal rico en funciones, con apoyo para SCP/SFTP/FTP/Kube/S3/WebDAV. Básicamente, es una utilidad de terminal con una TUI para conectarse a un servidor remoto para recuperar y cargar archivos e interactuar con el sistema de archivos local. Es compatible con **Linux**, **MacOS**, **FreeBSD** y **Windows**.
|
||||
|
||||

|
||||
|
||||
@@ -144,6 +144,7 @@ Termscp es un explorador y transferencia de archivos de terminal rico en funcion
|
||||
- **SFTP**
|
||||
- **SCP**
|
||||
- **FTP** y **FTPS**
|
||||
- **Kube**
|
||||
- **S3**
|
||||
- **SMB**
|
||||
- **WebDAV**
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
- [Uso ❓](#uso-)
|
||||
- [Argumento dirección 🌎](#argumento-dirección-)
|
||||
- [Argumento dirección por AWS S3](#argumento-dirección-por-aws-s3)
|
||||
- [Argumento de dirección Kube](#argumento-de-dirección-kube)
|
||||
- [Argumento de dirección de WebDAV](#argumento-de-dirección-de-webdav)
|
||||
- [Argumento dirección por SMB](#argumento-dirección-por-smb)
|
||||
- [Cómo se puede proporcionar la contraseña 🔐](#cómo-se-puede-proporcionar-la-contraseña-)
|
||||
@@ -104,6 +105,14 @@ por ejemplo
|
||||
s3://buckethead@eu-central-1:default:/assets
|
||||
```
|
||||
|
||||
#### Argumento de dirección Kube
|
||||
|
||||
En caso de que quieras conectarte a Kube, utiliza la siguiente sintaxis
|
||||
|
||||
```txt
|
||||
kube://<container>@<pod></path>
|
||||
```
|
||||
|
||||
#### Argumento de dirección de WebDAV
|
||||
|
||||
En caso de que quieras conectarte a WebDAV utiliza la siguiente sintaxis
|
||||
|
||||
@@ -132,7 +132,7 @@
|
||||
|
||||
## À propos des termscp 🖥
|
||||
|
||||
Termscp est un file transfer et explorateur de fichiers de terminal riche en fonctionnalités, avec support pour SCP/SFTP/FTP/S3. Essentiellement c'est une utilitaire terminal avec une TUI pour se connecter à un serveur distant pour télécharger de fichiers et interagir avec le système de fichiers local. Il est compatible avec **Linux**, **MacOS**, **FreeBSD** et **Windows**.
|
||||
Termscp est un file transfer et explorateur de fichiers de terminal riche en fonctionnalités, avec support pour SCP/SFTP/FTP/Kube/S3/WebDAV. Essentiellement c'est une utilitaire terminal avec une TUI pour se connecter à un serveur distant pour télécharger de fichiers et interagir avec le système de fichiers local. Il est compatible avec **Linux**, **MacOS**, **FreeBSD** et **Windows**.
|
||||
|
||||

|
||||
|
||||
@@ -144,6 +144,7 @@ Termscp est un file transfer et explorateur de fichiers de terminal riche en fon
|
||||
- **SFTP**
|
||||
- **SCP**
|
||||
- **FTP** et **FTPS**
|
||||
- **Kube**
|
||||
- **S3**
|
||||
- **SMB**
|
||||
- **WebDAV**
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
- [Usage ❓](#usage-)
|
||||
- [Argument d'adresse 🌎](#argument-dadresse-)
|
||||
- [Argument d'adresse AWS S3](#argument-dadresse-aws-s3)
|
||||
- [Argument d'adresse Kube](#argument-dadresse-kube)
|
||||
- [Argument d'adresse WebDAV](#argument-dadresse-webdav)
|
||||
- [Argument d'adresse SMB](#argument-dadresse-smb)
|
||||
- [Comment le mot de passe peut être fourni 🔐](#comment-le-mot-de-passe-peut-être-fourni-)
|
||||
@@ -102,6 +103,14 @@ e.g.
|
||||
s3://buckethead@eu-central-1:default:/assets
|
||||
```
|
||||
|
||||
#### Argument d'adresse Kube
|
||||
|
||||
Si vous souhaitez vous connecter à Kube, utilisez la syntaxe suivante
|
||||
|
||||
```txt
|
||||
kube://<container>@<pod></path>
|
||||
```
|
||||
|
||||
#### Argument d'adresse WebDAV
|
||||
|
||||
Dans le cas où vous souhaitez vous connecter à WebDAV, utilisez la syntaxe suivante
|
||||
|
||||
@@ -132,7 +132,7 @@
|
||||
|
||||
## Riguardo a termscp 🖥
|
||||
|
||||
Termscp è un file transfer ed explorer ricco di funzionalità, con supporto a SCP/SFTP/FTP/S3. In pratica è un utility su terminale con una terminal user-interface per connettersi a server remoti per scambiare file ed interagire con il file system sia locale che remoto. È compatibile con **Linux**, **MacOS**, **FreeBSD** e **Windows**.
|
||||
Termscp è un file transfer ed explorer ricco di funzionalità, con supporto a SCP/SFTP/FTP/Kube/S3/WebDAV. In pratica è un utility su terminale con una terminal user-interface per connettersi a server remoti per scambiare file ed interagire con il file system sia locale che remoto. È compatibile con **Linux**, **MacOS**, **FreeBSD** e **Windows**.
|
||||
|
||||

|
||||
|
||||
@@ -144,6 +144,7 @@ Termscp è un file transfer ed explorer ricco di funzionalità, con supporto a S
|
||||
- **SFTP**
|
||||
- **SCP**
|
||||
- **FTP** and **FTPS**
|
||||
- **Kube**
|
||||
- **S3**
|
||||
- **SMB**
|
||||
- **WebDAV**
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
- [Argomenti da linea di comando ❓](#argomenti-da-linea-di-comando-)
|
||||
- [Argomento indirizzo 🌎](#argomento-indirizzo-)
|
||||
- [Argomento indirizzo per AWS S3](#argomento-indirizzo-per-aws-s3)
|
||||
- [Argomento indirizzo Kube](#argomento-indirizzo-kube)
|
||||
- [Argomento indirizzo per WebDAV](#argomento-indirizzo-per-webdav)
|
||||
- [Indirizzo SMB](#indirizzo-smb)
|
||||
- [Come fornire la password 🔐](#come-fornire-la-password-)
|
||||
@@ -100,6 +101,14 @@ e.g.
|
||||
s3://buckethead@eu-central-1:default:/assets
|
||||
```
|
||||
|
||||
#### Argomento indirizzo Kube
|
||||
|
||||
Nel caso tu voglia connetterti a Kube usa la seguente sintassi
|
||||
|
||||
```txt
|
||||
kube://<container>@<pod></path>
|
||||
```
|
||||
|
||||
#### Argomento indirizzo per WebDAV
|
||||
|
||||
Nel caso in cui si desideri connettersi a WebDAV utilizzare la seguente sintassi
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
- [Usage ❓](#usage-)
|
||||
- [Address argument 🌎](#address-argument-)
|
||||
- [AWS S3 address argument](#aws-s3-address-argument)
|
||||
- [Kube address argument](#kube-address-argument)
|
||||
- [WebDAV address argument](#webdav-address-argument)
|
||||
- [SMB address argument](#smb-address-argument)
|
||||
- [How Password can be provided 🔐](#how-password-can-be-provided-)
|
||||
@@ -105,6 +106,14 @@ e.g.
|
||||
s3://buckethead@eu-central-1:default:/assets
|
||||
```
|
||||
|
||||
#### Kube address argument
|
||||
|
||||
In case you want to connect to Kube use the following syntax
|
||||
|
||||
```txt
|
||||
kube://<container>@<pod></path>
|
||||
```
|
||||
|
||||
#### WebDAV address argument
|
||||
|
||||
In case you want to connect to webDAV use the following syntax
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Termscp is a feature rich terminal file transfer and explorer, with support for SCP/SFTP/FTP/S3.
|
||||
Termscp is a feature rich terminal file transfer and explorer, with support for SCP/SFTP/FTP/Kube/S3/WebDAV.
|
||||
Basically is a terminal utility with an TUI to connect to a remote server to retrieve and upload files and
|
||||
to interact with the local file system.
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@
|
||||
|
||||
## Sobre o termscp 🖥
|
||||
|
||||
Termscp é um explorador e utilitário de transferência de arquivos com uma interface de terminal, com suporte para SCP/SFTP/FTP/S3. Basicamente, é uma ferramenta de terminal com uma interface de usuário para conectar-se a um servidor remoto para baixar e enviar arquivos e interagir com o sistema de arquivos local. Ele é compatível com **Linux**, **MacOS**, **FreeBSD**, **NetBSD** e **Windows**.
|
||||
Termscp é um explorador e utilitário de transferência de arquivos com uma interface de terminal, com suporte para SCP/SFTP/FTP/Kube/S3/WebDAV. Basicamente, é uma ferramenta de terminal com uma interface de usuário para conectar-se a um servidor remoto para baixar e enviar arquivos e interagir com o sistema de arquivos local. Ele é compatível com **Linux**, **MacOS**, **FreeBSD**, **NetBSD** e **Windows**.
|
||||
|
||||

|
||||
|
||||
@@ -139,6 +139,7 @@ Termscp é um explorador e utilitário de transferência de arquivos com uma int
|
||||
- **SFTP**
|
||||
- **SCP**
|
||||
- **FTP** e **FTPS**
|
||||
- **Kube**
|
||||
- **S3**
|
||||
- **SMB**
|
||||
- **WebDAV**
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
- [Uso ❓](#uso-)
|
||||
- [Argumento de Endereço 🌎](#argumento-de-endereço-)
|
||||
- [Argumento de Endereço do AWS S3](#argumento-de-endereço-do-aws-s3)
|
||||
- [Argumento de endereço Kube](#argumento-de-endereço-kube)
|
||||
- [Argumento de Endereço do WebDAV](#argumento-de-endereço-do-webdav)
|
||||
- [Argumento de Endereço do SMB](#argumento-de-endereço-do-smb)
|
||||
- [Como a Senha Pode Ser Fornecida 🔐](#como-a-senha-pode-ser-fornecida-)
|
||||
@@ -105,6 +106,14 @@ Exemplo:
|
||||
s3://buckethead@eu-central-1:default:/assets
|
||||
```
|
||||
|
||||
#### Argumento de endereço Kube
|
||||
|
||||
Caso queira se conectar ao Kube, use a seguinte sintaxe
|
||||
|
||||
```txt
|
||||
kube://<container>@<pod></path>
|
||||
```
|
||||
|
||||
#### Argumento de Endereço do WebDAV
|
||||
|
||||
Caso você queira se conectar ao WebDAV, use a seguinte sintaxe:
|
||||
|
||||
@@ -132,7 +132,7 @@
|
||||
|
||||
## 关于 termscp 🖥
|
||||
|
||||
termscp 是一个功能丰富的终端文件浏览和传输工具,支持 SCP/SFTP/FTP/S3。 作为一个带有 TUI 的命令行工具,它可以连接到远程服务器进行文件检索和上传,并能够与本地文件系统进行交互。
|
||||
termscp 是一个功能丰富的终端文件浏览和传输工具,支持 SCP/SFTP/FTP/Kube/S3/WebDAV。 作为一个带有 TUI 的命令行工具,它可以连接到远程服务器进行文件检索和上传,并能够与本地文件系统进行交互。
|
||||
|
||||
兼容 **Linux**、**MacOS**、**FreeBSD** 和 **Windows** 操作系统。
|
||||
|
||||
@@ -146,6 +146,7 @@ termscp 是一个功能丰富的终端文件浏览和传输工具,支持 SCP/S
|
||||
- **SFTP**
|
||||
- **SCP**
|
||||
- **FTP** and **FTPS**
|
||||
- **Kube**
|
||||
- **S3**
|
||||
- **SMB**
|
||||
- **WebDAV**
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
- [用法](#用法)
|
||||
- [地址参数](#地址参数)
|
||||
- [AWS S3 地址参数](#aws-s3-地址参数)
|
||||
- [Kube 地址参数](#kube-地址参数)
|
||||
- [WebDAV 地址参数](#webdav-地址参数)
|
||||
- [SMB 地址参数](#smb-地址参数)
|
||||
- [如何输入密码](#如何输入密码)
|
||||
@@ -102,6 +103,14 @@ s3://<bucket-name>@<region>[:profile][:/wrkdir]
|
||||
s3://buckethead@eu-central-1:default:/assets
|
||||
```
|
||||
|
||||
#### Kube 地址参数
|
||||
|
||||
如果您想连接到 Kube,请使用以下语法
|
||||
|
||||
```txt
|
||||
kube://<container>@<pod></path>
|
||||
```
|
||||
|
||||
#### WebDAV 地址参数
|
||||
|
||||
如果您想要连接到 WebDAV,请使用以下语法
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
|
||||
<head>
|
||||
<title>
|
||||
termscp is a terminal file transfer and explorer for SCP/SFTP/FTP/S3/SMB/WebDAV | termscp
|
||||
termscp is a terminal file transfer and explorer for SCP/SFTP/FTP/Kube/S3/WebDAV/SMB/WebDAV | termscp
|
||||
</title>
|
||||
<meta property="og:description"
|
||||
content="termscp is a feature rich terminal file transfer and explorer, with support for SCP/SFTP/FTP/S3. It is Linux, MacOS, FreeBSD, NetBSD and Windows compatible" />
|
||||
content="termscp is a feature rich terminal file transfer and explorer, with support for SCP/SFTP/FTP/Kube/S3/WebDAV. It is Linux, MacOS, FreeBSD, NetBSD and Windows compatible" />
|
||||
<meta name="description"
|
||||
content="termscp is a feature rich terminal file transfer and explorer, with support for SCP/SFTP/FTP/S3. It is Linux, MacOS, FreeBSD, NetBSD and Windows compatible" />
|
||||
<meta property="og:title" content="termscp is a terminal file transfer and explorer for SCP/SFTP/FTP/S3 | termscp" />
|
||||
content="termscp is a feature rich terminal file transfer and explorer, with support for SCP/SFTP/FTP/Kube/S3/WebDAV. It is Linux, MacOS, FreeBSD, NetBSD and Windows compatible" />
|
||||
<meta property="og:title" content="termscp is a terminal file transfer and explorer for SCP/SFTP/FTP/Kube/S3/WebDAV | termscp" />
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="robots" content="index, follow" />
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
<img class="w-[256px] h-auto m-auto" alt="logo" src="assets/images/termscp.webp" />
|
||||
<h2 class="text-xl font-thin text-center py-6" translate="intro.caption">
|
||||
A feature rich terminal UI file transfer and explorer with support for
|
||||
SCP/SFTP/FTP/S3/SMB/WebDAV
|
||||
SCP/SFTP/FTP/Kube/S3/WebDAV/SMB/WebDAV
|
||||
</h2>
|
||||
<button class="bg-brand hover:bg-gray-800 text-white font-thin text-xl py-2 px-4 rounded-xl max-w-fit">
|
||||
<a href="/get-started.html" class="no-underline" translate="intro.getStarted">Get started →</a>
|
||||
</button>
|
||||
<div class="p-4 my-4 text-sm text-green-800 rounded-lg bg-green-50">
|
||||
<p class="text-lg">
|
||||
<span translate="intro.versionAlert">termscp 0.13.0 is NOW out! Download it from</span>
|
||||
<span translate="intro.versionAlert">termscp 0.14.0 is NOW out! Download it from</span>
|
||||
<a href="/get-started.html" translate="intro.here">here!</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
|
||||
<head>
|
||||
<title>
|
||||
termscp is a terminal file transfer and explorer for SCP/SFTP/FTP/S3/SMB/WebDAV | termscp
|
||||
termscp is a terminal file transfer and explorer for SCP/SFTP/FTP/Kube/S3/WebDAV/SMB/WebDAV | termscp
|
||||
</title>
|
||||
<meta property="og:description"
|
||||
content="a WinSCP alternative for Linux and MacOS with support for SCP/SFTP/FTP/S3/SMB/WebDAV. Command line file transfer with user interface compatible with all the operating systems." />
|
||||
content="a WinSCP alternative for Linux and MacOS with support for SCP/SFTP/FTP/Kube/S3/WebDAV/SMB/WebDAV. Command line file transfer with user interface compatible with all the operating systems." />
|
||||
<meta name="description"
|
||||
content="a WinSCP alternative for Linux and MacOS with support for SCP/SFTP/FTP/S3/SMB/WebDAV. Command line file transfer with user interface compatible with all the operating systems." />
|
||||
content="a WinSCP alternative for Linux and MacOS with support for SCP/SFTP/FTP/Kube/S3/WebDAV/SMB/WebDAV. Command line file transfer with user interface compatible with all the operating systems." />
|
||||
<meta property="og:title"
|
||||
content="termscp is a terminal file transfer and explorer for SCP/SFTP/FTP/S3/SMB/WebDAV | termscp" />
|
||||
content="termscp is a terminal file transfer and explorer for SCP/SFTP/FTP/Kube/S3/WebDAV/SMB/WebDAV | termscp" />
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="robots" content="index, follow" />
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"support": "Support me"
|
||||
},
|
||||
"intro": {
|
||||
"caption": "A feature rich terminal UI file transfer and explorer with support for SCP/SFTP/FTP/S3",
|
||||
"caption": "A feature rich terminal UI file transfer and explorer with support for SCP/SFTP/FTP/Kube/S3/WebDAV",
|
||||
"getStarted": "Get started →",
|
||||
"versionAlert": "termscp 0.13.0 is NOW out! Download it from",
|
||||
"here": "here",
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"support": "Apoyame"
|
||||
},
|
||||
"intro": {
|
||||
"caption": "Un explorador y transferencia de archivos de terminal rico en funciones, con apoyo para SCP/SFTP/FTP/S3",
|
||||
"caption": "Un explorador y transferencia de archivos de terminal rico en funciones, con apoyo para SCP/SFTP/FTP/Kube/S3/WebDAV",
|
||||
"getStarted": "Para iniciar →",
|
||||
"versionAlert": "termscp 0.13.0 ya está disponible! Descárgalo desde",
|
||||
"here": "aquì",
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"support": "Me soutenir"
|
||||
},
|
||||
"intro": {
|
||||
"caption": "Un file transfer et navigateur de terminal riche en fonctionnalités avec support pour SCP/SFTP/FTP/S3",
|
||||
"caption": "Un file transfer et navigateur de terminal riche en fonctionnalités avec support pour SCP/SFTP/FTP/Kube/S3/WebDAV",
|
||||
"getStarted": "Pour commencer →",
|
||||
"versionAlert": "termscp 0.13.0 est maintenant sorti! Télécharge-le depuis",
|
||||
"here": "ici",
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"support": "支持我"
|
||||
},
|
||||
"intro": {
|
||||
"caption": "功能丰富的终端 UI 文件传输和浏览器,支持 SCP/SFTP/FTP/S3",
|
||||
"caption": "功能丰富的终端 UI 文件传输和浏览器,支持 SCP/SFTP/FTP/Kube/S3/WebDAV",
|
||||
"getStarted": "开始 →",
|
||||
"versionAlert": "termscp 0.13.0 现已发布! 从下载",
|
||||
"here": "这里",
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
//!
|
||||
//! `bookmarks` is the module which provides data types and de/serializer for bookmarks
|
||||
|
||||
mod aws_s3;
|
||||
mod kube;
|
||||
mod smb;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
@@ -9,9 +13,12 @@ use std::str::FromStr;
|
||||
use serde::de::Error as DeError;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
pub use self::aws_s3::S3Params;
|
||||
pub use self::kube::KubeParams;
|
||||
pub use self::smb::SmbParams;
|
||||
use crate::filetransfer::params::{
|
||||
AwsS3Params, GenericProtocolParams, ProtocolParams, SmbParams as TransferSmbParams,
|
||||
WebDAVProtocolParams,
|
||||
AwsS3Params, GenericProtocolParams, KubeProtocolParams, ProtocolParams,
|
||||
SmbParams as TransferSmbParams, WebDAVProtocolParams,
|
||||
};
|
||||
use crate::filetransfer::{FileTransferParams, FileTransferProtocol};
|
||||
|
||||
@@ -44,32 +51,14 @@ pub struct Bookmark {
|
||||
pub remote_path: Option<PathBuf>,
|
||||
/// local folder to open at startup
|
||||
pub local_path: Option<PathBuf>,
|
||||
/// Kube params; optional. When used other fields are empty for sure
|
||||
pub kube: Option<KubeParams>,
|
||||
/// S3 params; optional. When used other fields are empty for sure
|
||||
pub s3: Option<S3Params>,
|
||||
/// SMB params; optional. Extra params required for SMB protocol
|
||||
pub smb: Option<SmbParams>,
|
||||
}
|
||||
|
||||
/// Connection parameters for Aws s3 protocol
|
||||
#[derive(Clone, Deserialize, Serialize, Debug, PartialEq, Eq, Default)]
|
||||
pub struct S3Params {
|
||||
pub bucket: String,
|
||||
pub region: Option<String>,
|
||||
pub endpoint: Option<String>,
|
||||
pub profile: Option<String>,
|
||||
pub access_key: Option<String>,
|
||||
pub secret_access_key: Option<String>,
|
||||
/// NOTE: there are no session token and security token since they are always temporary
|
||||
pub new_path_style: Option<bool>,
|
||||
}
|
||||
|
||||
/// Extra Connection parameters for SMB protocol
|
||||
#[derive(Clone, Deserialize, Serialize, Debug, PartialEq, Eq, Default)]
|
||||
pub struct SmbParams {
|
||||
pub share: String,
|
||||
pub workgroup: Option<String>,
|
||||
}
|
||||
|
||||
// -- impls
|
||||
|
||||
impl From<FileTransferParams> for Bookmark {
|
||||
@@ -87,6 +76,7 @@ impl From<FileTransferParams> for Bookmark {
|
||||
password: params.password,
|
||||
remote_path,
|
||||
local_path,
|
||||
kube: None,
|
||||
s3: None,
|
||||
smb: None,
|
||||
},
|
||||
@@ -98,9 +88,22 @@ impl From<FileTransferParams> for Bookmark {
|
||||
password: None,
|
||||
remote_path,
|
||||
local_path,
|
||||
kube: None,
|
||||
s3: Some(S3Params::from(params)),
|
||||
smb: None,
|
||||
},
|
||||
ProtocolParams::Kube(params) => Self {
|
||||
protocol,
|
||||
address: None,
|
||||
port: None,
|
||||
username: None,
|
||||
password: None,
|
||||
remote_path,
|
||||
local_path,
|
||||
kube: Some(KubeParams::from(params)),
|
||||
s3: None,
|
||||
smb: None,
|
||||
},
|
||||
ProtocolParams::Smb(params) => Self {
|
||||
smb: Some(SmbParams::from(params.clone())),
|
||||
protocol,
|
||||
@@ -113,6 +116,7 @@ impl From<FileTransferParams> for Bookmark {
|
||||
password: params.password,
|
||||
remote_path,
|
||||
local_path,
|
||||
kube: None,
|
||||
s3: None,
|
||||
},
|
||||
ProtocolParams::WebDAV(parms) => Self {
|
||||
@@ -123,6 +127,7 @@ impl From<FileTransferParams> for Bookmark {
|
||||
password: Some(parms.password),
|
||||
remote_path,
|
||||
local_path,
|
||||
kube: None,
|
||||
s3: None,
|
||||
smb: None,
|
||||
},
|
||||
@@ -149,6 +154,11 @@ impl From<Bookmark> for FileTransferParams {
|
||||
.password(bookmark.password);
|
||||
Self::new(bookmark.protocol, ProtocolParams::Generic(params))
|
||||
}
|
||||
FileTransferProtocol::Kube => {
|
||||
let params = bookmark.kube.unwrap_or_default();
|
||||
let params = KubeProtocolParams::from(params);
|
||||
Self::new(bookmark.protocol, ProtocolParams::Kube(params))
|
||||
}
|
||||
#[cfg(unix)]
|
||||
FileTransferProtocol::Smb => {
|
||||
let params = TransferSmbParams::new(
|
||||
@@ -187,50 +197,6 @@ impl From<Bookmark> for FileTransferParams {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AwsS3Params> for S3Params {
|
||||
fn from(params: AwsS3Params) -> Self {
|
||||
S3Params {
|
||||
bucket: params.bucket_name,
|
||||
region: params.region,
|
||||
endpoint: params.endpoint,
|
||||
profile: params.profile,
|
||||
access_key: params.access_key,
|
||||
secret_access_key: params.secret_access_key,
|
||||
new_path_style: Some(params.new_path_style),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<S3Params> for AwsS3Params {
|
||||
fn from(params: S3Params) -> Self {
|
||||
AwsS3Params::new(params.bucket, params.region, params.profile)
|
||||
.endpoint(params.endpoint)
|
||||
.access_key(params.access_key)
|
||||
.secret_access_key(params.secret_access_key)
|
||||
.new_path_style(params.new_path_style.unwrap_or(false))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
impl From<TransferSmbParams> for SmbParams {
|
||||
fn from(params: TransferSmbParams) -> Self {
|
||||
Self {
|
||||
share: params.share,
|
||||
workgroup: params.workgroup,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
impl From<TransferSmbParams> for SmbParams {
|
||||
fn from(params: TransferSmbParams) -> Self {
|
||||
Self {
|
||||
share: params.share,
|
||||
workgroup: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_protocol<'de, D>(deserializer: D) -> Result<FileTransferProtocol, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
@@ -276,6 +242,7 @@ mod tests {
|
||||
password: Some(String::from("password")),
|
||||
remote_path: Some(PathBuf::from("/tmp")),
|
||||
local_path: Some(PathBuf::from("/usr")),
|
||||
kube: None,
|
||||
s3: None,
|
||||
smb: None,
|
||||
};
|
||||
@@ -287,6 +254,7 @@ mod tests {
|
||||
password: Some(String::from("password")),
|
||||
remote_path: Some(PathBuf::from("/home")),
|
||||
local_path: Some(PathBuf::from("/usr")),
|
||||
kube: None,
|
||||
s3: None,
|
||||
smb: None,
|
||||
};
|
||||
@@ -380,6 +348,38 @@ mod tests {
|
||||
assert_eq!(s3.secret_access_key.as_deref().unwrap(), "pluto");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bookmark_from_kube_ftparams() {
|
||||
let params = ProtocolParams::Kube(KubeProtocolParams {
|
||||
pod: "pod".to_string(),
|
||||
container: "container".to_string(),
|
||||
namespace: Some("default".to_string()),
|
||||
username: Some("root".to_string()),
|
||||
cluster_url: Some("https://localhost:6443".to_string()),
|
||||
client_cert: Some("cert".to_string()),
|
||||
client_key: Some("key".to_string()),
|
||||
});
|
||||
let params: FileTransferParams =
|
||||
FileTransferParams::new(FileTransferProtocol::Kube, params);
|
||||
let bookmark = Bookmark::from(params);
|
||||
assert_eq!(bookmark.protocol, FileTransferProtocol::Kube);
|
||||
assert!(bookmark.address.is_none());
|
||||
assert!(bookmark.port.is_none());
|
||||
assert!(bookmark.username.is_none());
|
||||
assert!(bookmark.password.is_none());
|
||||
let kube: &KubeParams = bookmark.kube.as_ref().unwrap();
|
||||
assert_eq!(kube.pod_name.as_str(), "pod");
|
||||
assert_eq!(kube.container.as_str(), "container");
|
||||
assert_eq!(kube.namespace.as_deref().unwrap(), "default");
|
||||
assert_eq!(
|
||||
kube.cluster_url.as_deref().unwrap(),
|
||||
"https://localhost:6443"
|
||||
);
|
||||
assert_eq!(kube.username.as_deref().unwrap(), "root");
|
||||
assert_eq!(kube.client_cert.as_deref().unwrap(), "cert");
|
||||
assert_eq!(kube.client_key.as_deref().unwrap(), "key");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ftparams_from_generic_bookmark() {
|
||||
let bookmark: Bookmark = Bookmark {
|
||||
@@ -390,6 +390,7 @@ mod tests {
|
||||
password: Some(String::from("password")),
|
||||
remote_path: Some(PathBuf::from("/tmp")),
|
||||
local_path: Some(PathBuf::from("/usr")),
|
||||
kube: None,
|
||||
s3: None,
|
||||
smb: None,
|
||||
};
|
||||
@@ -420,6 +421,7 @@ mod tests {
|
||||
password: Some(String::from("password")),
|
||||
remote_path: Some(PathBuf::from("/tmp")),
|
||||
local_path: Some(PathBuf::from("/usr")),
|
||||
kube: None,
|
||||
s3: None,
|
||||
smb: None,
|
||||
};
|
||||
@@ -449,6 +451,7 @@ mod tests {
|
||||
password: None,
|
||||
remote_path: Some(PathBuf::from("/tmp")),
|
||||
local_path: Some(PathBuf::from("/usr")),
|
||||
kube: None,
|
||||
s3: Some(S3Params {
|
||||
bucket: String::from("veeso"),
|
||||
region: Some(String::from("eu-west-1")),
|
||||
@@ -480,6 +483,50 @@ mod tests {
|
||||
assert_eq!(gparams.new_path_style, true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ftparams_from_kube_bookmark() {
|
||||
let bookmark: Bookmark = Bookmark {
|
||||
protocol: FileTransferProtocol::Kube,
|
||||
address: None,
|
||||
port: None,
|
||||
username: None,
|
||||
password: None,
|
||||
remote_path: Some(PathBuf::from("/tmp")),
|
||||
local_path: Some(PathBuf::from("/usr")),
|
||||
kube: Some(KubeParams {
|
||||
pod_name: String::from("pod"),
|
||||
container: String::from("container"),
|
||||
namespace: Some(String::from("default")),
|
||||
cluster_url: Some(String::from("https://localhost:6443")),
|
||||
username: Some(String::from("root")),
|
||||
client_cert: Some(String::from("cert")),
|
||||
client_key: Some(String::from("key")),
|
||||
}),
|
||||
s3: None,
|
||||
smb: None,
|
||||
};
|
||||
let params = FileTransferParams::from(bookmark);
|
||||
assert_eq!(params.protocol, FileTransferProtocol::Kube);
|
||||
assert_eq!(
|
||||
params.remote_path.as_deref().unwrap(),
|
||||
std::path::Path::new("/tmp")
|
||||
);
|
||||
assert_eq!(
|
||||
params.local_path.as_deref().unwrap(),
|
||||
std::path::Path::new("/usr")
|
||||
);
|
||||
let gparams = params.params.kube_params().unwrap();
|
||||
assert_eq!(gparams.pod.as_str(), "pod");
|
||||
assert_eq!(gparams.namespace.as_deref().unwrap(), "default");
|
||||
assert_eq!(
|
||||
gparams.cluster_url.as_deref().unwrap(),
|
||||
"https://localhost:6443"
|
||||
);
|
||||
assert_eq!(gparams.username.as_deref().unwrap(), "root");
|
||||
assert_eq!(gparams.client_cert.as_deref().unwrap(), "cert");
|
||||
assert_eq!(gparams.client_key.as_deref().unwrap(), "key");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn should_get_ftparams_from_smb_bookmark() {
|
||||
@@ -491,6 +538,7 @@ mod tests {
|
||||
password: Some("bar".to_string()),
|
||||
remote_path: Some(PathBuf::from("/tmp")),
|
||||
local_path: Some(PathBuf::from("/usr")),
|
||||
kube: None,
|
||||
s3: None,
|
||||
smb: Some(SmbParams {
|
||||
share: "test".to_string(),
|
||||
@@ -529,6 +577,7 @@ mod tests {
|
||||
remote_path: Some(PathBuf::from("/tmp")),
|
||||
local_path: Some(PathBuf::from("/usr")),
|
||||
s3: None,
|
||||
kube: None,
|
||||
smb: Some(SmbParams {
|
||||
share: "test".to_string(),
|
||||
workgroup: None,
|
||||
|
||||
40
src/config/bookmarks/aws_s3.rs
Normal file
40
src/config/bookmarks/aws_s3.rs
Normal file
@@ -0,0 +1,40 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::filetransfer::params::AwsS3Params;
|
||||
|
||||
/// Connection parameters for Aws s3 protocol
|
||||
#[derive(Clone, Deserialize, Serialize, Debug, PartialEq, Eq, Default)]
|
||||
pub struct S3Params {
|
||||
pub bucket: String,
|
||||
pub region: Option<String>,
|
||||
pub endpoint: Option<String>,
|
||||
pub profile: Option<String>,
|
||||
pub access_key: Option<String>,
|
||||
pub secret_access_key: Option<String>,
|
||||
/// NOTE: there are no session token and security token since they are always temporary
|
||||
pub new_path_style: Option<bool>,
|
||||
}
|
||||
|
||||
impl From<AwsS3Params> for S3Params {
|
||||
fn from(params: AwsS3Params) -> Self {
|
||||
S3Params {
|
||||
bucket: params.bucket_name,
|
||||
region: params.region,
|
||||
endpoint: params.endpoint,
|
||||
profile: params.profile,
|
||||
access_key: params.access_key,
|
||||
secret_access_key: params.secret_access_key,
|
||||
new_path_style: Some(params.new_path_style),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<S3Params> for AwsS3Params {
|
||||
fn from(params: S3Params) -> Self {
|
||||
AwsS3Params::new(params.bucket, params.region, params.profile)
|
||||
.endpoint(params.endpoint)
|
||||
.access_key(params.access_key)
|
||||
.secret_access_key(params.secret_access_key)
|
||||
.new_path_style(params.new_path_style.unwrap_or(false))
|
||||
}
|
||||
}
|
||||
43
src/config/bookmarks/kube.rs
Normal file
43
src/config/bookmarks/kube.rs
Normal file
@@ -0,0 +1,43 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::filetransfer::params::KubeProtocolParams;
|
||||
|
||||
/// Extra Connection parameters for Kube protocol
|
||||
#[derive(Clone, Deserialize, Serialize, Debug, PartialEq, Eq, Default)]
|
||||
pub struct KubeParams {
|
||||
pub pod_name: String,
|
||||
pub container: String,
|
||||
pub namespace: Option<String>,
|
||||
pub cluster_url: Option<String>,
|
||||
pub username: Option<String>,
|
||||
pub client_cert: Option<String>,
|
||||
pub client_key: Option<String>,
|
||||
}
|
||||
|
||||
impl From<KubeParams> for KubeProtocolParams {
|
||||
fn from(value: KubeParams) -> Self {
|
||||
Self {
|
||||
pod: value.pod_name,
|
||||
container: value.container,
|
||||
namespace: value.namespace,
|
||||
cluster_url: value.cluster_url,
|
||||
username: value.username,
|
||||
client_cert: value.client_cert,
|
||||
client_key: value.client_key,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<KubeProtocolParams> for KubeParams {
|
||||
fn from(value: KubeProtocolParams) -> Self {
|
||||
Self {
|
||||
pod_name: value.pod,
|
||||
container: value.container,
|
||||
namespace: value.namespace,
|
||||
cluster_url: value.cluster_url,
|
||||
username: value.username,
|
||||
client_cert: value.client_cert,
|
||||
client_key: value.client_key,
|
||||
}
|
||||
}
|
||||
}
|
||||
30
src/config/bookmarks/smb.rs
Normal file
30
src/config/bookmarks/smb.rs
Normal file
@@ -0,0 +1,30 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::filetransfer::params::SmbParams as TransferSmbParams;
|
||||
|
||||
/// Extra Connection parameters for SMB protocol
|
||||
#[derive(Clone, Deserialize, Serialize, Debug, PartialEq, Eq, Default)]
|
||||
pub struct SmbParams {
|
||||
pub share: String,
|
||||
pub workgroup: Option<String>,
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
impl From<TransferSmbParams> for SmbParams {
|
||||
fn from(params: TransferSmbParams) -> Self {
|
||||
Self {
|
||||
share: params.share,
|
||||
workgroup: params.workgroup,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
impl From<TransferSmbParams> for SmbParams {
|
||||
fn from(params: TransferSmbParams) -> Self {
|
||||
Self {
|
||||
share: params.share,
|
||||
workgroup: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -115,7 +115,7 @@ mod tests {
|
||||
use tuirealm::tui::style::Color;
|
||||
|
||||
use super::*;
|
||||
use crate::config::bookmarks::{Bookmark, S3Params, SmbParams, UserHosts};
|
||||
use crate::config::bookmarks::{Bookmark, KubeParams, S3Params, SmbParams, UserHosts};
|
||||
use crate::config::params::UserConfig;
|
||||
use crate::config::themes::Theme;
|
||||
use crate::filetransfer::FileTransferProtocol;
|
||||
@@ -366,7 +366,7 @@ mod tests {
|
||||
assert_eq!(host.username.as_deref().unwrap(), "root");
|
||||
assert_eq!(host.password, None);
|
||||
// Verify bookmarks
|
||||
assert_eq!(hosts.bookmarks.len(), 5);
|
||||
assert_eq!(hosts.bookmarks.len(), 6);
|
||||
let host: &Bookmark = hosts.bookmarks.get("raspberrypi2").unwrap();
|
||||
assert_eq!(host.address.as_deref().unwrap(), "192.168.1.31");
|
||||
assert_eq!(host.port.unwrap(), 22);
|
||||
@@ -404,6 +404,21 @@ mod tests {
|
||||
assert_eq!(s3.access_key.as_deref().unwrap(), "pippo");
|
||||
assert_eq!(s3.secret_access_key.as_deref().unwrap(), "pluto");
|
||||
assert_eq!(s3.new_path_style.unwrap(), true);
|
||||
// Kube pod
|
||||
let host: &Bookmark = hosts.bookmarks.get("pod").unwrap();
|
||||
assert_eq!(host.address, None);
|
||||
assert_eq!(host.port, None);
|
||||
assert_eq!(host.username, None);
|
||||
assert_eq!(host.password, None);
|
||||
assert_eq!(host.protocol, FileTransferProtocol::Kube);
|
||||
let kube = host.kube.as_ref().unwrap();
|
||||
assert_eq!(kube.pod_name.as_str(), "my-pod");
|
||||
assert_eq!(kube.container.as_str(), "my-container");
|
||||
assert_eq!(kube.namespace.as_deref().unwrap(), "my-namespace");
|
||||
assert_eq!(kube.cluster_url.as_deref().unwrap(), "https://my-cluster");
|
||||
assert_eq!(kube.username.as_deref().unwrap(), "my-username");
|
||||
assert_eq!(kube.client_cert.as_deref().unwrap(), "my-cert");
|
||||
assert_eq!(kube.client_key.as_deref().unwrap(), "my-key");
|
||||
|
||||
// smb
|
||||
let host = hosts.bookmarks.get("smb").unwrap();
|
||||
@@ -443,6 +458,7 @@ mod tests {
|
||||
password: None,
|
||||
remote_path: None,
|
||||
local_path: None,
|
||||
kube: None,
|
||||
s3: None,
|
||||
smb: None,
|
||||
},
|
||||
@@ -457,6 +473,7 @@ mod tests {
|
||||
password: Some(String::from("password")),
|
||||
remote_path: Some(PathBuf::from("/tmp")),
|
||||
local_path: Some(PathBuf::from("/usr")),
|
||||
kube: None,
|
||||
s3: None,
|
||||
smb: None,
|
||||
},
|
||||
@@ -480,9 +497,35 @@ mod tests {
|
||||
secret_access_key: None,
|
||||
new_path_style: None,
|
||||
}),
|
||||
kube: None,
|
||||
smb: None,
|
||||
},
|
||||
);
|
||||
// push kube pod
|
||||
bookmarks.insert(
|
||||
String::from("pod"),
|
||||
Bookmark {
|
||||
address: None,
|
||||
port: None,
|
||||
protocol: FileTransferProtocol::Kube,
|
||||
username: None,
|
||||
password: None,
|
||||
remote_path: None,
|
||||
local_path: None,
|
||||
s3: None,
|
||||
smb: None,
|
||||
kube: Some(KubeParams {
|
||||
pod_name: "my-pod".to_string(),
|
||||
container: "my-container".to_string(),
|
||||
namespace: Some("my-namespace".to_string()),
|
||||
cluster_url: Some("https://my-cluster".to_string()),
|
||||
username: Some("my-username".to_string()),
|
||||
client_cert: Some("my-cert".to_string()),
|
||||
client_key: Some("my-key".to_string()),
|
||||
}),
|
||||
},
|
||||
);
|
||||
|
||||
let smb_params: Option<SmbParams> = Some(SmbParams {
|
||||
share: "test".to_string(),
|
||||
workgroup: None,
|
||||
@@ -498,6 +541,7 @@ mod tests {
|
||||
remote_path: None,
|
||||
local_path: None,
|
||||
s3: None,
|
||||
kube: None,
|
||||
smb: smb_params,
|
||||
},
|
||||
);
|
||||
@@ -513,6 +557,7 @@ mod tests {
|
||||
remote_path: Some(PathBuf::from("/tmp")),
|
||||
local_path: Some(PathBuf::from("/usr")),
|
||||
s3: None,
|
||||
kube: None,
|
||||
smb: None,
|
||||
},
|
||||
);
|
||||
@@ -569,6 +614,17 @@ mod tests {
|
||||
secret_access_key = "pluto"
|
||||
new_path_style = true
|
||||
|
||||
[bookmarks.pod]
|
||||
protocol = "KUBE"
|
||||
[bookmarks.pod.kube]
|
||||
pod_name = "my-pod"
|
||||
container = "my-container"
|
||||
namespace = "my-namespace"
|
||||
cluster_url = "https://my-cluster"
|
||||
username = "my-username"
|
||||
client_cert = "my-cert"
|
||||
client_key = "my-key"
|
||||
|
||||
[bookmarks.smb]
|
||||
protocol = "SMB"
|
||||
address = "localhost"
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
//! Remotefs client builder
|
||||
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
use remotefs::RemoteFs;
|
||||
use remotefs_aws_s3::AwsS3Fs;
|
||||
use remotefs_ftp::FtpFs;
|
||||
use remotefs_kube::KubeFs;
|
||||
#[cfg(smb_unix)]
|
||||
use remotefs_smb::SmbOptions;
|
||||
#[cfg(smb)]
|
||||
@@ -14,11 +16,11 @@ use remotefs_smb::{SmbCredentials, SmbFs};
|
||||
use remotefs_ssh::{ScpFs, SftpFs, SshAgentIdentity, SshConfigParseRule, SshOpts};
|
||||
use remotefs_webdav::WebDAVFs;
|
||||
|
||||
use super::params::WebDAVProtocolParams;
|
||||
#[cfg(not(smb))]
|
||||
use super::params::{AwsS3Params, GenericProtocolParams};
|
||||
#[cfg(smb)]
|
||||
use super::params::{AwsS3Params, GenericProtocolParams, SmbParams};
|
||||
use super::params::{KubeProtocolParams, WebDAVProtocolParams};
|
||||
use super::{FileTransferProtocol, ProtocolParams};
|
||||
use crate::system::config_client::ConfigClient;
|
||||
use crate::system::sshkey_storage::SshKeyStorage;
|
||||
@@ -43,6 +45,9 @@ impl Builder {
|
||||
(FileTransferProtocol::Ftp(secure), ProtocolParams::Generic(params)) => {
|
||||
Box::new(Self::ftp_client(params, secure))
|
||||
}
|
||||
(FileTransferProtocol::Kube, ProtocolParams::Kube(params)) => {
|
||||
Box::new(Self::kube_client(params))
|
||||
}
|
||||
(FileTransferProtocol::Scp, ProtocolParams::Generic(params)) => {
|
||||
Box::new(Self::scp_client(params, config_client))
|
||||
}
|
||||
@@ -105,6 +110,23 @@ impl Builder {
|
||||
client
|
||||
}
|
||||
|
||||
/// Build kube client
|
||||
fn kube_client(params: KubeProtocolParams) -> KubeFs {
|
||||
let rt = Arc::new(
|
||||
tokio::runtime::Builder::new_multi_thread()
|
||||
.worker_threads(1)
|
||||
.enable_all()
|
||||
.build()
|
||||
.expect("Unable to create tokio runtime"),
|
||||
);
|
||||
let kube_fs = KubeFs::new(¶ms.pod, ¶ms.container, &rt);
|
||||
if let Some(config) = params.config() {
|
||||
kube_fs.config(config)
|
||||
} else {
|
||||
kube_fs
|
||||
}
|
||||
}
|
||||
|
||||
/// Build scp client
|
||||
fn scp_client(params: GenericProtocolParams, config_client: &ConfigClient) -> ScpFs {
|
||||
Self::build_ssh_opts(params, config_client).into()
|
||||
@@ -256,6 +278,21 @@ mod test {
|
||||
let _ = Builder::build(FileTransferProtocol::Ftp(true), params, &config_client);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_should_build_kube_fs() {
|
||||
let params = ProtocolParams::Kube(KubeProtocolParams {
|
||||
pod: "pod".to_string(),
|
||||
container: "container".to_string(),
|
||||
namespace: Some("namespace".to_string()),
|
||||
cluster_url: Some("cluster_url".to_string()),
|
||||
username: Some("username".to_string()),
|
||||
client_cert: Some("client_cert".to_string()),
|
||||
client_key: Some("client_key".to_string()),
|
||||
});
|
||||
let config_client = get_config_client();
|
||||
let _ = Builder::build(FileTransferProtocol::Kube, params, &config_client);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_build_scp_fs() {
|
||||
let params = ProtocolParams::Generic(
|
||||
|
||||
@@ -15,6 +15,7 @@ pub use params::{FileTransferParams, ProtocolParams};
|
||||
pub enum FileTransferProtocol {
|
||||
AwsS3,
|
||||
Ftp(bool), // Bool is for secure (true => ftps)
|
||||
Kube,
|
||||
Scp,
|
||||
Sftp,
|
||||
Smb,
|
||||
@@ -34,6 +35,7 @@ impl std::fmt::Display for FileTransferProtocol {
|
||||
true => "FTPS",
|
||||
false => "FTP",
|
||||
},
|
||||
FileTransferProtocol::Kube => "KUBE",
|
||||
FileTransferProtocol::Scp => "SCP",
|
||||
FileTransferProtocol::Sftp => "SFTP",
|
||||
FileTransferProtocol::Smb => "SMB",
|
||||
@@ -49,6 +51,7 @@ impl std::str::FromStr for FileTransferProtocol {
|
||||
match s.to_ascii_uppercase().as_str() {
|
||||
"FTP" => Ok(FileTransferProtocol::Ftp(false)),
|
||||
"FTPS" => Ok(FileTransferProtocol::Ftp(true)),
|
||||
"KUBE" => Ok(FileTransferProtocol::Kube),
|
||||
"S3" => Ok(FileTransferProtocol::AwsS3),
|
||||
"SCP" => Ok(FileTransferProtocol::Scp),
|
||||
"SFTP" => Ok(FileTransferProtocol::Sftp),
|
||||
@@ -114,6 +117,14 @@ mod tests {
|
||||
FileTransferProtocol::from_str("scp").ok().unwrap(),
|
||||
FileTransferProtocol::Scp
|
||||
);
|
||||
assert_eq!(
|
||||
FileTransferProtocol::from_str("kube").ok().unwrap(),
|
||||
FileTransferProtocol::Kube
|
||||
);
|
||||
assert_eq!(
|
||||
FileTransferProtocol::from_str("KUBE").ok().unwrap(),
|
||||
FileTransferProtocol::Kube
|
||||
);
|
||||
assert_eq!(
|
||||
FileTransferProtocol::from_str("SMB").ok().unwrap(),
|
||||
FileTransferProtocol::Smb
|
||||
@@ -153,5 +164,6 @@ mod tests {
|
||||
FileTransferProtocol::WebDAV.to_string(),
|
||||
String::from("WEBDAV")
|
||||
);
|
||||
assert_eq!(FileTransferProtocol::Kube.to_string(), String::from("KUBE"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,17 @@
|
||||
//!
|
||||
//! file transfer parameters
|
||||
|
||||
mod aws_s3;
|
||||
mod kube;
|
||||
mod smb;
|
||||
mod webdav;
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
pub use self::aws_s3::AwsS3Params;
|
||||
pub use self::kube::KubeProtocolParams;
|
||||
pub use self::smb::SmbParams;
|
||||
pub use self::webdav::WebDAVProtocolParams;
|
||||
use super::FileTransferProtocol;
|
||||
|
||||
/// Holds connection parameters for file transfers
|
||||
@@ -20,6 +29,7 @@ pub struct FileTransferParams {
|
||||
pub enum ProtocolParams {
|
||||
Generic(GenericProtocolParams),
|
||||
AwsS3(AwsS3Params),
|
||||
Kube(KubeProtocolParams),
|
||||
Smb(SmbParams),
|
||||
WebDAV(WebDAVProtocolParams),
|
||||
}
|
||||
@@ -33,33 +43,6 @@ pub struct GenericProtocolParams {
|
||||
pub password: Option<String>,
|
||||
}
|
||||
|
||||
/// Connection parameters for AWS S3 protocol
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AwsS3Params {
|
||||
pub bucket_name: String,
|
||||
pub region: Option<String>,
|
||||
pub endpoint: Option<String>,
|
||||
pub profile: Option<String>,
|
||||
pub access_key: Option<String>,
|
||||
pub secret_access_key: Option<String>,
|
||||
pub security_token: Option<String>,
|
||||
pub session_token: Option<String>,
|
||||
pub new_path_style: bool,
|
||||
}
|
||||
|
||||
/// Connection parameters for SMB protocol
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SmbParams {
|
||||
pub address: String,
|
||||
#[cfg(unix)]
|
||||
pub port: u16,
|
||||
pub share: String,
|
||||
pub username: Option<String>,
|
||||
pub password: Option<String>,
|
||||
#[cfg(unix)]
|
||||
pub workgroup: Option<String>,
|
||||
}
|
||||
|
||||
impl FileTransferParams {
|
||||
/// Instantiates a new `FileTransferParams`
|
||||
pub fn new(protocol: FileTransferProtocol, params: ProtocolParams) -> Self {
|
||||
@@ -89,6 +72,7 @@ impl FileTransferParams {
|
||||
match &self.params {
|
||||
ProtocolParams::AwsS3(params) => params.password_missing(),
|
||||
ProtocolParams::Generic(params) => params.password_missing(),
|
||||
ProtocolParams::Kube(params) => params.password_missing(),
|
||||
ProtocolParams::Smb(params) => params.password_missing(),
|
||||
ProtocolParams::WebDAV(params) => params.password_missing(),
|
||||
}
|
||||
@@ -99,30 +83,13 @@ impl FileTransferParams {
|
||||
match &mut self.params {
|
||||
ProtocolParams::AwsS3(params) => params.set_default_secret(secret),
|
||||
ProtocolParams::Generic(params) => params.set_default_secret(secret),
|
||||
ProtocolParams::Kube(params) => params.set_default_secret(secret),
|
||||
ProtocolParams::Smb(params) => params.set_default_secret(secret),
|
||||
ProtocolParams::WebDAV(params) => params.set_default_secret(secret),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Protocol params used by WebDAV
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct WebDAVProtocolParams {
|
||||
pub uri: String,
|
||||
pub username: String,
|
||||
pub password: String,
|
||||
}
|
||||
|
||||
impl WebDAVProtocolParams {
|
||||
fn set_default_secret(&mut self, secret: String) {
|
||||
self.password = secret;
|
||||
}
|
||||
|
||||
fn password_missing(&self) -> bool {
|
||||
self.password.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for FileTransferParams {
|
||||
fn default() -> Self {
|
||||
Self::new(FileTransferProtocol::Sftp, ProtocolParams::default())
|
||||
@@ -162,6 +129,15 @@ impl ProtocolParams {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
/// Retrieve Kube params parameters if any
|
||||
pub fn kube_params(&self) -> Option<&KubeProtocolParams> {
|
||||
match self {
|
||||
ProtocolParams::Kube(params) => Some(params),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
/// Retrieve SMB parameters if any
|
||||
pub fn smb_params(&self) -> Option<&SmbParams> {
|
||||
@@ -231,127 +207,6 @@ impl GenericProtocolParams {
|
||||
}
|
||||
}
|
||||
|
||||
// -- S3 params
|
||||
|
||||
impl AwsS3Params {
|
||||
/// Instantiates a new `AwsS3Params` struct
|
||||
pub fn new<S: AsRef<str>>(bucket: S, region: Option<S>, profile: Option<S>) -> Self {
|
||||
Self {
|
||||
bucket_name: bucket.as_ref().to_string(),
|
||||
region: region.map(|x| x.as_ref().to_string()),
|
||||
profile: profile.map(|x| x.as_ref().to_string()),
|
||||
endpoint: None,
|
||||
access_key: None,
|
||||
secret_access_key: None,
|
||||
security_token: None,
|
||||
session_token: None,
|
||||
new_path_style: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct aws s3 params with specified endpoint
|
||||
pub fn endpoint<S: AsRef<str>>(mut self, endpoint: Option<S>) -> Self {
|
||||
self.endpoint = endpoint.map(|x| x.as_ref().to_string());
|
||||
self
|
||||
}
|
||||
|
||||
/// Construct aws s3 params with provided access key
|
||||
pub fn access_key<S: AsRef<str>>(mut self, key: Option<S>) -> Self {
|
||||
self.access_key = key.map(|x| x.as_ref().to_string());
|
||||
self
|
||||
}
|
||||
|
||||
/// Construct aws s3 params with provided secret_access_key
|
||||
pub fn secret_access_key<S: AsRef<str>>(mut self, key: Option<S>) -> Self {
|
||||
self.secret_access_key = key.map(|x| x.as_ref().to_string());
|
||||
self
|
||||
}
|
||||
|
||||
/// Construct aws s3 params with provided security_token
|
||||
pub fn security_token<S: AsRef<str>>(mut self, key: Option<S>) -> Self {
|
||||
self.security_token = key.map(|x| x.as_ref().to_string());
|
||||
self
|
||||
}
|
||||
|
||||
/// Construct aws s3 params with provided session_token
|
||||
pub fn session_token<S: AsRef<str>>(mut self, key: Option<S>) -> Self {
|
||||
self.session_token = key.map(|x| x.as_ref().to_string());
|
||||
self
|
||||
}
|
||||
|
||||
/// Specify new path style when constructing aws s3 params
|
||||
pub fn new_path_style(mut self, new_path_style: bool) -> Self {
|
||||
self.new_path_style = new_path_style;
|
||||
self
|
||||
}
|
||||
|
||||
/// Returns whether a password is supposed to be required for this protocol params.
|
||||
/// The result true is returned ONLY if the supposed secret is MISSING!!!
|
||||
pub fn password_missing(&self) -> bool {
|
||||
self.secret_access_key.is_none() && self.security_token.is_none()
|
||||
}
|
||||
|
||||
/// Set password
|
||||
pub fn set_default_secret(&mut self, secret: String) {
|
||||
self.secret_access_key = Some(secret);
|
||||
}
|
||||
}
|
||||
|
||||
// -- SMB params
|
||||
|
||||
impl SmbParams {
|
||||
/// Instantiates a new `AwsS3Params` struct
|
||||
pub fn new<S: AsRef<str>>(address: S, share: S) -> Self {
|
||||
Self {
|
||||
address: address.as_ref().to_string(),
|
||||
#[cfg(unix)]
|
||||
port: 445,
|
||||
share: share.as_ref().to_string(),
|
||||
username: None,
|
||||
password: None,
|
||||
#[cfg(unix)]
|
||||
workgroup: None,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
pub fn port(mut self, port: u16) -> Self {
|
||||
self.port = port;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn username(mut self, username: Option<impl ToString>) -> Self {
|
||||
self.username = username.map(|x| x.to_string());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn password(mut self, password: Option<impl ToString>) -> Self {
|
||||
self.password = password.map(|x| x.to_string());
|
||||
self
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
pub fn workgroup(mut self, workgroup: Option<impl ToString>) -> Self {
|
||||
self.workgroup = workgroup.map(|x| x.to_string());
|
||||
self
|
||||
}
|
||||
|
||||
/// Returns whether a password is supposed to be required for this protocol params.
|
||||
/// The result true is returned ONLY if the supposed secret is MISSING!!!
|
||||
pub fn password_missing(&self) -> bool {
|
||||
self.password.is_none()
|
||||
}
|
||||
|
||||
/// Set password
|
||||
#[cfg(unix)]
|
||||
pub fn set_default_secret(&mut self, secret: String) {
|
||||
self.password = Some(secret);
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn set_default_secret(&mut self, _secret: String) {}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
@@ -386,87 +241,6 @@ mod test {
|
||||
assert!(params.password.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_init_aws_s3_params() {
|
||||
let params: AwsS3Params = AwsS3Params::new("omar", Some("eu-west-1"), Some("test"));
|
||||
assert_eq!(params.bucket_name.as_str(), "omar");
|
||||
assert_eq!(params.region.as_deref().unwrap(), "eu-west-1");
|
||||
assert_eq!(params.profile.as_deref().unwrap(), "test");
|
||||
assert!(params.endpoint.is_none());
|
||||
assert!(params.access_key.is_none());
|
||||
assert!(params.secret_access_key.is_none());
|
||||
assert!(params.security_token.is_none());
|
||||
assert!(params.session_token.is_none());
|
||||
assert_eq!(params.new_path_style, false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_init_aws_s3_params_with_optionals() {
|
||||
let params: AwsS3Params = AwsS3Params::new("omar", Some("eu-west-1"), Some("test"))
|
||||
.endpoint(Some("http://omar.it"))
|
||||
.access_key(Some("pippo"))
|
||||
.secret_access_key(Some("pluto"))
|
||||
.security_token(Some("omar"))
|
||||
.session_token(Some("gerry-scotti"))
|
||||
.new_path_style(true);
|
||||
assert_eq!(params.bucket_name.as_str(), "omar");
|
||||
assert_eq!(params.region.as_deref().unwrap(), "eu-west-1");
|
||||
assert_eq!(params.profile.as_deref().unwrap(), "test");
|
||||
assert_eq!(params.endpoint.as_deref().unwrap(), "http://omar.it");
|
||||
assert_eq!(params.access_key.as_deref().unwrap(), "pippo");
|
||||
assert_eq!(params.secret_access_key.as_deref().unwrap(), "pluto");
|
||||
assert_eq!(params.security_token.as_deref().unwrap(), "omar");
|
||||
assert_eq!(params.session_token.as_deref().unwrap(), "gerry-scotti");
|
||||
assert_eq!(params.new_path_style, true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_init_smb_params() {
|
||||
let params = SmbParams::new("localhost", "temp");
|
||||
assert_eq!(¶ms.address, "localhost");
|
||||
|
||||
#[cfg(unix)]
|
||||
assert_eq!(params.port, 445);
|
||||
assert_eq!(¶ms.share, "temp");
|
||||
|
||||
#[cfg(unix)]
|
||||
assert!(params.username.is_none());
|
||||
#[cfg(unix)]
|
||||
assert!(params.password.is_none());
|
||||
#[cfg(unix)]
|
||||
assert!(params.workgroup.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn should_init_smb_params_with_optionals() {
|
||||
let params = SmbParams::new("localhost", "temp")
|
||||
.port(3456)
|
||||
.username(Some("foo"))
|
||||
.password(Some("bar"))
|
||||
.workgroup(Some("baz"));
|
||||
|
||||
assert_eq!(¶ms.address, "localhost");
|
||||
assert_eq!(params.port, 3456);
|
||||
assert_eq!(¶ms.share, "temp");
|
||||
assert_eq!(params.username.as_deref().unwrap(), "foo");
|
||||
assert_eq!(params.password.as_deref().unwrap(), "bar");
|
||||
assert_eq!(params.workgroup.as_deref().unwrap(), "baz");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(windows)]
|
||||
fn should_init_smb_params_with_optionals() {
|
||||
let params = SmbParams::new("localhost", "temp")
|
||||
.username(Some("foo"))
|
||||
.password(Some("bar"));
|
||||
|
||||
assert_eq!(¶ms.address, "localhost");
|
||||
assert_eq!(¶ms.share, "temp");
|
||||
assert_eq!(params.username.as_deref().unwrap(), "foo");
|
||||
assert_eq!(params.password.as_deref().unwrap(), "bar");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn references() {
|
||||
let mut params =
|
||||
|
||||
121
src/filetransfer/params/aws_s3.rs
Normal file
121
src/filetransfer/params/aws_s3.rs
Normal file
@@ -0,0 +1,121 @@
|
||||
/// Connection parameters for AWS S3 protocol
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AwsS3Params {
|
||||
pub bucket_name: String,
|
||||
pub region: Option<String>,
|
||||
pub endpoint: Option<String>,
|
||||
pub profile: Option<String>,
|
||||
pub access_key: Option<String>,
|
||||
pub secret_access_key: Option<String>,
|
||||
pub security_token: Option<String>,
|
||||
pub session_token: Option<String>,
|
||||
pub new_path_style: bool,
|
||||
}
|
||||
|
||||
// -- S3 params
|
||||
|
||||
impl AwsS3Params {
|
||||
/// Instantiates a new `AwsS3Params` struct
|
||||
pub fn new<S: AsRef<str>>(bucket: S, region: Option<S>, profile: Option<S>) -> Self {
|
||||
Self {
|
||||
bucket_name: bucket.as_ref().to_string(),
|
||||
region: region.map(|x| x.as_ref().to_string()),
|
||||
profile: profile.map(|x| x.as_ref().to_string()),
|
||||
endpoint: None,
|
||||
access_key: None,
|
||||
secret_access_key: None,
|
||||
security_token: None,
|
||||
session_token: None,
|
||||
new_path_style: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct aws s3 params with specified endpoint
|
||||
pub fn endpoint<S: AsRef<str>>(mut self, endpoint: Option<S>) -> Self {
|
||||
self.endpoint = endpoint.map(|x| x.as_ref().to_string());
|
||||
self
|
||||
}
|
||||
|
||||
/// Construct aws s3 params with provided access key
|
||||
pub fn access_key<S: AsRef<str>>(mut self, key: Option<S>) -> Self {
|
||||
self.access_key = key.map(|x| x.as_ref().to_string());
|
||||
self
|
||||
}
|
||||
|
||||
/// Construct aws s3 params with provided secret_access_key
|
||||
pub fn secret_access_key<S: AsRef<str>>(mut self, key: Option<S>) -> Self {
|
||||
self.secret_access_key = key.map(|x| x.as_ref().to_string());
|
||||
self
|
||||
}
|
||||
|
||||
/// Construct aws s3 params with provided security_token
|
||||
pub fn security_token<S: AsRef<str>>(mut self, key: Option<S>) -> Self {
|
||||
self.security_token = key.map(|x| x.as_ref().to_string());
|
||||
self
|
||||
}
|
||||
|
||||
/// Construct aws s3 params with provided session_token
|
||||
pub fn session_token<S: AsRef<str>>(mut self, key: Option<S>) -> Self {
|
||||
self.session_token = key.map(|x| x.as_ref().to_string());
|
||||
self
|
||||
}
|
||||
|
||||
/// Specify new path style when constructing aws s3 params
|
||||
pub fn new_path_style(mut self, new_path_style: bool) -> Self {
|
||||
self.new_path_style = new_path_style;
|
||||
self
|
||||
}
|
||||
|
||||
/// Returns whether a password is supposed to be required for this protocol params.
|
||||
/// The result true is returned ONLY if the supposed secret is MISSING!!!
|
||||
pub fn password_missing(&self) -> bool {
|
||||
self.secret_access_key.is_none() && self.security_token.is_none()
|
||||
}
|
||||
|
||||
/// Set password
|
||||
pub fn set_default_secret(&mut self, secret: String) {
|
||||
self.secret_access_key = Some(secret);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn should_init_aws_s3_params() {
|
||||
let params: AwsS3Params = AwsS3Params::new("omar", Some("eu-west-1"), Some("test"));
|
||||
assert_eq!(params.bucket_name.as_str(), "omar");
|
||||
assert_eq!(params.region.as_deref().unwrap(), "eu-west-1");
|
||||
assert_eq!(params.profile.as_deref().unwrap(), "test");
|
||||
assert!(params.endpoint.is_none());
|
||||
assert!(params.access_key.is_none());
|
||||
assert!(params.secret_access_key.is_none());
|
||||
assert!(params.security_token.is_none());
|
||||
assert!(params.session_token.is_none());
|
||||
assert_eq!(params.new_path_style, false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_init_aws_s3_params_with_optionals() {
|
||||
let params: AwsS3Params = AwsS3Params::new("omar", Some("eu-west-1"), Some("test"))
|
||||
.endpoint(Some("http://omar.it"))
|
||||
.access_key(Some("pippo"))
|
||||
.secret_access_key(Some("pluto"))
|
||||
.security_token(Some("omar"))
|
||||
.session_token(Some("gerry-scotti"))
|
||||
.new_path_style(true);
|
||||
assert_eq!(params.bucket_name.as_str(), "omar");
|
||||
assert_eq!(params.region.as_deref().unwrap(), "eu-west-1");
|
||||
assert_eq!(params.profile.as_deref().unwrap(), "test");
|
||||
assert_eq!(params.endpoint.as_deref().unwrap(), "http://omar.it");
|
||||
assert_eq!(params.access_key.as_deref().unwrap(), "pippo");
|
||||
assert_eq!(params.secret_access_key.as_deref().unwrap(), "pluto");
|
||||
assert_eq!(params.security_token.as_deref().unwrap(), "omar");
|
||||
assert_eq!(params.session_token.as_deref().unwrap(), "gerry-scotti");
|
||||
assert_eq!(params.new_path_style, true);
|
||||
}
|
||||
}
|
||||
37
src/filetransfer/params/kube.rs
Normal file
37
src/filetransfer/params/kube.rs
Normal file
@@ -0,0 +1,37 @@
|
||||
use remotefs_kube::Config;
|
||||
|
||||
/// Protocol params used by WebDAV
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct KubeProtocolParams {
|
||||
pub pod: String,
|
||||
pub container: String,
|
||||
pub namespace: Option<String>,
|
||||
pub cluster_url: Option<String>,
|
||||
pub username: Option<String>,
|
||||
pub client_cert: Option<String>,
|
||||
pub client_key: Option<String>,
|
||||
}
|
||||
|
||||
impl KubeProtocolParams {
|
||||
pub fn set_default_secret(&mut self, _secret: String) {}
|
||||
|
||||
pub fn password_missing(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
pub fn config(self) -> Option<Config> {
|
||||
if let Some(cluster_url) = self.cluster_url {
|
||||
let mut config = Config::new(cluster_url.parse().unwrap_or_default());
|
||||
config.auth_info.username = self.username;
|
||||
config.auth_info.client_certificate = self.client_cert;
|
||||
config.auth_info.client_key = self.client_key;
|
||||
if let Some(namespace) = self.namespace {
|
||||
config.default_namespace = namespace;
|
||||
}
|
||||
|
||||
Some(config)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
122
src/filetransfer/params/smb.rs
Normal file
122
src/filetransfer/params/smb.rs
Normal file
@@ -0,0 +1,122 @@
|
||||
/// Connection parameters for SMB protocol
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SmbParams {
|
||||
pub address: String,
|
||||
#[cfg(unix)]
|
||||
pub port: u16,
|
||||
pub share: String,
|
||||
pub username: Option<String>,
|
||||
pub password: Option<String>,
|
||||
#[cfg(unix)]
|
||||
pub workgroup: Option<String>,
|
||||
}
|
||||
|
||||
// -- SMB params
|
||||
|
||||
impl SmbParams {
|
||||
/// Instantiates a new `AwsS3Params` struct
|
||||
pub fn new<S: AsRef<str>>(address: S, share: S) -> Self {
|
||||
Self {
|
||||
address: address.as_ref().to_string(),
|
||||
#[cfg(unix)]
|
||||
port: 445,
|
||||
share: share.as_ref().to_string(),
|
||||
username: None,
|
||||
password: None,
|
||||
#[cfg(unix)]
|
||||
workgroup: None,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
pub fn port(mut self, port: u16) -> Self {
|
||||
self.port = port;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn username(mut self, username: Option<impl ToString>) -> Self {
|
||||
self.username = username.map(|x| x.to_string());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn password(mut self, password: Option<impl ToString>) -> Self {
|
||||
self.password = password.map(|x| x.to_string());
|
||||
self
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
pub fn workgroup(mut self, workgroup: Option<impl ToString>) -> Self {
|
||||
self.workgroup = workgroup.map(|x| x.to_string());
|
||||
self
|
||||
}
|
||||
|
||||
/// Returns whether a password is supposed to be required for this protocol params.
|
||||
/// The result true is returned ONLY if the supposed secret is MISSING!!!
|
||||
pub fn password_missing(&self) -> bool {
|
||||
self.password.is_none()
|
||||
}
|
||||
|
||||
/// Set password
|
||||
#[cfg(unix)]
|
||||
pub fn set_default_secret(&mut self, secret: String) {
|
||||
self.password = Some(secret);
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn set_default_secret(&mut self, _secret: String) {}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn should_init_smb_params() {
|
||||
let params = SmbParams::new("localhost", "temp");
|
||||
assert_eq!(¶ms.address, "localhost");
|
||||
|
||||
#[cfg(unix)]
|
||||
assert_eq!(params.port, 445);
|
||||
assert_eq!(¶ms.share, "temp");
|
||||
|
||||
#[cfg(unix)]
|
||||
assert!(params.username.is_none());
|
||||
#[cfg(unix)]
|
||||
assert!(params.password.is_none());
|
||||
#[cfg(unix)]
|
||||
assert!(params.workgroup.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn should_init_smb_params_with_optionals() {
|
||||
let params = SmbParams::new("localhost", "temp")
|
||||
.port(3456)
|
||||
.username(Some("foo"))
|
||||
.password(Some("bar"))
|
||||
.workgroup(Some("baz"));
|
||||
|
||||
assert_eq!(¶ms.address, "localhost");
|
||||
assert_eq!(params.port, 3456);
|
||||
assert_eq!(¶ms.share, "temp");
|
||||
assert_eq!(params.username.as_deref().unwrap(), "foo");
|
||||
assert_eq!(params.password.as_deref().unwrap(), "bar");
|
||||
assert_eq!(params.workgroup.as_deref().unwrap(), "baz");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(windows)]
|
||||
fn should_init_smb_params_with_optionals() {
|
||||
let params = SmbParams::new("localhost", "temp")
|
||||
.username(Some("foo"))
|
||||
.password(Some("bar"));
|
||||
|
||||
assert_eq!(¶ms.address, "localhost");
|
||||
assert_eq!(¶ms.share, "temp");
|
||||
assert_eq!(params.username.as_deref().unwrap(), "foo");
|
||||
assert_eq!(params.password.as_deref().unwrap(), "bar");
|
||||
}
|
||||
}
|
||||
17
src/filetransfer/params/webdav.rs
Normal file
17
src/filetransfer/params/webdav.rs
Normal file
@@ -0,0 +1,17 @@
|
||||
/// Protocol params used by WebDAV
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct WebDAVProtocolParams {
|
||||
pub uri: String,
|
||||
pub username: String,
|
||||
pub password: String,
|
||||
}
|
||||
|
||||
impl WebDAVProtocolParams {
|
||||
pub fn set_default_secret(&mut self, secret: String) {
|
||||
self.password = secret;
|
||||
}
|
||||
|
||||
pub fn password_missing(&self) -> bool {
|
||||
self.password.is_empty()
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,8 @@
|
||||
// Locals
|
||||
use super::{AuthActivity, FileTransferParams};
|
||||
use crate::filetransfer::params::{
|
||||
AwsS3Params, GenericProtocolParams, ProtocolParams, SmbParams, WebDAVProtocolParams,
|
||||
AwsS3Params, GenericProtocolParams, KubeProtocolParams, ProtocolParams, SmbParams,
|
||||
WebDAVProtocolParams,
|
||||
};
|
||||
|
||||
impl AuthActivity {
|
||||
@@ -164,6 +165,8 @@ impl AuthActivity {
|
||||
);
|
||||
match bookmark.params {
|
||||
ProtocolParams::AwsS3(params) => self.load_bookmark_s3_into_gui(params),
|
||||
ProtocolParams::Kube(params) => self.load_bookmark_kube_into_gui(params),
|
||||
|
||||
ProtocolParams::Generic(params) => self.load_bookmark_generic_into_gui(params),
|
||||
ProtocolParams::Smb(params) => self.load_bookmark_smb_into_gui(params),
|
||||
ProtocolParams::WebDAV(params) => self.load_bookmark_webdav_into_gui(params),
|
||||
@@ -189,6 +192,16 @@ impl AuthActivity {
|
||||
self.mount_s3_new_path_style(params.new_path_style);
|
||||
}
|
||||
|
||||
fn load_bookmark_kube_into_gui(&mut self, params: KubeProtocolParams) {
|
||||
self.mount_kube_pod_name(params.pod.as_str());
|
||||
self.mount_kube_container(¶ms.container);
|
||||
self.mount_kube_cluster_url(params.cluster_url.as_deref().unwrap_or(""));
|
||||
self.mount_kube_namespace(params.namespace.as_deref().unwrap_or(""));
|
||||
self.mount_kube_client_cert(params.client_cert.as_deref().unwrap_or(""));
|
||||
self.mount_kube_client_key(params.client_key.as_deref().unwrap_or(""));
|
||||
self.mount_kube_username(params.username.as_deref().unwrap_or(""));
|
||||
}
|
||||
|
||||
fn load_bookmark_smb_into_gui(&mut self, params: SmbParams) {
|
||||
self.mount_address(params.address.as_str());
|
||||
#[cfg(unix)]
|
||||
|
||||
@@ -10,8 +10,8 @@ use tuirealm::{Component, Event, MockComponent, NoUserEvent, State, StateValue};
|
||||
|
||||
use super::{FileTransferProtocol, FormMsg, Msg, UiMsg};
|
||||
use crate::ui::activities::auth::{
|
||||
RADIO_PROTOCOL_FTP, RADIO_PROTOCOL_FTPS, RADIO_PROTOCOL_S3, RADIO_PROTOCOL_SCP,
|
||||
RADIO_PROTOCOL_SFTP, RADIO_PROTOCOL_SMB, RADIO_PROTOCOL_WEBDAV,
|
||||
RADIO_PROTOCOL_FTP, RADIO_PROTOCOL_FTPS, RADIO_PROTOCOL_KUBE, RADIO_PROTOCOL_S3,
|
||||
RADIO_PROTOCOL_SCP, RADIO_PROTOCOL_SFTP, RADIO_PROTOCOL_SMB, RADIO_PROTOCOL_WEBDAV,
|
||||
};
|
||||
|
||||
// -- protocol
|
||||
@@ -31,9 +31,9 @@ impl ProtocolRadio {
|
||||
.modifiers(BorderType::Rounded),
|
||||
)
|
||||
.choices(if cfg!(smb) {
|
||||
&["SFTP", "SCP", "FTP", "FTPS", "S3", "WebDAV", "SMB"]
|
||||
&["SFTP", "SCP", "FTP", "FTPS", "S3", "Kube", "WebDAV", "SMB"]
|
||||
} else {
|
||||
&["SFTP", "SCP", "FTP", "FTPS", "S3", "WebDAV"]
|
||||
&["SFTP", "SCP", "FTP", "FTPS", "S3", "Kube", "WebDAV"]
|
||||
})
|
||||
.foreground(color)
|
||||
.rewind(true)
|
||||
@@ -50,6 +50,7 @@ impl ProtocolRadio {
|
||||
RADIO_PROTOCOL_FTPS => FileTransferProtocol::Ftp(true),
|
||||
RADIO_PROTOCOL_S3 => FileTransferProtocol::AwsS3,
|
||||
RADIO_PROTOCOL_SMB => FileTransferProtocol::Smb,
|
||||
RADIO_PROTOCOL_KUBE => FileTransferProtocol::Kube,
|
||||
RADIO_PROTOCOL_WEBDAV => FileTransferProtocol::WebDAV,
|
||||
_ => FileTransferProtocol::Sftp,
|
||||
}
|
||||
@@ -63,6 +64,7 @@ impl ProtocolRadio {
|
||||
FileTransferProtocol::Ftp(false) => RADIO_PROTOCOL_FTP,
|
||||
FileTransferProtocol::Ftp(true) => RADIO_PROTOCOL_FTPS,
|
||||
FileTransferProtocol::AwsS3 => RADIO_PROTOCOL_S3,
|
||||
FileTransferProtocol::Kube => RADIO_PROTOCOL_KUBE,
|
||||
FileTransferProtocol::Smb => RADIO_PROTOCOL_SMB,
|
||||
FileTransferProtocol::WebDAV => RADIO_PROTOCOL_WEBDAV,
|
||||
}
|
||||
@@ -827,3 +829,252 @@ impl Component<Msg, NoUserEvent> for InputWebDAVUri {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// kube
|
||||
|
||||
#[derive(MockComponent)]
|
||||
pub struct InputKubePodName {
|
||||
component: Input,
|
||||
}
|
||||
|
||||
impl InputKubePodName {
|
||||
pub fn new(bucket: &str, color: Color) -> Self {
|
||||
Self {
|
||||
component: Input::default()
|
||||
.borders(
|
||||
Borders::default()
|
||||
.color(color)
|
||||
.modifiers(BorderType::Rounded),
|
||||
)
|
||||
.foreground(color)
|
||||
.placeholder("pod-name", Style::default().fg(Color::Rgb(128, 128, 128)))
|
||||
.title("Pod name", Alignment::Left)
|
||||
.input_type(InputType::Text)
|
||||
.value(bucket),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component<Msg, NoUserEvent> for InputKubePodName {
|
||||
fn on(&mut self, ev: Event<NoUserEvent>) -> Option<Msg> {
|
||||
handle_input_ev(
|
||||
self,
|
||||
ev,
|
||||
Msg::Ui(UiMsg::KubePodNameBlurDown),
|
||||
Msg::Ui(UiMsg::KubePodNameBlurUp),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(MockComponent)]
|
||||
pub struct InputKubeNamespace {
|
||||
component: Input,
|
||||
}
|
||||
|
||||
impl InputKubeNamespace {
|
||||
pub fn new(bucket: &str, color: Color) -> Self {
|
||||
Self {
|
||||
component: Input::default()
|
||||
.borders(
|
||||
Borders::default()
|
||||
.color(color)
|
||||
.modifiers(BorderType::Rounded),
|
||||
)
|
||||
.foreground(color)
|
||||
.placeholder("namespace", Style::default().fg(Color::Rgb(128, 128, 128)))
|
||||
.title("Pod namespace (optional)", Alignment::Left)
|
||||
.input_type(InputType::Text)
|
||||
.value(bucket),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component<Msg, NoUserEvent> for InputKubeNamespace {
|
||||
fn on(&mut self, ev: Event<NoUserEvent>) -> Option<Msg> {
|
||||
handle_input_ev(
|
||||
self,
|
||||
ev,
|
||||
Msg::Ui(UiMsg::KubeNamespaceBlurDown),
|
||||
Msg::Ui(UiMsg::KubeNamespaceBlurUp),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(MockComponent)]
|
||||
pub struct InputKubeClusterUrl {
|
||||
component: Input,
|
||||
}
|
||||
|
||||
impl InputKubeClusterUrl {
|
||||
pub fn new(bucket: &str, color: Color) -> Self {
|
||||
Self {
|
||||
component: Input::default()
|
||||
.borders(
|
||||
Borders::default()
|
||||
.color(color)
|
||||
.modifiers(BorderType::Rounded),
|
||||
)
|
||||
.foreground(color)
|
||||
.placeholder(
|
||||
"cluster url",
|
||||
Style::default().fg(Color::Rgb(128, 128, 128)),
|
||||
)
|
||||
.title("Kube cluster url (optional)", Alignment::Left)
|
||||
.input_type(InputType::Text)
|
||||
.value(bucket),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component<Msg, NoUserEvent> for InputKubeClusterUrl {
|
||||
fn on(&mut self, ev: Event<NoUserEvent>) -> Option<Msg> {
|
||||
handle_input_ev(
|
||||
self,
|
||||
ev,
|
||||
Msg::Ui(UiMsg::KubeClusterUrlBlurDown),
|
||||
Msg::Ui(UiMsg::KubeClusterUrlBlurUp),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(MockComponent)]
|
||||
pub struct InputKubeContainer {
|
||||
component: Input,
|
||||
}
|
||||
|
||||
impl InputKubeContainer {
|
||||
pub fn new(bucket: &str, color: Color) -> Self {
|
||||
Self {
|
||||
component: Input::default()
|
||||
.borders(
|
||||
Borders::default()
|
||||
.color(color)
|
||||
.modifiers(BorderType::Rounded),
|
||||
)
|
||||
.foreground(color)
|
||||
.placeholder("container", Style::default().fg(Color::Rgb(128, 128, 128)))
|
||||
.title("Kube container", Alignment::Left)
|
||||
.input_type(InputType::Text)
|
||||
.value(bucket),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component<Msg, NoUserEvent> for InputKubeContainer {
|
||||
fn on(&mut self, ev: Event<NoUserEvent>) -> Option<Msg> {
|
||||
handle_input_ev(
|
||||
self,
|
||||
ev,
|
||||
Msg::Ui(UiMsg::KubeContainerBlurDown),
|
||||
Msg::Ui(UiMsg::KubeContainerBlurUp),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(MockComponent)]
|
||||
pub struct InputKubeUsername {
|
||||
component: Input,
|
||||
}
|
||||
|
||||
impl InputKubeUsername {
|
||||
pub fn new(bucket: &str, color: Color) -> Self {
|
||||
Self {
|
||||
component: Input::default()
|
||||
.borders(
|
||||
Borders::default()
|
||||
.color(color)
|
||||
.modifiers(BorderType::Rounded),
|
||||
)
|
||||
.foreground(color)
|
||||
.placeholder("username", Style::default().fg(Color::Rgb(128, 128, 128)))
|
||||
.title("Kube username (optional)", Alignment::Left)
|
||||
.input_type(InputType::Text)
|
||||
.value(bucket),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component<Msg, NoUserEvent> for InputKubeUsername {
|
||||
fn on(&mut self, ev: Event<NoUserEvent>) -> Option<Msg> {
|
||||
handle_input_ev(
|
||||
self,
|
||||
ev,
|
||||
Msg::Ui(UiMsg::KubeUsernameBlurDown),
|
||||
Msg::Ui(UiMsg::KubeUsernameBlurUp),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(MockComponent)]
|
||||
pub struct InputKubeClientCert {
|
||||
component: Input,
|
||||
}
|
||||
|
||||
impl InputKubeClientCert {
|
||||
pub fn new(bucket: &str, color: Color) -> Self {
|
||||
Self {
|
||||
component: Input::default()
|
||||
.borders(
|
||||
Borders::default()
|
||||
.color(color)
|
||||
.modifiers(BorderType::Rounded),
|
||||
)
|
||||
.foreground(color)
|
||||
.placeholder(
|
||||
"/home/user/.kube/client.crt",
|
||||
Style::default().fg(Color::Rgb(128, 128, 128)),
|
||||
)
|
||||
.title("Kube client cert path (optional)", Alignment::Left)
|
||||
.input_type(InputType::Text)
|
||||
.value(bucket),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component<Msg, NoUserEvent> for InputKubeClientCert {
|
||||
fn on(&mut self, ev: Event<NoUserEvent>) -> Option<Msg> {
|
||||
handle_input_ev(
|
||||
self,
|
||||
ev,
|
||||
Msg::Ui(UiMsg::KubeClientCertBlurDown),
|
||||
Msg::Ui(UiMsg::KubeClientCertBlurUp),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(MockComponent)]
|
||||
pub struct InputKubeClientKey {
|
||||
component: Input,
|
||||
}
|
||||
|
||||
impl InputKubeClientKey {
|
||||
pub fn new(bucket: &str, color: Color) -> Self {
|
||||
Self {
|
||||
component: Input::default()
|
||||
.borders(
|
||||
Borders::default()
|
||||
.color(color)
|
||||
.modifiers(BorderType::Rounded),
|
||||
)
|
||||
.foreground(color)
|
||||
.placeholder(
|
||||
"/home/user/.kube/client.key",
|
||||
Style::default().fg(Color::Rgb(128, 128, 128)),
|
||||
)
|
||||
.title("Kube client key path (optional)", Alignment::Left)
|
||||
.input_type(InputType::Text)
|
||||
.value(bucket),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component<Msg, NoUserEvent> for InputKubeClientKey {
|
||||
fn on(&mut self, ev: Event<NoUserEvent>) -> Option<Msg> {
|
||||
handle_input_ev(
|
||||
self,
|
||||
ev,
|
||||
Msg::Ui(UiMsg::KubeClientKeyBlurDown),
|
||||
Msg::Ui(UiMsg::KubeClientKeyBlurUp),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,12 @@ pub use bookmarks::{
|
||||
#[cfg(unix)]
|
||||
pub use form::InputSmbWorkgroup;
|
||||
pub use form::{
|
||||
InputAddress, InputLocalDirectory, InputPassword, InputPort, InputRemoteDirectory,
|
||||
InputS3AccessKey, InputS3Bucket, InputS3Endpoint, InputS3Profile, InputS3Region,
|
||||
InputS3SecretAccessKey, InputS3SecurityToken, InputS3SessionToken, InputSmbShare,
|
||||
InputUsername, InputWebDAVUri, ProtocolRadio, RadioS3NewPathStyle,
|
||||
InputAddress, InputKubeClientCert, InputKubeClientKey, InputKubeClusterUrl, InputKubeContainer,
|
||||
InputKubeNamespace, InputKubePodName, InputKubeUsername, InputLocalDirectory, InputPassword,
|
||||
InputPort, InputRemoteDirectory, InputS3AccessKey, InputS3Bucket, InputS3Endpoint,
|
||||
InputS3Profile, InputS3Region, InputS3SecretAccessKey, InputS3SecurityToken,
|
||||
InputS3SessionToken, InputSmbShare, InputUsername, InputWebDAVUri, ProtocolRadio,
|
||||
RadioS3NewPathStyle,
|
||||
};
|
||||
pub use popup::{
|
||||
ErrorPopup, InfoPopup, InstallUpdatePopup, Keybindings, QuitPopup, ReleaseNotes, WaitPopup,
|
||||
|
||||
@@ -14,6 +14,7 @@ impl AuthActivity {
|
||||
FileTransferProtocol::Sftp | FileTransferProtocol::Scp => 22,
|
||||
FileTransferProtocol::Ftp(_) => 21,
|
||||
FileTransferProtocol::AwsS3 => 22, // Doesn't matter, since not used
|
||||
FileTransferProtocol::Kube => 22, // Doesn't matter, since not used
|
||||
FileTransferProtocol::Smb => 445,
|
||||
FileTransferProtocol::WebDAV => 80, // Doesn't matter, since not used
|
||||
}
|
||||
@@ -38,6 +39,7 @@ impl AuthActivity {
|
||||
pub(super) fn collect_host_params(&self) -> Result<FileTransferParams, &'static str> {
|
||||
match self.protocol {
|
||||
FileTransferProtocol::AwsS3 => self.collect_s3_host_params(),
|
||||
FileTransferProtocol::Kube => self.collect_kube_host_params(),
|
||||
FileTransferProtocol::Smb => self.collect_smb_host_params(),
|
||||
FileTransferProtocol::Ftp(_)
|
||||
| FileTransferProtocol::Scp
|
||||
@@ -80,6 +82,20 @@ impl AuthActivity {
|
||||
})
|
||||
}
|
||||
|
||||
/// Get input values from fields or return an error if fields are invalid to work as aws s3
|
||||
pub(super) fn collect_kube_host_params(&self) -> Result<FileTransferParams, &'static str> {
|
||||
let params = self.get_kube_params_input();
|
||||
if params.pod.is_empty() {
|
||||
return Err("Invalid pod name");
|
||||
}
|
||||
Ok(FileTransferParams {
|
||||
protocol: FileTransferProtocol::Kube,
|
||||
params: ProtocolParams::Kube(params),
|
||||
local_path: self.get_input_local_directory(),
|
||||
remote_path: self.get_input_remote_directory(),
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn collect_smb_host_params(&self) -> Result<FileTransferParams, &'static str> {
|
||||
let params = self.get_smb_params_input();
|
||||
if params.address.is_empty() {
|
||||
|
||||
@@ -29,8 +29,9 @@ const RADIO_PROTOCOL_SCP: usize = 1;
|
||||
const RADIO_PROTOCOL_FTP: usize = 2;
|
||||
const RADIO_PROTOCOL_FTPS: usize = 3;
|
||||
const RADIO_PROTOCOL_S3: usize = 4;
|
||||
const RADIO_PROTOCOL_WEBDAV: usize = 5;
|
||||
const RADIO_PROTOCOL_SMB: usize = 6;
|
||||
const RADIO_PROTOCOL_KUBE: usize = 5;
|
||||
const RADIO_PROTOCOL_WEBDAV: usize = 6;
|
||||
const RADIO_PROTOCOL_SMB: usize = 7;
|
||||
|
||||
// -- components
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
|
||||
@@ -47,6 +48,13 @@ pub enum Id {
|
||||
InfoPopup,
|
||||
InstallUpdatePopup,
|
||||
Keybindings,
|
||||
KubePodName,
|
||||
KubeContainer,
|
||||
KubeNamespace,
|
||||
KubeClusterUrl,
|
||||
KubeUsername,
|
||||
KubeClientCert,
|
||||
KubeClientKey,
|
||||
LocalDirectory,
|
||||
NewVersionChangelog,
|
||||
NewVersionDisclaimer,
|
||||
@@ -111,6 +119,20 @@ pub enum UiMsg {
|
||||
CloseKeybindingsPopup,
|
||||
CloseQuitPopup,
|
||||
CloseSaveBookmark,
|
||||
KubePodNameBlurDown,
|
||||
KubePodNameBlurUp,
|
||||
KubeContainerBlurDown,
|
||||
KubeContainerBlurUp,
|
||||
KubeNamespaceBlurDown,
|
||||
KubeNamespaceBlurUp,
|
||||
KubeClusterUrlBlurDown,
|
||||
KubeClusterUrlBlurUp,
|
||||
KubeUsernameBlurDown,
|
||||
KubeUsernameBlurUp,
|
||||
KubeClientCertBlurDown,
|
||||
KubeClientCertBlurUp,
|
||||
KubeClientKeyBlurDown,
|
||||
KubeClientKeyBlurUp,
|
||||
LocalDirectoryBlurDown,
|
||||
LocalDirectoryBlurUp,
|
||||
ParamsFormBlur,
|
||||
@@ -167,6 +189,7 @@ pub enum UiMsg {
|
||||
enum InputMask {
|
||||
Generic,
|
||||
AwsS3,
|
||||
Kube,
|
||||
Smb,
|
||||
WebDAV,
|
||||
}
|
||||
@@ -244,6 +267,7 @@ impl AuthActivity {
|
||||
FileTransferProtocol::Ftp(_)
|
||||
| FileTransferProtocol::Scp
|
||||
| FileTransferProtocol::Sftp => InputMask::Generic,
|
||||
FileTransferProtocol::Kube => InputMask::Kube,
|
||||
FileTransferProtocol::Smb => InputMask::Smb,
|
||||
FileTransferProtocol::WebDAV => InputMask::WebDAV,
|
||||
}
|
||||
|
||||
@@ -70,6 +70,7 @@ impl AuthActivity {
|
||||
InputMask::Generic => &Id::Password,
|
||||
InputMask::Smb => &Id::Password,
|
||||
InputMask::AwsS3 => &Id::S3Bucket,
|
||||
InputMask::Kube => &Id::KubePodName,
|
||||
InputMask::WebDAV => &Id::Password,
|
||||
})
|
||||
.is_ok());
|
||||
@@ -83,6 +84,7 @@ impl AuthActivity {
|
||||
InputMask::Generic => &Id::Password,
|
||||
InputMask::Smb => &Id::Password,
|
||||
InputMask::AwsS3 => &Id::S3Bucket,
|
||||
InputMask::Kube => &Id::KubePodName,
|
||||
InputMask::WebDAV => &Id::Password,
|
||||
})
|
||||
.is_ok());
|
||||
@@ -179,6 +181,7 @@ impl AuthActivity {
|
||||
#[cfg(windows)]
|
||||
InputMask::Smb => &Id::RemoteDirectory,
|
||||
InputMask::AwsS3 => panic!("this shouldn't happen (password on s3)"),
|
||||
InputMask::Kube => panic!("this shouldn't happen (password on kube)"),
|
||||
InputMask::WebDAV => &Id::RemoteDirectory,
|
||||
})
|
||||
.is_ok());
|
||||
@@ -192,8 +195,8 @@ impl AuthActivity {
|
||||
.active(match self.input_mask() {
|
||||
InputMask::Generic => &Id::Username,
|
||||
InputMask::Smb => &Id::SmbShare,
|
||||
InputMask::AwsS3 | InputMask::WebDAV =>
|
||||
panic!("this shouldn't happen (port on s3)"),
|
||||
InputMask::AwsS3 | InputMask::Kube | InputMask::WebDAV =>
|
||||
panic!("this shouldn't happen (port on s3/kube/webdav)"),
|
||||
})
|
||||
.is_ok());
|
||||
}
|
||||
@@ -207,6 +210,7 @@ impl AuthActivity {
|
||||
InputMask::Generic => &Id::Address,
|
||||
InputMask::Smb => &Id::Address,
|
||||
InputMask::AwsS3 => &Id::S3Bucket,
|
||||
InputMask::Kube => &Id::KubePodName,
|
||||
InputMask::WebDAV => &Id::WebDAVUri,
|
||||
})
|
||||
.is_ok());
|
||||
@@ -229,6 +233,7 @@ impl AuthActivity {
|
||||
InputMask::Smb => &Id::SmbWorkgroup,
|
||||
#[cfg(windows)]
|
||||
InputMask::Smb => &Id::Password,
|
||||
InputMask::Kube => &Id::KubeClientKey,
|
||||
InputMask::AwsS3 => &Id::S3NewPathStyle,
|
||||
InputMask::WebDAV => &Id::Password,
|
||||
})
|
||||
@@ -288,6 +293,48 @@ impl AuthActivity {
|
||||
UiMsg::S3NewPathStyleBlurUp => {
|
||||
assert!(self.app.active(&Id::S3SessionToken).is_ok());
|
||||
}
|
||||
UiMsg::KubeClientCertBlurDown => {
|
||||
assert!(self.app.active(&Id::KubeClientKey).is_ok());
|
||||
}
|
||||
UiMsg::KubeClientCertBlurUp => {
|
||||
assert!(self.app.active(&Id::KubeUsername).is_ok());
|
||||
}
|
||||
UiMsg::KubeClientKeyBlurDown => {
|
||||
assert!(self.app.active(&Id::RemoteDirectory).is_ok());
|
||||
}
|
||||
UiMsg::KubeClientKeyBlurUp => {
|
||||
assert!(self.app.active(&Id::KubeClientCert).is_ok());
|
||||
}
|
||||
UiMsg::KubeContainerBlurDown => {
|
||||
assert!(self.app.active(&Id::KubeNamespace).is_ok());
|
||||
}
|
||||
UiMsg::KubeContainerBlurUp => {
|
||||
assert!(self.app.active(&Id::KubePodName).is_ok());
|
||||
}
|
||||
UiMsg::KubePodNameBlurDown => {
|
||||
assert!(self.app.active(&Id::KubeContainer).is_ok());
|
||||
}
|
||||
UiMsg::KubePodNameBlurUp => {
|
||||
assert!(self.app.active(&Id::Protocol).is_ok());
|
||||
}
|
||||
UiMsg::KubeNamespaceBlurDown => {
|
||||
assert!(self.app.active(&Id::KubeClusterUrl).is_ok());
|
||||
}
|
||||
UiMsg::KubeNamespaceBlurUp => {
|
||||
assert!(self.app.active(&Id::KubeContainer).is_ok());
|
||||
}
|
||||
UiMsg::KubeClusterUrlBlurDown => {
|
||||
assert!(self.app.active(&Id::KubeUsername).is_ok());
|
||||
}
|
||||
UiMsg::KubeClusterUrlBlurUp => {
|
||||
assert!(self.app.active(&Id::KubeNamespace).is_ok());
|
||||
}
|
||||
UiMsg::KubeUsernameBlurDown => {
|
||||
assert!(self.app.active(&Id::KubeClientCert).is_ok());
|
||||
}
|
||||
UiMsg::KubeUsernameBlurUp => {
|
||||
assert!(self.app.active(&Id::KubeClusterUrl).is_ok());
|
||||
}
|
||||
UiMsg::SmbShareBlurDown => {
|
||||
assert!(self.app.active(&Id::Username).is_ok());
|
||||
}
|
||||
@@ -337,6 +384,7 @@ impl AuthActivity {
|
||||
.active(match self.input_mask() {
|
||||
InputMask::Generic => &Id::Port,
|
||||
InputMask::Smb => &Id::SmbShare,
|
||||
InputMask::Kube => panic!("this shouldn't happen (username on kube)"),
|
||||
InputMask::AwsS3 => panic!("this shouldn't happen (username on s3)"),
|
||||
InputMask::WebDAV => &Id::WebDAVUri,
|
||||
})
|
||||
|
||||
@@ -13,7 +13,8 @@ use tuirealm::{State, StateValue, Sub, SubClause, SubEventClause};
|
||||
|
||||
use super::{components, AuthActivity, Context, FileTransferProtocol, Id, InputMask};
|
||||
use crate::filetransfer::params::{
|
||||
AwsS3Params, GenericProtocolParams, ProtocolParams, SmbParams, WebDAVProtocolParams,
|
||||
AwsS3Params, GenericProtocolParams, KubeProtocolParams, ProtocolParams, SmbParams,
|
||||
WebDAVProtocolParams,
|
||||
};
|
||||
use crate::filetransfer::FileTransferParams;
|
||||
use crate::utils::ui::{Popup, Size};
|
||||
@@ -60,6 +61,13 @@ impl AuthActivity {
|
||||
self.mount_s3_security_token("");
|
||||
self.mount_s3_session_token("");
|
||||
self.mount_s3_new_path_style(false);
|
||||
self.mount_kube_client_cert("");
|
||||
self.mount_kube_client_key("");
|
||||
self.mount_kube_cluster_url("");
|
||||
self.mount_kube_container("");
|
||||
self.mount_kube_namespace("");
|
||||
self.mount_kube_pod_name("");
|
||||
self.mount_kube_username("");
|
||||
self.mount_smb_share("");
|
||||
#[cfg(unix)]
|
||||
self.mount_smb_workgroup("");
|
||||
@@ -155,6 +163,16 @@ impl AuthActivity {
|
||||
)
|
||||
.direction(Direction::Vertical)
|
||||
.split(auth_chunks[4]),
|
||||
InputMask::Kube => Layout::default()
|
||||
.constraints([
|
||||
Constraint::Length(3), // ...
|
||||
Constraint::Length(3), // ...
|
||||
Constraint::Length(3), // ...
|
||||
Constraint::Length(3), // ...
|
||||
Constraint::Length(3), // remote directory
|
||||
])
|
||||
.direction(Direction::Vertical)
|
||||
.split(auth_chunks[4]),
|
||||
InputMask::Generic => Layout::default()
|
||||
.constraints(
|
||||
[
|
||||
@@ -238,6 +256,13 @@ impl AuthActivity {
|
||||
self.app.view(&view_ids[2], f, input_mask[2]);
|
||||
self.app.view(&view_ids[3], f, input_mask[3]);
|
||||
}
|
||||
InputMask::Kube => {
|
||||
let view_ids = self.get_kube_view();
|
||||
self.app.view(&view_ids[0], f, input_mask[0]);
|
||||
self.app.view(&view_ids[1], f, input_mask[1]);
|
||||
self.app.view(&view_ids[2], f, input_mask[2]);
|
||||
self.app.view(&view_ids[3], f, input_mask[3]);
|
||||
}
|
||||
InputMask::Smb => {
|
||||
let view_ids = self.get_smb_view();
|
||||
self.app.view(&view_ids[0], f, input_mask[0]);
|
||||
@@ -791,6 +816,90 @@ impl AuthActivity {
|
||||
.is_ok());
|
||||
}
|
||||
|
||||
pub(super) fn mount_kube_pod_name(&mut self, value: &str) {
|
||||
let color = self.theme().auth_address;
|
||||
assert!(self
|
||||
.app
|
||||
.remount(
|
||||
Id::KubePodName,
|
||||
Box::new(components::InputKubePodName::new(value, color)),
|
||||
vec![]
|
||||
)
|
||||
.is_ok());
|
||||
}
|
||||
|
||||
pub(super) fn mount_kube_container(&mut self, value: &str) {
|
||||
let color = self.theme().auth_password;
|
||||
assert!(self
|
||||
.app
|
||||
.remount(
|
||||
Id::KubeContainer,
|
||||
Box::new(components::InputKubeContainer::new(value, color)),
|
||||
vec![]
|
||||
)
|
||||
.is_ok());
|
||||
}
|
||||
|
||||
pub(super) fn mount_kube_namespace(&mut self, value: &str) {
|
||||
let color = self.theme().auth_port;
|
||||
assert!(self
|
||||
.app
|
||||
.remount(
|
||||
Id::KubeNamespace,
|
||||
Box::new(components::InputKubeNamespace::new(value, color)),
|
||||
vec![]
|
||||
)
|
||||
.is_ok());
|
||||
}
|
||||
|
||||
pub(super) fn mount_kube_cluster_url(&mut self, value: &str) {
|
||||
let color = self.theme().auth_username;
|
||||
assert!(self
|
||||
.app
|
||||
.remount(
|
||||
Id::KubeClusterUrl,
|
||||
Box::new(components::InputKubeClusterUrl::new(value, color)),
|
||||
vec![]
|
||||
)
|
||||
.is_ok());
|
||||
}
|
||||
|
||||
pub(super) fn mount_kube_username(&mut self, value: &str) {
|
||||
let color = self.theme().auth_password;
|
||||
assert!(self
|
||||
.app
|
||||
.remount(
|
||||
Id::KubeUsername,
|
||||
Box::new(components::InputKubeUsername::new(value, color)),
|
||||
vec![]
|
||||
)
|
||||
.is_ok());
|
||||
}
|
||||
|
||||
pub(super) fn mount_kube_client_cert(&mut self, value: &str) {
|
||||
let color = self.theme().auth_address;
|
||||
assert!(self
|
||||
.app
|
||||
.remount(
|
||||
Id::KubeClientCert,
|
||||
Box::new(components::InputKubeClientCert::new(value, color)),
|
||||
vec![]
|
||||
)
|
||||
.is_ok());
|
||||
}
|
||||
|
||||
pub(super) fn mount_kube_client_key(&mut self, value: &str) {
|
||||
let color = self.theme().auth_port;
|
||||
assert!(self
|
||||
.app
|
||||
.remount(
|
||||
Id::KubeClientKey,
|
||||
Box::new(components::InputKubeClientKey::new(value, color)),
|
||||
vec![]
|
||||
)
|
||||
.is_ok());
|
||||
}
|
||||
|
||||
pub(crate) fn mount_smb_share(&mut self, share: &str) {
|
||||
let color = self.theme().auth_password;
|
||||
assert!(self
|
||||
@@ -863,6 +972,26 @@ impl AuthActivity {
|
||||
.new_path_style(new_path_style)
|
||||
}
|
||||
|
||||
/// Collect s3 input values from view
|
||||
pub(super) fn get_kube_params_input(&self) -> KubeProtocolParams {
|
||||
let pod = self.get_input_kube_pod_name();
|
||||
let container = self.get_input_kube_container();
|
||||
let namespace = self.get_input_kube_namespace();
|
||||
let cluster_url = self.get_input_kube_cluster_url();
|
||||
let username = self.get_input_kube_username();
|
||||
let client_cert = self.get_input_kube_client_cert();
|
||||
let client_key = self.get_input_kube_client_key();
|
||||
KubeProtocolParams {
|
||||
pod,
|
||||
container,
|
||||
namespace,
|
||||
cluster_url,
|
||||
username,
|
||||
client_cert,
|
||||
client_key,
|
||||
}
|
||||
}
|
||||
|
||||
/// Collect s3 input values from view
|
||||
#[cfg(unix)]
|
||||
pub(super) fn get_smb_params_input(&self) -> SmbParams {
|
||||
@@ -1025,6 +1154,55 @@ impl AuthActivity {
|
||||
)
|
||||
}
|
||||
|
||||
pub(super) fn get_input_kube_pod_name(&self) -> String {
|
||||
match self.app.state(&Id::KubePodName) {
|
||||
Ok(State::One(StateValue::String(x))) => x,
|
||||
_ => String::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn get_input_kube_container(&self) -> String {
|
||||
match self.app.state(&Id::KubeContainer) {
|
||||
Ok(State::One(StateValue::String(x))) => x,
|
||||
_ => String::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn get_input_kube_namespace(&self) -> Option<String> {
|
||||
match self.app.state(&Id::KubeNamespace) {
|
||||
Ok(State::One(StateValue::String(x))) if !x.is_empty() => Some(x),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn get_input_kube_cluster_url(&self) -> Option<String> {
|
||||
match self.app.state(&Id::KubeClusterUrl) {
|
||||
Ok(State::One(StateValue::String(x))) if !x.is_empty() => Some(x),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn get_input_kube_username(&self) -> Option<String> {
|
||||
match self.app.state(&Id::KubeUsername) {
|
||||
Ok(State::One(StateValue::String(x))) if !x.is_empty() => Some(x),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn get_input_kube_client_cert(&self) -> Option<String> {
|
||||
match self.app.state(&Id::KubeClientCert) {
|
||||
Ok(State::One(StateValue::String(x))) if !x.is_empty() => Some(x),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn get_input_kube_client_key(&self) -> Option<String> {
|
||||
match self.app.state(&Id::KubeClientKey) {
|
||||
Ok(State::One(StateValue::String(x))) if !x.is_empty() => Some(x),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn get_input_smb_share(&self) -> String {
|
||||
match self.app.state(&Id::SmbShare) {
|
||||
Ok(State::One(StateValue::String(x))) => x,
|
||||
@@ -1063,6 +1241,7 @@ impl AuthActivity {
|
||||
match self.input_mask() {
|
||||
InputMask::AwsS3 => 12,
|
||||
InputMask::Generic => 12,
|
||||
InputMask::Kube => 12,
|
||||
InputMask::Smb => 12,
|
||||
InputMask::WebDAV => 12,
|
||||
}
|
||||
@@ -1104,6 +1283,24 @@ impl AuthActivity {
|
||||
protocol, username, params.address, params.port
|
||||
)
|
||||
}
|
||||
ProtocolParams::Kube(params) => {
|
||||
format!(
|
||||
"{}://{}@{}{}{}",
|
||||
protocol,
|
||||
params.container,
|
||||
params.pod,
|
||||
params
|
||||
.namespace
|
||||
.as_deref()
|
||||
.map(|x| format!("/{x}"))
|
||||
.unwrap_or_default(),
|
||||
params
|
||||
.cluster_url
|
||||
.as_deref()
|
||||
.map(|x| format!("@{x}"))
|
||||
.unwrap_or_default()
|
||||
)
|
||||
}
|
||||
#[cfg(unix)]
|
||||
ProtocolParams::Smb(params) => {
|
||||
let username: String = match params.username {
|
||||
@@ -1189,6 +1386,54 @@ impl AuthActivity {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the visible element in the kube form, based on current focus
|
||||
fn get_kube_view(&self) -> [Id; 4] {
|
||||
match self.app.focus() {
|
||||
Some(&Id::KubePodName) => [
|
||||
Id::KubePodName,
|
||||
Id::KubeContainer,
|
||||
Id::KubeNamespace,
|
||||
Id::KubeClusterUrl,
|
||||
],
|
||||
Some(&Id::KubeUsername) => [
|
||||
Id::KubeContainer,
|
||||
Id::KubeNamespace,
|
||||
Id::KubeClusterUrl,
|
||||
Id::KubeUsername,
|
||||
],
|
||||
Some(&Id::KubeClientCert) => [
|
||||
Id::KubeNamespace,
|
||||
Id::KubeClusterUrl,
|
||||
Id::KubeUsername,
|
||||
Id::KubeClientCert,
|
||||
],
|
||||
Some(&Id::KubeClientKey) => [
|
||||
Id::KubeClusterUrl,
|
||||
Id::KubeUsername,
|
||||
Id::KubeClientCert,
|
||||
Id::KubeClientKey,
|
||||
],
|
||||
Some(&Id::RemoteDirectory) => [
|
||||
Id::KubeUsername,
|
||||
Id::KubeClientCert,
|
||||
Id::KubeClientKey,
|
||||
Id::RemoteDirectory,
|
||||
],
|
||||
Some(&Id::LocalDirectory) => [
|
||||
Id::KubeClientCert,
|
||||
Id::KubeClientKey,
|
||||
Id::RemoteDirectory,
|
||||
Id::LocalDirectory,
|
||||
],
|
||||
_ => [
|
||||
Id::KubePodName,
|
||||
Id::KubeContainer,
|
||||
Id::KubeNamespace,
|
||||
Id::KubeClusterUrl,
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn get_smb_view(&self) -> [Id; 4] {
|
||||
match self.app.focus() {
|
||||
|
||||
@@ -111,6 +111,7 @@ impl FileTransferActivity {
|
||||
match &ft_params.params {
|
||||
ProtocolParams::Generic(params) => params.address.clone(),
|
||||
ProtocolParams::AwsS3(params) => params.bucket_name.clone(),
|
||||
ProtocolParams::Kube(params) => params.pod.clone(),
|
||||
ProtocolParams::Smb(params) => params.address.clone(),
|
||||
ProtocolParams::WebDAV(params) => params.uri.clone(),
|
||||
}
|
||||
@@ -135,6 +136,13 @@ impl FileTransferActivity {
|
||||
);
|
||||
format!("Connecting to {}…", params.bucket_name)
|
||||
}
|
||||
ProtocolParams::Kube(params) => {
|
||||
info!(
|
||||
"Client is not connected to remote; connecting to pod {}",
|
||||
params.pod,
|
||||
);
|
||||
format!("Connecting to {}…", params.pod)
|
||||
}
|
||||
ProtocolParams::Smb(params) => {
|
||||
info!(
|
||||
"Client is not connected to remote; connecting to {}:{}",
|
||||
|
||||
@@ -12,8 +12,8 @@ use super::{ConfigMsg, Msg};
|
||||
use crate::explorer::GroupDirs as GroupDirsEnum;
|
||||
use crate::filetransfer::FileTransferProtocol;
|
||||
use crate::ui::activities::setup::{
|
||||
RADIO_PROTOCOL_FTP, RADIO_PROTOCOL_FTPS, RADIO_PROTOCOL_S3, RADIO_PROTOCOL_SCP,
|
||||
RADIO_PROTOCOL_SFTP, RADIO_PROTOCOL_SMB, RADIO_PROTOCOL_WEBDAV,
|
||||
RADIO_PROTOCOL_FTP, RADIO_PROTOCOL_FTPS, RADIO_PROTOCOL_KUBE, RADIO_PROTOCOL_S3,
|
||||
RADIO_PROTOCOL_SCP, RADIO_PROTOCOL_SFTP, RADIO_PROTOCOL_SMB, RADIO_PROTOCOL_WEBDAV,
|
||||
};
|
||||
use crate::utils::parser::parse_bytesize;
|
||||
|
||||
@@ -67,7 +67,7 @@ impl DefaultProtocol {
|
||||
.color(Color::Cyan)
|
||||
.modifiers(BorderType::Rounded),
|
||||
)
|
||||
.choices(&["SFTP", "SCP", "FTP", "FTPS", "S3", "SMB", "WebDAV"])
|
||||
.choices(&["SFTP", "SCP", "FTP", "FTPS", "Kube", "S3", "SMB", "WebDAV"])
|
||||
.foreground(Color::Cyan)
|
||||
.rewind(true)
|
||||
.title("Default protocol", Alignment::Left)
|
||||
@@ -76,6 +76,7 @@ impl DefaultProtocol {
|
||||
FileTransferProtocol::Scp => RADIO_PROTOCOL_SCP,
|
||||
FileTransferProtocol::Ftp(false) => RADIO_PROTOCOL_FTP,
|
||||
FileTransferProtocol::Ftp(true) => RADIO_PROTOCOL_FTPS,
|
||||
FileTransferProtocol::Kube => RADIO_PROTOCOL_KUBE,
|
||||
FileTransferProtocol::AwsS3 => RADIO_PROTOCOL_S3,
|
||||
FileTransferProtocol::Smb => RADIO_PROTOCOL_SMB,
|
||||
FileTransferProtocol::WebDAV => RADIO_PROTOCOL_WEBDAV,
|
||||
|
||||
@@ -29,9 +29,10 @@ const RADIO_PROTOCOL_SFTP: usize = 0;
|
||||
const RADIO_PROTOCOL_SCP: usize = 1;
|
||||
const RADIO_PROTOCOL_FTP: usize = 2;
|
||||
const RADIO_PROTOCOL_FTPS: usize = 3;
|
||||
const RADIO_PROTOCOL_S3: usize = 4;
|
||||
const RADIO_PROTOCOL_SMB: usize = 5;
|
||||
const RADIO_PROTOCOL_WEBDAV: usize = 6;
|
||||
const RADIO_PROTOCOL_KUBE: usize = 4;
|
||||
const RADIO_PROTOCOL_S3: usize = 5;
|
||||
const RADIO_PROTOCOL_SMB: usize = 6;
|
||||
const RADIO_PROTOCOL_WEBDAV: usize = 7;
|
||||
|
||||
// -- components
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
|
||||
|
||||
@@ -11,7 +11,8 @@ use tuirealm::tui::layout::{Constraint, Direction, Layout};
|
||||
use tuirealm::{State, StateValue};
|
||||
|
||||
use super::{
|
||||
components, Context, Id, IdCommon, IdConfig, SetupActivity, ViewLayout, RADIO_PROTOCOL_WEBDAV,
|
||||
components, Context, Id, IdCommon, IdConfig, SetupActivity, ViewLayout, RADIO_PROTOCOL_KUBE,
|
||||
RADIO_PROTOCOL_WEBDAV,
|
||||
};
|
||||
use crate::explorer::GroupDirs;
|
||||
use crate::filetransfer::FileTransferProtocol;
|
||||
@@ -277,6 +278,7 @@ impl SetupActivity {
|
||||
RADIO_PROTOCOL_SCP => FileTransferProtocol::Scp,
|
||||
RADIO_PROTOCOL_FTP => FileTransferProtocol::Ftp(false),
|
||||
RADIO_PROTOCOL_FTPS => FileTransferProtocol::Ftp(true),
|
||||
RADIO_PROTOCOL_KUBE => FileTransferProtocol::Kube,
|
||||
RADIO_PROTOCOL_S3 => FileTransferProtocol::AwsS3,
|
||||
RADIO_PROTOCOL_SMB => FileTransferProtocol::Smb,
|
||||
RADIO_PROTOCOL_WEBDAV => FileTransferProtocol::WebDAV,
|
||||
|
||||
@@ -15,7 +15,7 @@ use tuirealm::utils::parser as tuirealm_parser;
|
||||
#[cfg(smb)]
|
||||
use crate::filetransfer::params::SmbParams;
|
||||
use crate::filetransfer::params::{
|
||||
AwsS3Params, GenericProtocolParams, ProtocolParams, WebDAVProtocolParams,
|
||||
AwsS3Params, GenericProtocolParams, KubeProtocolParams, ProtocolParams, WebDAVProtocolParams,
|
||||
};
|
||||
use crate::filetransfer::{FileTransferParams, FileTransferProtocol};
|
||||
#[cfg(not(test))] // NOTE: don't use configuration during tests
|
||||
@@ -53,7 +53,15 @@ static REMOTE_GENERIC_OPT_REGEX: Lazy<Regex> = lazy_regex!(
|
||||
* - group 4: Some(path) | None
|
||||
*/
|
||||
static REMOTE_WEBDAV_OPT_REGEX: Lazy<Regex> =
|
||||
lazy_regex!(r"(?:([^:]+):)(?:(.+[^@])@)(?:([^/]+))(?:/(.+))?");
|
||||
lazy_regex!(r"(?:([^:]+):)(?:(.+[^@])@)(?:([^/]+))(?:(.+))?");
|
||||
|
||||
/**
|
||||
* Regex matches: {container}@{pod}/{path}
|
||||
* - group 1: Container
|
||||
* - group 2: Pod
|
||||
* - group 3: Some(path) | None
|
||||
*/
|
||||
static REMOTE_KUBE_OPT_REGEX: Lazy<Regex> = lazy_regex!(r"(?:(.+[^@])@)(?:([^/]+))(?:(.+))?");
|
||||
|
||||
/**
|
||||
* Regex matches:
|
||||
@@ -162,6 +170,7 @@ pub fn parse_remote_opt(s: &str) -> Result<FileTransferParams, String> {
|
||||
// Match against regex for protocol type
|
||||
match protocol {
|
||||
FileTransferProtocol::AwsS3 => parse_s3_remote_opt(remote.as_str()),
|
||||
FileTransferProtocol::Kube => parse_kube_remote_opt(remote.as_str()),
|
||||
#[cfg(smb)]
|
||||
FileTransferProtocol::Smb => parse_smb_remote_opts(remote.as_str()),
|
||||
FileTransferProtocol::WebDAV => {
|
||||
@@ -302,6 +311,37 @@ fn parse_s3_remote_opt(s: &str) -> Result<FileTransferParams, String> {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_kube_remote_opt(s: &str) -> Result<FileTransferParams, String> {
|
||||
match REMOTE_KUBE_OPT_REGEX.captures(s) {
|
||||
Some(groups) => {
|
||||
let container: String = groups
|
||||
.get(1)
|
||||
.map(|x| x.as_str().to_string())
|
||||
.unwrap_or_default();
|
||||
let pod: String = groups
|
||||
.get(2)
|
||||
.map(|x| x.as_str().to_string())
|
||||
.unwrap_or_default();
|
||||
let remote_path: Option<PathBuf> =
|
||||
groups.get(3).map(|group| PathBuf::from(group.as_str()));
|
||||
Ok(FileTransferParams::new(
|
||||
FileTransferProtocol::Kube,
|
||||
ProtocolParams::Kube(KubeProtocolParams {
|
||||
pod,
|
||||
container,
|
||||
namespace: None,
|
||||
cluster_url: None,
|
||||
username: None,
|
||||
client_cert: None,
|
||||
client_key: None,
|
||||
}),
|
||||
)
|
||||
.remote_path(remote_path))
|
||||
}
|
||||
None => Err(String::from("Bad remote host syntax!")),
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse remote options for smb protocol
|
||||
#[cfg(smb_unix)]
|
||||
fn parse_smb_remote_opts(s: &str) -> Result<FileTransferParams, String> {
|
||||
@@ -630,6 +670,12 @@ mod tests {
|
||||
assert_eq!(params.uri.as_str(), "http://myserver:4445");
|
||||
assert_eq!(params.username.as_str(), "omar");
|
||||
assert_eq!(params.password.as_str(), "password");
|
||||
|
||||
// remote path
|
||||
assert_eq!(
|
||||
result.remote_path.unwrap(),
|
||||
PathBuf::from("/myshare/dir/subdir")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -706,6 +752,24 @@ mod tests {
|
||||
assert_eq!(params.region.as_deref().unwrap(), "eu-central-1");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_parse_kube_address() {
|
||||
let result = parse_remote_opt("kube://alpine@my-pod/tmp").ok().unwrap();
|
||||
let params = result.params.kube_params().unwrap();
|
||||
|
||||
assert_eq!(params.container.as_str(), "alpine");
|
||||
assert_eq!(params.pod.as_str(), "my-pod");
|
||||
assert_eq!(params.namespace, None);
|
||||
assert_eq!(params.cluster_url, None);
|
||||
assert_eq!(params.username, None);
|
||||
assert_eq!(params.client_cert, None);
|
||||
assert_eq!(params.client_key, None);
|
||||
assert_eq!(
|
||||
result.remote_path.as_deref().unwrap(),
|
||||
std::path::Path::new("/tmp")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(smb_unix)]
|
||||
fn should_parse_smb_address() {
|
||||
|
||||
Reference in New Issue
Block a user