Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 47 additions & 3 deletions kube-client/src/config/file_config.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{
collections::HashMap,
fs,
fs, io,
path::{Path, PathBuf},
};

Expand Down Expand Up @@ -351,8 +351,8 @@
impl Kubeconfig {
/// Read a Config from an arbitrary location
pub fn read_from<P: AsRef<Path>>(path: P) -> Result<Kubeconfig, KubeconfigError> {
let data = fs::read_to_string(&path)
.map_err(|source| KubeconfigError::ReadConfig(source, path.as_ref().into()))?;
let data =
read_path(&path).map_err(|source| KubeconfigError::ReadConfig(source, path.as_ref().into()))?;

Check warning on line 355 in kube-client/src/config/file_config.rs

View check run for this annotation

Codecov / codecov/patch

kube-client/src/config/file_config.rs#L355

Added line #L355 was not covered by tests

// Remap all files we read to absolute paths.
let mut merged_docs = None;
Expand Down Expand Up @@ -497,6 +497,33 @@
});
}

fn read_path<P: AsRef<Path>>(path: P) -> io::Result<String> {
let bytes = fs::read(&path)?;
match bytes.as_slice() {
[0xFF, 0xFE, ..] => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a comment for these magic numbers would be helpful for a future person 😅

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would you prefer using encoding_rs crate instead?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps also putting a comment to use String::from_utf16le and friends when they become stable

let utf16_data: Vec<u16> = bytes[2..]
.chunks(2)
.map(|chunk| u16::from_le_bytes([chunk[0], chunk[1]]))
.collect();
String::from_utf16(&utf16_data)
.map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Invalid UTF-16 LE"))

Check warning on line 509 in kube-client/src/config/file_config.rs

View check run for this annotation

Codecov / codecov/patch

kube-client/src/config/file_config.rs#L509

Added line #L509 was not covered by tests
}
[0xFE, 0xFF, ..] => {

Check warning on line 511 in kube-client/src/config/file_config.rs

View check run for this annotation

Codecov / codecov/patch

kube-client/src/config/file_config.rs#L511

Added line #L511 was not covered by tests
let utf16_data: Vec<u16> = bytes[2..]
.chunks(2)
.map(|chunk| u16::from_be_bytes([chunk[0], chunk[1]]))
.collect();
String::from_utf16(&utf16_data)
.map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Invalid UTF-16 BE"))

Check warning on line 517 in kube-client/src/config/file_config.rs

View check run for this annotation

Codecov / codecov/patch

kube-client/src/config/file_config.rs#L517

Added line #L517 was not covered by tests
}
[0xEF, 0xBB, 0xBF, ..] => String::from_utf8(bytes[3..].to_vec())
.map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Invalid UTF-8 BOM")),
_ => {

Check warning on line 521 in kube-client/src/config/file_config.rs

View check run for this annotation

Codecov / codecov/patch

kube-client/src/config/file_config.rs#L520-L521

Added lines #L520 - L521 were not covered by tests
String::from_utf8(bytes).map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Invalid UTF-8"))
}
}
}

fn to_absolute(dir: &Path, file: &str) -> Option<String> {
let path = Path::new(&file);
if path.is_relative() {
Expand Down Expand Up @@ -969,4 +996,21 @@
json!({"audience": "foo", "other": "bar"})
);
}

#[tokio::test]
async fn parse_kubeconfig_encodings() {
let files = vec![
"kubeconfig_utf8.yaml",
"kubeconfig_utf16le.yaml",
"kubeconfig_utf16be.yaml",
];

for file_name in files {
let path = PathBuf::from(format!("{}/src/config/test_data/{}", env!("CARGO_MANIFEST_DIR"), file_name));
let cfg = Kubeconfig::read_from(path).unwrap();
assert_eq!(cfg.clusters[0].name, "k3d-promstack");
assert_eq!(cfg.contexts[0].name, "k3d-promstack");
assert_eq!(cfg.auth_infos[0].name, "admin@k3d-k3s-default");
}
}
}
Binary file not shown.
Binary file not shown.
19 changes: 19 additions & 0 deletions kube-client/src/config/test_data/kubeconfig_utf8.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: aGVsbG8K
server: https://0.0.0.0:6443
name: k3d-promstack
contexts:
- context:
cluster: k3d-promstack
user: admin@k3d-promstack
name: k3d-promstack
users:
- name: admin@k3d-k3s-default
user:
client-certificate-data: aGVsbG8K
client-key-data: aGVsbG8K
current-context: k3d-promstack
kind: Config
preferences: {}
Loading