Skip to content

Commit

Permalink
add logic to process check-sql config file
Browse files Browse the repository at this point in the history
- limited to windows

TESTS: local manual in Windows, validation integration in Linux too

Change-Id: Ib54d568c1749db37c1ebed62440434ad946a436c
  • Loading branch information
s-kipnis committed Oct 31, 2023
1 parent 2539c1a commit 7c6c421
Show file tree
Hide file tree
Showing 9 changed files with 175 additions and 19 deletions.
3 changes: 2 additions & 1 deletion packages/check-sql/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ clap = { version = "4.1.*", features = [
"derive",
] } # replace with 4.4.2 if rutsc >= 1.70
yaml-rust = "0.4.5"
lazy_static = { version = "1.4" }


[dev-dependencies]
lazy_static = { version = "*" }
tempfile = { version = "*" }
assert_cmd = { version = "*" }
12 changes: 10 additions & 2 deletions packages/check-sql/src/config/yaml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,16 @@ impl Get for Yaml {
}

pub fn load_from_file(file_name: &Path) -> Result<Vec<Yaml>> {
let content = read_file(file_name)?;
load_from_str(&content)
match read_file(file_name) {
Ok(content) => load_from_str(&content),
Err(e) => anyhow::bail!(
"Can't read file: {}, {e} ",
// Use relatively complicated method to print name of the file
// as it is not possible to use "{file_name:?}": produces to many backslashes
// in Windows. Probability to NOT decode filename as UTF-8 is nil.
file_name.as_os_str().to_str().unwrap_or("")
),
}
}

