mirror of
https://github.com/veeso/termscp.git
synced 2026-09-26 05:51:20 -07:00
feat: Pods and container explorer for Kube protocol (#281)
This commit is contained in:
@@ -41,6 +41,10 @@
|
|||||||
|
|
||||||
Released on
|
Released on
|
||||||
|
|
||||||
|
- [Issue 268](https://github.com/veeso/termscp/issues/268): Pods and container explorer for Kube protocol.
|
||||||
|
- BREAKING ‼️ Kube address argument has changed; see manual!
|
||||||
|
- Pod and container argumets have been removed; from now on you will connect with the following syntax to the provided namespace: `/pod-name/container-name/path/to/file`
|
||||||
|
|
||||||
## 0.14.0
|
## 0.14.0
|
||||||
|
|
||||||
Released on 17/07/2024
|
Released on 17/07/2024
|
||||||
|
|||||||
Generated
+83
@@ -568,6 +568,19 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dbus-secret-service"
|
||||||
|
version = "4.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1caa0c241c01ad8d99a78d553567d38f873dd3ac16eca33a5370d650ab25584e"
|
||||||
|
dependencies = [
|
||||||
|
"dbus",
|
||||||
|
"futures-util",
|
||||||
|
"num",
|
||||||
|
"once_cell",
|
||||||
|
"rand",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "debug-helper"
|
name = "debug-helper"
|
||||||
version = "0.3.13"
|
version = "0.3.13"
|
||||||
@@ -1450,6 +1463,12 @@ name = "keyring"
|
|||||||
version = "3.3.0"
|
version = "3.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5fa83d1ca02db069b5fbe94b23b584d588e989218310c9c15015bb5571ef1a94"
|
checksum = "5fa83d1ca02db069b5fbe94b23b584d588e989218310c9c15015bb5571ef1a94"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"dbus-secret-service",
|
||||||
|
"security-framework",
|
||||||
|
"windows-sys 0.59.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kqueue"
|
name = "kqueue"
|
||||||
@@ -1809,12 +1828,76 @@ dependencies = [
|
|||||||
"tauri-winrt-notification",
|
"tauri-winrt-notification",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23"
|
||||||
|
dependencies = [
|
||||||
|
"num-bigint",
|
||||||
|
"num-complex",
|
||||||
|
"num-integer",
|
||||||
|
"num-iter",
|
||||||
|
"num-rational",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-bigint"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
|
||||||
|
dependencies = [
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-complex"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-conv"
|
name = "num-conv"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-integer"
|
||||||
|
version = "0.1.46"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-iter"
|
||||||
|
version = "0.1.45"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-rational"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
|
||||||
|
dependencies = [
|
||||||
|
"num-bigint",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.19"
|
version = "0.2.19"
|
||||||
|
|||||||
+1
-1
@@ -46,7 +46,7 @@ dirs = "^5.0"
|
|||||||
edit = "^0.1"
|
edit = "^0.1"
|
||||||
filetime = "^0.2"
|
filetime = "^0.2"
|
||||||
hostname = "^0.4"
|
hostname = "^0.4"
|
||||||
keyring = { version = "^3", optional = true }
|
keyring = { version = "^3", optional = true, features = ["apple-native", "windows-native", "sync-secret-service"] }
|
||||||
lazy-regex = "^3"
|
lazy-regex = "^3"
|
||||||
lazy_static = "^1"
|
lazy_static = "^1"
|
||||||
log = "^0.4"
|
log = "^0.4"
|
||||||
|
|||||||
+1
-1
@@ -133,7 +133,7 @@ s3://buckethead@eu-central-1:default:/assets
|
|||||||
Falls Sie eine Verbindung zu Kube herstellen möchten, verwenden Sie die folgende Syntax
|
Falls Sie eine Verbindung zu Kube herstellen möchten, verwenden Sie die folgende Syntax
|
||||||
|
|
||||||
```txt
|
```txt
|
||||||
kube://<container>@<pod></path>
|
kube://[namespace][@<cluster_url>][$</path>]
|
||||||
```
|
```
|
||||||
|
|
||||||
#### SMB Adressargument
|
#### SMB Adressargument
|
||||||
|
|||||||
+1
-1
@@ -110,7 +110,7 @@ s3://buckethead@eu-central-1:default:/assets
|
|||||||
En caso de que quieras conectarte a Kube, utiliza la siguiente sintaxis
|
En caso de que quieras conectarte a Kube, utiliza la siguiente sintaxis
|
||||||
|
|
||||||
```txt
|
```txt
|
||||||
kube://<container>@<pod></path>
|
kube://[namespace][@<cluster_url>][$</path>]
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Argumento de dirección de WebDAV
|
#### Argumento de dirección de WebDAV
|
||||||
|
|||||||
+1
-1
@@ -108,7 +108,7 @@ s3://buckethead@eu-central-1:default:/assets
|
|||||||
Si vous souhaitez vous connecter à Kube, utilisez la syntaxe suivante
|
Si vous souhaitez vous connecter à Kube, utilisez la syntaxe suivante
|
||||||
|
|
||||||
```txt
|
```txt
|
||||||
kube://<container>@<pod></path>
|
kube://[namespace][@<cluster_url>][$</path>]
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Argument d'adresse WebDAV
|
#### Argument d'adresse WebDAV
|
||||||
|
|||||||
+1
-1
@@ -106,7 +106,7 @@ s3://buckethead@eu-central-1:default:/assets
|
|||||||
Nel caso tu voglia connetterti a Kube usa la seguente sintassi
|
Nel caso tu voglia connetterti a Kube usa la seguente sintassi
|
||||||
|
|
||||||
```txt
|
```txt
|
||||||
kube://<container>@<pod></path>
|
kube://[namespace][@<cluster_url>][$</path>]
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Argomento indirizzo per WebDAV
|
#### Argomento indirizzo per WebDAV
|
||||||
|
|||||||
+1
-1
@@ -111,7 +111,7 @@ s3://buckethead@eu-central-1:default:/assets
|
|||||||
In case you want to connect to Kube use the following syntax
|
In case you want to connect to Kube use the following syntax
|
||||||
|
|
||||||
```txt
|
```txt
|
||||||
kube://<container>@<pod></path>
|
kube://[namespace][@<cluster_url>][$</path>]
|
||||||
```
|
```
|
||||||
|
|
||||||
#### WebDAV address argument
|
#### WebDAV address argument
|
||||||
|
|||||||
+1
-1
@@ -111,7 +111,7 @@ s3://buckethead@eu-central-1:default:/assets
|
|||||||
Caso queira se conectar ao Kube, use a seguinte sintaxe
|
Caso queira se conectar ao Kube, use a seguinte sintaxe
|
||||||
|
|
||||||
```txt
|
```txt
|
||||||
kube://<container>@<pod></path>
|
kube://[namespace][@<cluster_url>][$</path>]
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Argumento de Endereço do WebDAV
|
#### Argumento de Endereço do WebDAV
|
||||||
|
|||||||
+1
-1
@@ -108,7 +108,7 @@ s3://buckethead@eu-central-1:default:/assets
|
|||||||
如果您想连接到 Kube,请使用以下语法
|
如果您想连接到 Kube,请使用以下语法
|
||||||
|
|
||||||
```txt
|
```txt
|
||||||
kube://<container>@<pod></path>
|
kube://[namespace][@<cluster_url>][$</path>]
|
||||||
```
|
```
|
||||||
|
|
||||||
#### WebDAV 地址参数
|
#### WebDAV 地址参数
|
||||||
|
|||||||
@@ -351,8 +351,6 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn bookmark_from_kube_ftparams() {
|
fn bookmark_from_kube_ftparams() {
|
||||||
let params = ProtocolParams::Kube(KubeProtocolParams {
|
let params = ProtocolParams::Kube(KubeProtocolParams {
|
||||||
pod: "pod".to_string(),
|
|
||||||
container: "container".to_string(),
|
|
||||||
namespace: Some("default".to_string()),
|
namespace: Some("default".to_string()),
|
||||||
username: Some("root".to_string()),
|
username: Some("root".to_string()),
|
||||||
cluster_url: Some("https://localhost:6443".to_string()),
|
cluster_url: Some("https://localhost:6443".to_string()),
|
||||||
@@ -368,8 +366,6 @@ mod tests {
|
|||||||
assert!(bookmark.username.is_none());
|
assert!(bookmark.username.is_none());
|
||||||
assert!(bookmark.password.is_none());
|
assert!(bookmark.password.is_none());
|
||||||
let kube: &KubeParams = bookmark.kube.as_ref().unwrap();
|
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.namespace.as_deref().unwrap(), "default");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
kube.cluster_url.as_deref().unwrap(),
|
kube.cluster_url.as_deref().unwrap(),
|
||||||
@@ -494,8 +490,6 @@ mod tests {
|
|||||||
remote_path: Some(PathBuf::from("/tmp")),
|
remote_path: Some(PathBuf::from("/tmp")),
|
||||||
local_path: Some(PathBuf::from("/usr")),
|
local_path: Some(PathBuf::from("/usr")),
|
||||||
kube: Some(KubeParams {
|
kube: Some(KubeParams {
|
||||||
pod_name: String::from("pod"),
|
|
||||||
container: String::from("container"),
|
|
||||||
namespace: Some(String::from("default")),
|
namespace: Some(String::from("default")),
|
||||||
cluster_url: Some(String::from("https://localhost:6443")),
|
cluster_url: Some(String::from("https://localhost:6443")),
|
||||||
username: Some(String::from("root")),
|
username: Some(String::from("root")),
|
||||||
@@ -516,7 +510,6 @@ mod tests {
|
|||||||
std::path::Path::new("/usr")
|
std::path::Path::new("/usr")
|
||||||
);
|
);
|
||||||
let gparams = params.params.kube_params().unwrap();
|
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.namespace.as_deref().unwrap(), "default");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
gparams.cluster_url.as_deref().unwrap(),
|
gparams.cluster_url.as_deref().unwrap(),
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ use crate::filetransfer::params::KubeProtocolParams;
|
|||||||
/// Extra Connection parameters for Kube protocol
|
/// Extra Connection parameters for Kube protocol
|
||||||
#[derive(Clone, Deserialize, Serialize, Debug, PartialEq, Eq, Default)]
|
#[derive(Clone, Deserialize, Serialize, Debug, PartialEq, Eq, Default)]
|
||||||
pub struct KubeParams {
|
pub struct KubeParams {
|
||||||
pub pod_name: String,
|
|
||||||
pub container: String,
|
|
||||||
pub namespace: Option<String>,
|
pub namespace: Option<String>,
|
||||||
pub cluster_url: Option<String>,
|
pub cluster_url: Option<String>,
|
||||||
pub username: Option<String>,
|
pub username: Option<String>,
|
||||||
@@ -17,8 +15,6 @@ pub struct KubeParams {
|
|||||||
impl From<KubeParams> for KubeProtocolParams {
|
impl From<KubeParams> for KubeProtocolParams {
|
||||||
fn from(value: KubeParams) -> Self {
|
fn from(value: KubeParams) -> Self {
|
||||||
Self {
|
Self {
|
||||||
pod: value.pod_name,
|
|
||||||
container: value.container,
|
|
||||||
namespace: value.namespace,
|
namespace: value.namespace,
|
||||||
cluster_url: value.cluster_url,
|
cluster_url: value.cluster_url,
|
||||||
username: value.username,
|
username: value.username,
|
||||||
@@ -31,8 +27,6 @@ impl From<KubeParams> for KubeProtocolParams {
|
|||||||
impl From<KubeProtocolParams> for KubeParams {
|
impl From<KubeProtocolParams> for KubeParams {
|
||||||
fn from(value: KubeProtocolParams) -> Self {
|
fn from(value: KubeProtocolParams) -> Self {
|
||||||
Self {
|
Self {
|
||||||
pod_name: value.pod,
|
|
||||||
container: value.container,
|
|
||||||
namespace: value.namespace,
|
namespace: value.namespace,
|
||||||
cluster_url: value.cluster_url,
|
cluster_url: value.cluster_url,
|
||||||
username: value.username,
|
username: value.username,
|
||||||
|
|||||||
@@ -412,8 +412,6 @@ mod tests {
|
|||||||
assert_eq!(host.password, None);
|
assert_eq!(host.password, None);
|
||||||
assert_eq!(host.protocol, FileTransferProtocol::Kube);
|
assert_eq!(host.protocol, FileTransferProtocol::Kube);
|
||||||
let kube = host.kube.as_ref().unwrap();
|
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.namespace.as_deref().unwrap(), "my-namespace");
|
||||||
assert_eq!(kube.cluster_url.as_deref().unwrap(), "https://my-cluster");
|
assert_eq!(kube.cluster_url.as_deref().unwrap(), "https://my-cluster");
|
||||||
assert_eq!(kube.username.as_deref().unwrap(), "my-username");
|
assert_eq!(kube.username.as_deref().unwrap(), "my-username");
|
||||||
@@ -515,8 +513,6 @@ mod tests {
|
|||||||
s3: None,
|
s3: None,
|
||||||
smb: None,
|
smb: None,
|
||||||
kube: Some(KubeParams {
|
kube: Some(KubeParams {
|
||||||
pod_name: "my-pod".to_string(),
|
|
||||||
container: "my-container".to_string(),
|
|
||||||
namespace: Some("my-namespace".to_string()),
|
namespace: Some("my-namespace".to_string()),
|
||||||
cluster_url: Some("https://my-cluster".to_string()),
|
cluster_url: Some("https://my-cluster".to_string()),
|
||||||
username: Some("my-username".to_string()),
|
username: Some("my-username".to_string()),
|
||||||
@@ -593,6 +589,22 @@ mod tests {
|
|||||||
assert!(deserialize::<Theme>(Box::new(toml_file)).is_err());
|
assert!(deserialize::<Theme>(Box::new(toml_file)).is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_should_deserialize_v14_pod_bookmark() {
|
||||||
|
let toml = create_v14_pod_bookmark();
|
||||||
|
toml.as_file().sync_all().unwrap();
|
||||||
|
toml.as_file().rewind().unwrap();
|
||||||
|
let deserialized: UserHosts = deserialize(Box::new(toml)).unwrap();
|
||||||
|
let kube = deserialized.bookmarks.get("pod").unwrap();
|
||||||
|
assert_eq!(kube.protocol, FileTransferProtocol::Kube);
|
||||||
|
let kube = kube.kube.as_ref().unwrap();
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
fn create_good_toml_bookmarks() -> tempfile::NamedTempFile {
|
fn create_good_toml_bookmarks() -> tempfile::NamedTempFile {
|
||||||
// Write
|
// Write
|
||||||
let mut tmpfile: tempfile::NamedTempFile = tempfile::NamedTempFile::new().unwrap();
|
let mut tmpfile: tempfile::NamedTempFile = tempfile::NamedTempFile::new().unwrap();
|
||||||
@@ -617,8 +629,6 @@ mod tests {
|
|||||||
[bookmarks.pod]
|
[bookmarks.pod]
|
||||||
protocol = "KUBE"
|
protocol = "KUBE"
|
||||||
[bookmarks.pod.kube]
|
[bookmarks.pod.kube]
|
||||||
pod_name = "my-pod"
|
|
||||||
container = "my-container"
|
|
||||||
namespace = "my-namespace"
|
namespace = "my-namespace"
|
||||||
cluster_url = "https://my-cluster"
|
cluster_url = "https://my-cluster"
|
||||||
username = "my-username"
|
username = "my-username"
|
||||||
@@ -644,6 +654,29 @@ mod tests {
|
|||||||
tmpfile
|
tmpfile
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_v14_pod_bookmark() -> tempfile::NamedTempFile {
|
||||||
|
let mut tmpfile: tempfile::NamedTempFile = tempfile::NamedTempFile::new().unwrap();
|
||||||
|
let file_content: &str = r#"
|
||||||
|
[bookmarks]
|
||||||
|
|
||||||
|
[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"
|
||||||
|
|
||||||
|
[recents]
|
||||||
|
"#;
|
||||||
|
tmpfile.write_all(file_content.as_bytes()).unwrap();
|
||||||
|
//write!(tmpfile, "[bookmarks]\nraspberrypi2 = {{ address = \"192.168.1.31\", port = 22, protocol = \"SFTP\", username = \"root\" }}\nmsi-estrem = {{ address = \"192.168.1.30\", port = 22, protocol = \"SFTP\", username = \"cvisintin\" }}\naws-server-prod1 = {{ address = \"51.23.67.12\", port = 21, protocol = \"FTPS\", username = \"aws001\" }}\n\n[recents]\nISO20201215T094000Z = {{ address = \"172.16.104.10\", port = 22, protocol = \"SCP\", username = \"root\" }}\n");
|
||||||
|
tmpfile
|
||||||
|
}
|
||||||
|
|
||||||
fn create_bad_toml_bookmarks() -> tempfile::NamedTempFile {
|
fn create_bad_toml_bookmarks() -> tempfile::NamedTempFile {
|
||||||
// Write
|
// Write
|
||||||
let mut tmpfile: tempfile::NamedTempFile = tempfile::NamedTempFile::new().unwrap();
|
let mut tmpfile: tempfile::NamedTempFile = tempfile::NamedTempFile::new().unwrap();
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use std::sync::Arc;
|
|||||||
use remotefs::RemoteFs;
|
use remotefs::RemoteFs;
|
||||||
use remotefs_aws_s3::AwsS3Fs;
|
use remotefs_aws_s3::AwsS3Fs;
|
||||||
use remotefs_ftp::FtpFs;
|
use remotefs_ftp::FtpFs;
|
||||||
use remotefs_kube::KubeContainerFs as KubeFs;
|
use remotefs_kube::KubeMultiPodFs as KubeFs;
|
||||||
#[cfg(smb_unix)]
|
#[cfg(smb_unix)]
|
||||||
use remotefs_smb::SmbOptions;
|
use remotefs_smb::SmbOptions;
|
||||||
#[cfg(smb)]
|
#[cfg(smb)]
|
||||||
@@ -119,7 +119,7 @@ impl Builder {
|
|||||||
.build()
|
.build()
|
||||||
.expect("Unable to create tokio runtime"),
|
.expect("Unable to create tokio runtime"),
|
||||||
);
|
);
|
||||||
let kube_fs = KubeFs::new(¶ms.pod, ¶ms.container, &rt);
|
let kube_fs = KubeFs::new(&rt);
|
||||||
if let Some(config) = params.config() {
|
if let Some(config) = params.config() {
|
||||||
kube_fs.config(config)
|
kube_fs.config(config)
|
||||||
} else {
|
} else {
|
||||||
@@ -281,8 +281,6 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_should_build_kube_fs() {
|
fn test_should_build_kube_fs() {
|
||||||
let params = ProtocolParams::Kube(KubeProtocolParams {
|
let params = ProtocolParams::Kube(KubeProtocolParams {
|
||||||
pod: "pod".to_string(),
|
|
||||||
container: "container".to_string(),
|
|
||||||
namespace: Some("namespace".to_string()),
|
namespace: Some("namespace".to_string()),
|
||||||
cluster_url: Some("cluster_url".to_string()),
|
cluster_url: Some("cluster_url".to_string()),
|
||||||
username: Some("username".to_string()),
|
username: Some("username".to_string()),
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ use remotefs_kube::Config;
|
|||||||
/// Protocol params used by WebDAV
|
/// Protocol params used by WebDAV
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct KubeProtocolParams {
|
pub struct KubeProtocolParams {
|
||||||
pub pod: String,
|
|
||||||
pub container: String,
|
|
||||||
pub namespace: Option<String>,
|
pub namespace: Option<String>,
|
||||||
pub cluster_url: Option<String>,
|
pub cluster_url: Option<String>,
|
||||||
pub username: Option<String>,
|
pub username: Option<String>,
|
||||||
|
|||||||
@@ -76,16 +76,12 @@ impl KeyStorage for KeyringStorage {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#[cfg(linux)]
|
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
#[cfg(linux)]
|
|
||||||
use whoami::username;
|
use whoami::username;
|
||||||
|
|
||||||
#[cfg(linux)]
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(linux)]
|
|
||||||
fn test_system_keys_keyringstorage() {
|
fn test_system_keys_keyringstorage() {
|
||||||
let username: String = username();
|
let username: String = username();
|
||||||
let storage: KeyringStorage = KeyringStorage::new(username.as_str());
|
let storage: KeyringStorage = KeyringStorage::new(username.as_str());
|
||||||
|
|||||||
@@ -193,8 +193,6 @@ impl AuthActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn load_bookmark_kube_into_gui(&mut self, params: KubeProtocolParams) {
|
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_cluster_url(params.cluster_url.as_deref().unwrap_or(""));
|
||||||
self.mount_kube_namespace(params.namespace.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_cert(params.client_cert.as_deref().unwrap_or(""));
|
||||||
|
|||||||
@@ -832,40 +832,6 @@ impl Component<Msg, NoUserEvent> for InputWebDAVUri {
|
|||||||
|
|
||||||
// kube
|
// 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)]
|
#[derive(MockComponent)]
|
||||||
pub struct InputKubeNamespace {
|
pub struct InputKubeNamespace {
|
||||||
component: Input,
|
component: Input,
|
||||||
@@ -937,40 +903,6 @@ impl Component<Msg, NoUserEvent> for InputKubeClusterUrl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[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)]
|
#[derive(MockComponent)]
|
||||||
pub struct InputKubeUsername {
|
pub struct InputKubeUsername {
|
||||||
component: Input,
|
component: Input,
|
||||||
|
|||||||
@@ -16,12 +16,11 @@ pub use bookmarks::{
|
|||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
pub use form::InputSmbWorkgroup;
|
pub use form::InputSmbWorkgroup;
|
||||||
pub use form::{
|
pub use form::{
|
||||||
InputAddress, InputKubeClientCert, InputKubeClientKey, InputKubeClusterUrl, InputKubeContainer,
|
InputAddress, InputKubeClientCert, InputKubeClientKey, InputKubeClusterUrl, InputKubeNamespace,
|
||||||
InputKubeNamespace, InputKubePodName, InputKubeUsername, InputLocalDirectory, InputPassword,
|
InputKubeUsername, InputLocalDirectory, InputPassword, InputPort, InputRemoteDirectory,
|
||||||
InputPort, InputRemoteDirectory, InputS3AccessKey, InputS3Bucket, InputS3Endpoint,
|
InputS3AccessKey, InputS3Bucket, InputS3Endpoint, InputS3Profile, InputS3Region,
|
||||||
InputS3Profile, InputS3Region, InputS3SecretAccessKey, InputS3SecurityToken,
|
InputS3SecretAccessKey, InputS3SecurityToken, InputS3SessionToken, InputSmbShare,
|
||||||
InputS3SessionToken, InputSmbShare, InputUsername, InputWebDAVUri, ProtocolRadio,
|
InputUsername, InputWebDAVUri, ProtocolRadio, RadioS3NewPathStyle,
|
||||||
RadioS3NewPathStyle,
|
|
||||||
};
|
};
|
||||||
pub use popup::{
|
pub use popup::{
|
||||||
ErrorPopup, InfoPopup, InstallUpdatePopup, Keybindings, QuitPopup, ReleaseNotes, WaitPopup,
|
ErrorPopup, InfoPopup, InstallUpdatePopup, Keybindings, QuitPopup, ReleaseNotes, WaitPopup,
|
||||||
|
|||||||
@@ -85,9 +85,7 @@ impl AuthActivity {
|
|||||||
/// Get input values from fields or return an error if fields are invalid to work as aws s3
|
/// 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> {
|
pub(super) fn collect_kube_host_params(&self) -> Result<FileTransferParams, &'static str> {
|
||||||
let params = self.get_kube_params_input();
|
let params = self.get_kube_params_input();
|
||||||
if params.pod.is_empty() {
|
|
||||||
return Err("Invalid pod name");
|
|
||||||
}
|
|
||||||
Ok(FileTransferParams {
|
Ok(FileTransferParams {
|
||||||
protocol: FileTransferProtocol::Kube,
|
protocol: FileTransferProtocol::Kube,
|
||||||
params: ProtocolParams::Kube(params),
|
params: ProtocolParams::Kube(params),
|
||||||
|
|||||||
@@ -48,8 +48,6 @@ pub enum Id {
|
|||||||
InfoPopup,
|
InfoPopup,
|
||||||
InstallUpdatePopup,
|
InstallUpdatePopup,
|
||||||
Keybindings,
|
Keybindings,
|
||||||
KubePodName,
|
|
||||||
KubeContainer,
|
|
||||||
KubeNamespace,
|
KubeNamespace,
|
||||||
KubeClusterUrl,
|
KubeClusterUrl,
|
||||||
KubeUsername,
|
KubeUsername,
|
||||||
@@ -119,10 +117,6 @@ pub enum UiMsg {
|
|||||||
CloseKeybindingsPopup,
|
CloseKeybindingsPopup,
|
||||||
CloseQuitPopup,
|
CloseQuitPopup,
|
||||||
CloseSaveBookmark,
|
CloseSaveBookmark,
|
||||||
KubePodNameBlurDown,
|
|
||||||
KubePodNameBlurUp,
|
|
||||||
KubeContainerBlurDown,
|
|
||||||
KubeContainerBlurUp,
|
|
||||||
KubeNamespaceBlurDown,
|
KubeNamespaceBlurDown,
|
||||||
KubeNamespaceBlurUp,
|
KubeNamespaceBlurUp,
|
||||||
KubeClusterUrlBlurDown,
|
KubeClusterUrlBlurDown,
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ impl AuthActivity {
|
|||||||
InputMask::Generic => &Id::Password,
|
InputMask::Generic => &Id::Password,
|
||||||
InputMask::Smb => &Id::Password,
|
InputMask::Smb => &Id::Password,
|
||||||
InputMask::AwsS3 => &Id::S3Bucket,
|
InputMask::AwsS3 => &Id::S3Bucket,
|
||||||
InputMask::Kube => &Id::KubePodName,
|
InputMask::Kube => &Id::KubeNamespace,
|
||||||
InputMask::WebDAV => &Id::Password,
|
InputMask::WebDAV => &Id::Password,
|
||||||
})
|
})
|
||||||
.is_ok());
|
.is_ok());
|
||||||
@@ -84,7 +84,7 @@ impl AuthActivity {
|
|||||||
InputMask::Generic => &Id::Password,
|
InputMask::Generic => &Id::Password,
|
||||||
InputMask::Smb => &Id::Password,
|
InputMask::Smb => &Id::Password,
|
||||||
InputMask::AwsS3 => &Id::S3Bucket,
|
InputMask::AwsS3 => &Id::S3Bucket,
|
||||||
InputMask::Kube => &Id::KubePodName,
|
InputMask::Kube => &Id::KubeNamespace,
|
||||||
InputMask::WebDAV => &Id::Password,
|
InputMask::WebDAV => &Id::Password,
|
||||||
})
|
})
|
||||||
.is_ok());
|
.is_ok());
|
||||||
@@ -210,7 +210,7 @@ impl AuthActivity {
|
|||||||
InputMask::Generic => &Id::Address,
|
InputMask::Generic => &Id::Address,
|
||||||
InputMask::Smb => &Id::Address,
|
InputMask::Smb => &Id::Address,
|
||||||
InputMask::AwsS3 => &Id::S3Bucket,
|
InputMask::AwsS3 => &Id::S3Bucket,
|
||||||
InputMask::Kube => &Id::KubePodName,
|
InputMask::Kube => &Id::KubeNamespace,
|
||||||
InputMask::WebDAV => &Id::WebDAVUri,
|
InputMask::WebDAV => &Id::WebDAVUri,
|
||||||
})
|
})
|
||||||
.is_ok());
|
.is_ok());
|
||||||
@@ -305,23 +305,11 @@ impl AuthActivity {
|
|||||||
UiMsg::KubeClientKeyBlurUp => {
|
UiMsg::KubeClientKeyBlurUp => {
|
||||||
assert!(self.app.active(&Id::KubeClientCert).is_ok());
|
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 => {
|
UiMsg::KubeNamespaceBlurDown => {
|
||||||
assert!(self.app.active(&Id::KubeClusterUrl).is_ok());
|
assert!(self.app.active(&Id::KubeClusterUrl).is_ok());
|
||||||
}
|
}
|
||||||
UiMsg::KubeNamespaceBlurUp => {
|
UiMsg::KubeNamespaceBlurUp => {
|
||||||
assert!(self.app.active(&Id::KubeContainer).is_ok());
|
assert!(self.app.active(&Id::Protocol).is_ok());
|
||||||
}
|
}
|
||||||
UiMsg::KubeClusterUrlBlurDown => {
|
UiMsg::KubeClusterUrlBlurDown => {
|
||||||
assert!(self.app.active(&Id::KubeUsername).is_ok());
|
assert!(self.app.active(&Id::KubeUsername).is_ok());
|
||||||
|
|||||||
@@ -64,9 +64,7 @@ impl AuthActivity {
|
|||||||
self.mount_kube_client_cert("");
|
self.mount_kube_client_cert("");
|
||||||
self.mount_kube_client_key("");
|
self.mount_kube_client_key("");
|
||||||
self.mount_kube_cluster_url("");
|
self.mount_kube_cluster_url("");
|
||||||
self.mount_kube_container("");
|
|
||||||
self.mount_kube_namespace("");
|
self.mount_kube_namespace("");
|
||||||
self.mount_kube_pod_name("");
|
|
||||||
self.mount_kube_username("");
|
self.mount_kube_username("");
|
||||||
self.mount_smb_share("");
|
self.mount_smb_share("");
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
@@ -748,30 +746,6 @@ impl AuthActivity {
|
|||||||
.is_ok());
|
.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) {
|
pub(super) fn mount_kube_namespace(&mut self, value: &str) {
|
||||||
let color = self.theme().auth_port;
|
let color = self.theme().auth_port;
|
||||||
assert!(self
|
assert!(self
|
||||||
@@ -906,16 +880,12 @@ impl AuthActivity {
|
|||||||
|
|
||||||
/// Collect s3 input values from view
|
/// Collect s3 input values from view
|
||||||
pub(super) fn get_kube_params_input(&self) -> KubeProtocolParams {
|
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 namespace = self.get_input_kube_namespace();
|
||||||
let cluster_url = self.get_input_kube_cluster_url();
|
let cluster_url = self.get_input_kube_cluster_url();
|
||||||
let username = self.get_input_kube_username();
|
let username = self.get_input_kube_username();
|
||||||
let client_cert = self.get_input_kube_client_cert();
|
let client_cert = self.get_input_kube_client_cert();
|
||||||
let client_key = self.get_input_kube_client_key();
|
let client_key = self.get_input_kube_client_key();
|
||||||
KubeProtocolParams {
|
KubeProtocolParams {
|
||||||
pod,
|
|
||||||
container,
|
|
||||||
namespace,
|
namespace,
|
||||||
cluster_url,
|
cluster_url,
|
||||||
username,
|
username,
|
||||||
@@ -1083,20 +1053,6 @@ 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> {
|
pub(super) fn get_input_kube_namespace(&self) -> Option<String> {
|
||||||
match self.app.state(&Id::KubeNamespace) {
|
match self.app.state(&Id::KubeNamespace) {
|
||||||
Ok(State::One(StateValue::String(x))) if !x.is_empty() => Some(x),
|
Ok(State::One(StateValue::String(x))) if !x.is_empty() => Some(x),
|
||||||
@@ -1214,15 +1170,13 @@ impl AuthActivity {
|
|||||||
}
|
}
|
||||||
ProtocolParams::Kube(params) => {
|
ProtocolParams::Kube(params) => {
|
||||||
format!(
|
format!(
|
||||||
"{}://{}@{}{}{}",
|
"{}://{}{}",
|
||||||
protocol,
|
protocol,
|
||||||
params.container,
|
|
||||||
params.pod,
|
|
||||||
params
|
params
|
||||||
.namespace
|
.namespace
|
||||||
.as_deref()
|
.as_deref()
|
||||||
.map(|x| format!("/{x}"))
|
.map(|x| format!("/{x}"))
|
||||||
.unwrap_or_default(),
|
.unwrap_or_else(|| String::from("default")),
|
||||||
params
|
params
|
||||||
.cluster_url
|
.cluster_url
|
||||||
.as_deref()
|
.as_deref()
|
||||||
@@ -1318,18 +1272,6 @@ impl AuthActivity {
|
|||||||
/// Get the visible element in the kube form, based on current focus
|
/// Get the visible element in the kube form, based on current focus
|
||||||
fn get_kube_view(&self) -> [Id; 4] {
|
fn get_kube_view(&self) -> [Id; 4] {
|
||||||
match self.app.focus() {
|
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) => [
|
Some(&Id::KubeClientCert) => [
|
||||||
Id::KubeNamespace,
|
Id::KubeNamespace,
|
||||||
Id::KubeClusterUrl,
|
Id::KubeClusterUrl,
|
||||||
@@ -1355,10 +1297,10 @@ impl AuthActivity {
|
|||||||
Id::LocalDirectory,
|
Id::LocalDirectory,
|
||||||
],
|
],
|
||||||
_ => [
|
_ => [
|
||||||
Id::KubePodName,
|
|
||||||
Id::KubeContainer,
|
|
||||||
Id::KubeNamespace,
|
Id::KubeNamespace,
|
||||||
Id::KubeClusterUrl,
|
Id::KubeClusterUrl,
|
||||||
|
Id::KubeUsername,
|
||||||
|
Id::KubeClientCert,
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,7 +111,9 @@ impl FileTransferActivity {
|
|||||||
match &ft_params.params {
|
match &ft_params.params {
|
||||||
ProtocolParams::Generic(params) => params.address.clone(),
|
ProtocolParams::Generic(params) => params.address.clone(),
|
||||||
ProtocolParams::AwsS3(params) => params.bucket_name.clone(),
|
ProtocolParams::AwsS3(params) => params.bucket_name.clone(),
|
||||||
ProtocolParams::Kube(params) => params.pod.clone(),
|
ProtocolParams::Kube(params) => {
|
||||||
|
params.namespace.clone().unwrap_or("default".to_string())
|
||||||
|
}
|
||||||
ProtocolParams::Smb(params) => params.address.clone(),
|
ProtocolParams::Smb(params) => params.address.clone(),
|
||||||
ProtocolParams::WebDAV(params) => params.uri.clone(),
|
ProtocolParams::WebDAV(params) => params.uri.clone(),
|
||||||
}
|
}
|
||||||
@@ -137,11 +139,9 @@ impl FileTransferActivity {
|
|||||||
format!("Connecting to {}…", params.bucket_name)
|
format!("Connecting to {}…", params.bucket_name)
|
||||||
}
|
}
|
||||||
ProtocolParams::Kube(params) => {
|
ProtocolParams::Kube(params) => {
|
||||||
info!(
|
let namespace = params.namespace.as_deref().unwrap_or("default");
|
||||||
"Client is not connected to remote; connecting to pod {}",
|
info!("Client is not connected to remote; connecting to namespace {namespace}",);
|
||||||
params.pod,
|
format!("Connecting to Kube namespace {namespace}…",)
|
||||||
);
|
|
||||||
format!("Connecting to {}…", params.pod)
|
|
||||||
}
|
}
|
||||||
ProtocolParams::Smb(params) => {
|
ProtocolParams::Smb(params) => {
|
||||||
info!(
|
info!(
|
||||||
|
|||||||
@@ -57,7 +57,11 @@ impl FileTransferActivity {
|
|||||||
// Connect to remote
|
// Connect to remote
|
||||||
match self.client.connect() {
|
match self.client.connect() {
|
||||||
Ok(Welcome { banner, .. }) => {
|
Ok(Welcome { banner, .. }) => {
|
||||||
self.connected = true;
|
self.connected = self.client.is_connected();
|
||||||
|
if !self.connected {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(banner) = banner {
|
if let Some(banner) = banner {
|
||||||
// Log welcome
|
// Log welcome
|
||||||
self.log(
|
self.log(
|
||||||
@@ -68,6 +72,15 @@ impl FileTransferActivity {
|
|||||||
banner
|
banner
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
// Log welcome
|
||||||
|
self.log(
|
||||||
|
LogLevel::Info,
|
||||||
|
format!(
|
||||||
|
"Established connection with '{}'",
|
||||||
|
self.get_remote_hostname()
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
// Try to change directory to entry directory
|
// Try to change directory to entry directory
|
||||||
let mut remote_chdir: Option<PathBuf> = None;
|
let mut remote_chdir: Option<PathBuf> = None;
|
||||||
@@ -111,16 +124,28 @@ impl FileTransferActivity {
|
|||||||
|
|
||||||
/// Reload remote directory entries and update browser
|
/// Reload remote directory entries and update browser
|
||||||
pub(super) fn reload_remote_dir(&mut self) {
|
pub(super) fn reload_remote_dir(&mut self) {
|
||||||
|
if !self.connected {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Get current entries
|
// Get current entries
|
||||||
if let Ok(wrkdir) = self.client.pwd() {
|
if let Ok(wrkdir) = self.client.pwd() {
|
||||||
self.mount_blocking_wait("Loading remote directory...");
|
self.mount_blocking_wait("Loading remote directory...");
|
||||||
|
|
||||||
if self.remote_scan(wrkdir.as_path()).is_ok() {
|
let res = self.remote_scan(wrkdir.as_path());
|
||||||
// Set wrkdir
|
|
||||||
self.remote_mut().wrkdir = wrkdir;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.umount_wait();
|
self.umount_wait();
|
||||||
|
|
||||||
|
match res {
|
||||||
|
Ok(_) => {
|
||||||
|
self.remote_mut().wrkdir = wrkdir;
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
self.log_and_alert(
|
||||||
|
LogLevel::Error,
|
||||||
|
format!("Could not scan current remote directory: {err}"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,11 +155,21 @@ impl FileTransferActivity {
|
|||||||
|
|
||||||
let wrkdir: PathBuf = self.host.pwd();
|
let wrkdir: PathBuf = self.host.pwd();
|
||||||
|
|
||||||
if self.local_scan(wrkdir.as_path()).is_ok() {
|
let res = self.local_scan(wrkdir.as_path());
|
||||||
self.local_mut().wrkdir = wrkdir;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.umount_wait();
|
self.umount_wait();
|
||||||
|
|
||||||
|
match res {
|
||||||
|
Ok(_) => {
|
||||||
|
self.local_mut().wrkdir = wrkdir;
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
self.log_and_alert(
|
||||||
|
LogLevel::Error,
|
||||||
|
format!("Could not scan current local directory: {err}"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Scan current local directory
|
/// Scan current local directory
|
||||||
@@ -146,13 +181,7 @@ impl FileTransferActivity {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => Err(err),
|
||||||
self.log_and_alert(
|
|
||||||
LogLevel::Error,
|
|
||||||
format!("Could not scan current directory: {err}"),
|
|
||||||
);
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,13 +193,7 @@ impl FileTransferActivity {
|
|||||||
self.remote_mut().set_files(files);
|
self.remote_mut().set_files(files);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => Err(err),
|
||||||
self.log_and_alert(
|
|
||||||
LogLevel::Error,
|
|
||||||
format!("Could not scan current directory: {err}"),
|
|
||||||
);
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ impl FileTransferActivity {
|
|||||||
self.refresh_remote_status_bar();
|
self.refresh_remote_status_bar();
|
||||||
// Update components
|
// Update components
|
||||||
self.update_local_filelist();
|
self.update_local_filelist();
|
||||||
self.update_remote_filelist();
|
// self.update_remote_filelist();
|
||||||
// Global listener
|
// Global listener
|
||||||
self.mount_global_listener();
|
self.mount_global_listener();
|
||||||
// Give focus to local explorer
|
// Give focus to local explorer
|
||||||
|
|||||||
+15
-23
@@ -56,12 +56,12 @@ static REMOTE_WEBDAV_OPT_REGEX: Lazy<Regex> =
|
|||||||
lazy_regex!(r"(?:([^:]+):)(?:(.+[^@])@)(?:([^/]+))(?:(.+))?");
|
lazy_regex!(r"(?:([^:]+):)(?:(.+[^@])@)(?:([^/]+))(?:(.+))?");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Regex matches: {container}@{pod}/{path}
|
* Regex matches: {namespace}[@{cluster_url}]$/{path}
|
||||||
* - group 1: Container
|
* - group 1: Namespace
|
||||||
* - group 2: Pod
|
* - group 3: Some(cluster_url) | None
|
||||||
* - group 3: Some(path) | None
|
* - group 5: Some(path) | None
|
||||||
*/
|
*/
|
||||||
static REMOTE_KUBE_OPT_REGEX: Lazy<Regex> = lazy_regex!(r"(?:(.+[^@])@)(?:([^/]+))(?:(.+))?");
|
static REMOTE_KUBE_OPT_REGEX: Lazy<Regex> = lazy_regex!(r"(?:([^@]+))(@(?:([^$]+)))?(\$(?:(.+)))?");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Regex matches:
|
* Regex matches:
|
||||||
@@ -313,23 +313,15 @@ fn parse_s3_remote_opt(s: &str) -> Result<FileTransferParams, String> {
|
|||||||
fn parse_kube_remote_opt(s: &str) -> Result<FileTransferParams, String> {
|
fn parse_kube_remote_opt(s: &str) -> Result<FileTransferParams, String> {
|
||||||
match REMOTE_KUBE_OPT_REGEX.captures(s) {
|
match REMOTE_KUBE_OPT_REGEX.captures(s) {
|
||||||
Some(groups) => {
|
Some(groups) => {
|
||||||
let container: String = groups
|
let namespace: Option<String> = groups.get(1).map(|x| x.as_str().to_string());
|
||||||
.get(1)
|
let cluster_url: Option<String> = groups.get(3).map(|x| x.as_str().to_string());
|
||||||
.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> =
|
let remote_path: Option<PathBuf> =
|
||||||
groups.get(3).map(|group| PathBuf::from(group.as_str()));
|
groups.get(5).map(|group| PathBuf::from(group.as_str()));
|
||||||
Ok(FileTransferParams::new(
|
Ok(FileTransferParams::new(
|
||||||
FileTransferProtocol::Kube,
|
FileTransferProtocol::Kube,
|
||||||
ProtocolParams::Kube(KubeProtocolParams {
|
ProtocolParams::Kube(KubeProtocolParams {
|
||||||
pod,
|
namespace,
|
||||||
container,
|
cluster_url,
|
||||||
namespace: None,
|
|
||||||
cluster_url: None,
|
|
||||||
username: None,
|
username: None,
|
||||||
client_cert: None,
|
client_cert: None,
|
||||||
client_key: None,
|
client_key: None,
|
||||||
@@ -753,13 +745,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_parse_kube_address() {
|
fn should_parse_kube_address() {
|
||||||
let result = parse_remote_opt("kube://alpine@my-pod/tmp").ok().unwrap();
|
let result = parse_remote_opt("kube://my-namespace@http://localhost:1234$/tmp")
|
||||||
|
.ok()
|
||||||
|
.unwrap();
|
||||||
let params = result.params.kube_params().unwrap();
|
let params = result.params.kube_params().unwrap();
|
||||||
|
|
||||||
assert_eq!(params.container.as_str(), "alpine");
|
assert_eq!(params.namespace, Some("my-namespace".to_string()));
|
||||||
assert_eq!(params.pod.as_str(), "my-pod");
|
assert_eq!(params.cluster_url.as_deref(), Some("http://localhost:1234"));
|
||||||
assert_eq!(params.namespace, None);
|
|
||||||
assert_eq!(params.cluster_url, None);
|
|
||||||
assert_eq!(params.username, None);
|
assert_eq!(params.username, None);
|
||||||
assert_eq!(params.client_cert, None);
|
assert_eq!(params.client_cert, None);
|
||||||
assert_eq!(params.client_key, None);
|
assert_eq!(params.client_key, None);
|
||||||
|
|||||||
Reference in New Issue
Block a user