From 133690434cdc16394a86ec02aee1d25865aebfcd Mon Sep 17 00:00:00 2001 From: David Esparza Date: Wed, 5 Oct 2022 09:09:47 -0500 Subject: [PATCH] kata-ctl: implement CLI argument --check-version-only This kata-ctl argument returns the latest stable Kata release by hitting github.com. Adds check-version unit tests. Fixes: #11 Signed-off-by: David Esparza --- src/tools/kata-ctl/Cargo.toml | 2 + src/tools/kata-ctl/src/check.rs | 79 +++++++++++++++++++++++- src/tools/kata-ctl/src/ops/version.rs.in | 2 +- 3 files changed, 81 insertions(+), 2 deletions(-) diff --git a/src/tools/kata-ctl/Cargo.toml b/src/tools/kata-ctl/Cargo.toml index eef1f5fbb9..ba73db270a 100644 --- a/src/tools/kata-ctl/Cargo.toml +++ b/src/tools/kata-ctl/Cargo.toml @@ -12,6 +12,8 @@ edition = "2021" [dependencies] anyhow = "1.0.31" clap = { version = "3.2.20", features = ["derive", "cargo"] } +reqwest = { version = "0.11", features = ["json", "blocking"] } +serde_json = "1.0.85" thiserror = "1.0.35" [dev-dependencies] diff --git a/src/tools/kata-ctl/src/check.rs b/src/tools/kata-ctl/src/check.rs index 6a3788d959..7900ed364c 100644 --- a/src/tools/kata-ctl/src/check.rs +++ b/src/tools/kata-ctl/src/check.rs @@ -5,8 +5,14 @@ // Contains checks that are not architecture-specific -use anyhow::{anyhow, Result}; + use std::fs; +use serde_json::Value; +use std::collections::HashMap; +use anyhow::{anyhow, Result}; +use reqwest::header::{CONTENT_TYPE,USER_AGENT}; + +const KATA_GITHUB_URL: &str = "https://api.github.com/repos/kata-containers/kata-containers/releases/latest"; fn get_cpu_info(cpu_info_file: &str) -> Result { let contents = fs::read_to_string(cpu_info_file)?; @@ -89,13 +95,50 @@ pub fn run_network_checks() -> Result<()> { Ok(()) } +fn get_kata_version_by_url(url: &str) -> std::result::Result { + let content = reqwest::blocking::Client::new() + .get(url) + .header(CONTENT_TYPE, "application/json") + .header(USER_AGENT, "kata") + .send()? + .json::>()?; + + let version = content["tag_name"].as_str().unwrap(); + Ok(version.to_string()) +} + +fn handle_reqwest_error(e: reqwest::Error) -> anyhow::Error { + if e.is_connect() { + return anyhow!(e).context("http connection failure: connection refused"); + } + + if e.is_timeout() { + return anyhow!(e).context("http connection failure: connection timeout"); + } + + if e.is_builder() { + return anyhow!(e).context("http connection failure: url malformed"); + } + + if e.is_decode() { + return anyhow!(e).context("http connection failure: unable to decode response body"); + } + + anyhow!(e).context("unknown http connection failure: {:?}") +} + pub fn check_version() -> Result<()> { + let version = get_kata_version_by_url(KATA_GITHUB_URL).map_err(|e| handle_reqwest_error(e))?; + + println!("Version: {}", version); + Ok(()) } #[cfg(test)] mod tests { use super::*; + use semver::Version; #[test] fn test_get_cpu_info_empty_input() { @@ -113,4 +156,38 @@ mod tests { let actual = get_cpu_flags("", "").err().unwrap().to_string(); assert_eq!(expected, actual); } + + #[test] + fn check_version_by_empty_url() { + const TEST_URL: &str = "http:"; + let expected = "builder error: empty host"; + let actual = get_kata_version_by_url(TEST_URL).err().unwrap().to_string(); + assert_eq!(expected, actual); + } + + #[test] + fn check_version_by_garbage_url() { + const TEST_URL: &str = "_localhost_"; + let expected = "builder error: relative URL without a base"; + let actual = get_kata_version_by_url(TEST_URL).err().unwrap().to_string(); + assert_eq!(expected, actual); + } + + #[test] + fn check_version_by_invalid_url() { + const TEST_URL: &str = "http://localhost :80"; + let expected = "builder error: invalid domain character"; + let actual = get_kata_version_by_url(TEST_URL).err().unwrap().to_string(); + assert_eq!(expected, actual); + } + + #[test] + fn check_latest_version() { + let version = get_kata_version_by_url(KATA_GITHUB_URL).unwrap(); + + let v = Version::parse(&version).unwrap(); + assert!(!v.major.to_string().is_empty()); + assert!(!v.minor.to_string().is_empty()); + assert!(!v.patch.to_string().is_empty()); + } } diff --git a/src/tools/kata-ctl/src/ops/version.rs.in b/src/tools/kata-ctl/src/ops/version.rs.in index 16b3c7e7f3..c207b0ea3e 100644 --- a/src/tools/kata-ctl/src/ops/version.rs.in +++ b/src/tools/kata-ctl/src/ops/version.rs.in @@ -28,7 +28,7 @@ mod tests { #[test] fn test_get() { - let version = get(); + let version = get().unwrap(); let v = Version::parse(&version).unwrap(); assert!(!v.major.to_string().is_empty());