fn read_file(file_name: &Path) -> Result<String> {
Expand Down
18 changes: 17 additions & 1 deletion packages/check-sql/src/constants.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,26 @@
// Copyright (C) 2023 Checkmk GmbH - License: GNU General Public License v2
// This file is part of Checkmk (https://checkmk.com). It is subject to the terms and
// conditions defined in the file COPYING, which is part of this source code package.

use lazy_static::lazy_static;
use std::path::{Path, PathBuf};
pub mod log {
use flexi_logger::{Cleanup, Criterion, Naming};
pub const FILE_MAX_SIZE: Criterion = Criterion::Size(100000);
pub const FILE_NAMING: Naming = Naming::Numbers;
pub const FILE_CLEANUP: Cleanup = Cleanup::KeepLogFiles(5);
}

pub mod environment {
pub const CONFIG_NAME: &str = "check-sql.yml";
pub const CONFIG_DIR_ENV_VAR: &str = "MK_CONFDIR";
}

lazy_static! {
pub static ref DEFAULT_CONFIG_FILE: PathBuf =
Path::new(&get_env_value(environment::CONFIG_DIR_ENV_VAR, "."))
.join(environment::CONFIG_NAME);
}

fn get_env_value(var: &str, on_lack: &str) -> String {
std::env::var(var).unwrap_or(on_lack.to_string())
}
14 changes: 8 additions & 6 deletions packages/check-sql/src/emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@
// This file is part of Checkmk (https://checkmk.com). It is subject to the terms and
// conditions defined in the file COPYING, which is part of this source code package.

const PREFIX: &str = "mssql";

pub fn header(name: &str, separator: Option<char>) -> String {
match separator {
Some(s) => {
let sep = s as u8;
format!("<<<{name}:sep({sep:0>2})>>>\n")
format!("<<<{PREFIX}_{name}:sep({sep:0>2})>>>\n")
}
None => format!("<<<{name}>>>\n"),
None => format!("<<<{PREFIX}_{name}>>>\n"),
}
}

Expand All @@ -17,9 +19,9 @@ mod test {
use super::*;
#[test]
fn test_header() {
assert_eq!(header("name", Some('\n')), "<<<name:sep(10)>>>\n");
assert_eq!(header("name", Some('\t')), "<<<name:sep(09)>>>\n");
assert_eq!(header("name", Some('|')), "<<<name:sep(124)>>>\n");
assert_eq!(header("name", None), "<<<name>>>\n");
assert_eq!(header("name", Some('\n')), "<<<mssql_name:sep(10)>>>\n");
assert_eq!(header("name", Some('\t')), "<<<mssql_name:sep(09)>>>\n");
assert_eq!(header("name", Some('|')), "<<<mssql_name:sep(124)>>>\n");
assert_eq!(header("name", None), "<<<mssql_name>>>\n");
}
}
4 changes: 2 additions & 2 deletions packages/check-sql/src/ms_sql/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ fn to_section(name: &String) -> Section {

fn get_section_separator(name: &str) -> Option<char> {
match name {
"instance" | "database" | "counters" | "blocked_sessions" | "transactionlogs"
| "datafiles" | "cluster" => Some('|'),
"instance" | "databases" | "counters" | "blocked_sessions" | "transactionlogs"
| "datafiles" | "cluster" | "clusters" | "backup" => Some('|'),
"jobs" | "mirroring" | "availability_groups" => Some('\t'),
"tablespaces" | "connections" => None,
_ => None,
Expand Down
10 changes: 6 additions & 4 deletions packages/check-sql/src/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,12 @@ fn init_logging_from_args(args: &Args) -> Result<()> {
}

fn get_check_config(args: &Args) -> Result<CheckConfig> {
match args.config_file {
Some(ref config_file) => Ok(CheckConfig::load_file(config_file)?),
None => Ok(CheckConfig::default()),
}
let file = match args.config_file {
Some(ref config_file) => config_file,
None => &constants::DEFAULT_CONFIG_FILE,
};

CheckConfig::load_file(file)
}

fn init_logging(
Expand Down
5 changes: 5 additions & 0 deletions packages/check-sql/tests/common/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Copyright (C) 2023 Checkmk GmbH - License: GNU General Public License v2
// This file is part of Checkmk (https://checkmk.com). It is subject to the terms and
// conditions defined in the file COPYING, which is part of this source code package.

pub mod tools;
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,39 @@
// This file is part of Checkmk (https://checkmk.com). It is subject to the terms and
// conditions defined in the file COPYING, which is part of this source code package.

#[cfg(windows)]
use anyhow::Result;
#[cfg(windows)]
use assert_cmd::output::OutputError;
use assert_cmd::Command;
use std::io::Write;
#[cfg(windows)]
use std::path::Path;
#[cfg(windows)]
use std::process::Output;
use tempfile::NamedTempFile;
#[cfg(windows)]
use tempfile::{Builder, TempDir};

pub fn run_bin() -> Command {
Command::cargo_bin("check-sql").unwrap()
}

/// returns stderr content + resulting code
#[cfg(windows)]
pub fn get_bad_results(output_err: &OutputError) -> Result<(String, i32)> {
let output = output_err.as_output().unwrap();
let stderr = std::str::from_utf8(&output.stderr).map(|s| s.to_string());
Ok((stderr?, output.status.code().unwrap()))
}

/// returns stdout content + resulting code
#[cfg(windows)]
pub fn get_good_results(output: &Output) -> Result<(String, i32)> {
let stdout = std::str::from_utf8(&output.stdout).map(|s| s.to_string());
Ok((stdout?, output.status.code().unwrap()))
}

pub const SQL_DB_ENDPOINT: &str = "CI_TEST_SQL_DB_ENDPOINT";
const SQL_DB_ENDPOINT_SPLITTER: char = ':';
pub struct SqlDbEndpoint {
Expand Down Expand Up @@ -39,6 +64,32 @@ pub fn get_remote_sql_from_env_var() -> Option<SqlDbEndpoint> {
None
}

#[cfg(windows)]
fn create_temp_dir_with_file(file_name: &str, content: &str) -> TempDir {
let dir = create_temp_process_dir();
create_file_with_content(dir.path(), file_name, content);

dir
}

#[cfg(windows)]
pub fn create_file_with_content(dir: &Path, file_name: &str, content: &str) {
let file_path = dir.join(file_name);
let mut file = std::fs::File::create(file_path).unwrap();
file.write_all(content.as_bytes()).unwrap();
}

#[cfg(windows)]
fn create_temp_process_dir() -> TempDir {
let dir = Builder::new()
.prefix(&format!("check-sql-{}", std::process::id()))
.rand_bytes(5)
.tempdir()
.unwrap();

dir
}

pub fn create_remote_config(end_point: &SqlDbEndpoint) -> NamedTempFile {
let mut l = NamedTempFile::new().unwrap();
let config = format!(
Expand All @@ -58,6 +109,7 @@ mssql:
l.write_all(config.as_bytes()).unwrap();
l
}

pub fn create_local_config() -> NamedTempFile {
let mut l = NamedTempFile::new().unwrap();
let config = r#"
Expand All @@ -73,3 +125,8 @@ mssql:
l.write_all(config.as_bytes()).unwrap();
l
}

#[cfg(windows)]
pub fn create_config_dir_with_yml(content: &str) -> TempDir {
create_temp_dir_with_file("check-sql.yml", content)
}
71 changes: 68 additions & 3 deletions packages/check-sql/tests/test_ms_sql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
// This file is part of Checkmk (https://checkmk.com). It is subject to the terms and
// conditions defined in the file COPYING, which is part of this source code package.

mod tools;

mod common;
use check_sql::{config::CheckConfig, ms_sql::api};
use common::tools;
#[cfg(windows)]
use tempfile::TempDir;
#[cfg(windows)]
#[tokio::test(flavor = "multi_thread")]
async fn test_local_connection() {
Expand Down Expand Up @@ -73,7 +75,7 @@ fn test_run_remote() {

#[cfg(windows)]
#[test]
fn test_run_local_as_plugin_fail() {
fn test_run_local_as_plugin_without_config() {
assert!(
tools::run_bin()
.unwrap_err()
Expand All @@ -83,4 +85,67 @@ fn test_run_local_as_plugin_fail() {
.code()
== Some(1)
);
assert!(
tools::run_bin()
.env("MK_CONFDIR", ".")
.unwrap_err()
.as_output()
.unwrap()
.status
.code()
== Some(1)
);
}

#[cfg(windows)]
#[test]
fn test_run_local_as_plugin_with_config() {
// Good config
let content = r#"
---
mssql:
standard:
authentication:
username: "nobody"
type: "integrated"
connection:
hostname: "localhost"
"#;
let dir = tools::create_config_dir_with_yml(content);
let exec = tools::run_bin()
.env("MK_CONFDIR", dir.path())
.timeout(std::time::Duration::from_secs(5))
.unwrap();
let (stdout, code) = tools::get_good_results(&exec).unwrap();
assert_eq!(code, 0);
assert!(stdout.starts_with(
r"<<<mssql_instance:sep(124)>>>
<<<mssql_databases:sep(124)>>>
<<<mssql_counters:sep(124)>>>
<<<mssql_blocked_sessions:sep(124)>>>
<<<mssql_transactionlogs:sep(124)>>>
<<<mssql_clusters:sep(124)>>>
<<<mssql_mirroring:sep(09)>>>
<<<mssql_availability_groups:sep(09)>>>
<<<mssql_connections>>>
<<<mssql_tablespaces>>>
<<<mssql_datafiles:sep(124)>>>
<<<mssql_backup:sep(124)>>>
<<<mssql_jobs:sep(09)>>>"
));

// Bad config
invalidate_config_in_dir(&dir);
let exec_err = tools::run_bin()
.env("MK_CONFDIR", dir.path())
.timeout(std::time::Duration::from_secs(5))
.unwrap_err();
let (stderr, code) = tools::get_bad_results(&exec_err).unwrap();
assert_eq!(code, 1);
assert_eq!(stderr, "Error: No Config\n");
}

#[cfg(windows)]
fn invalidate_config_in_dir(dir: &TempDir) {
tools::create_file_with_content(dir.path(), "check-sql.yml", "---\n");
}

0 comments on commit 7c6c421

Please sign in to comment.