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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion agent/native_windows/src/check_files.cc
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,12 @@ void ::check_files_detail::filter::find_files() {

fs::path search_path(_root_path);

// rebuild the map on each scan
absl::flat_hash_map<std::string, std::unique_ptr<file_metadata>>
new_files_metadata;

if (!fs::exists(search_path) || !fs::is_directory(search_path)) {
_files_metadata = std::move(new_files_metadata);
return;
}

Expand All @@ -378,14 +383,22 @@ void ::check_files_detail::filter::find_files() {
if (_file_filter && !_file_filter->check(*metadata)) {
continue; // skip to next if the data don't match the filter
}
_files_metadata[std::move(path_str)] = std::move(metadata);
new_files_metadata[std::move(path_str)] = std::move(metadata);
} else {
// File unchanged since the previous scan: reuse.
auto previous = _files_metadata.find(path_str);
if (previous != _files_metadata.end()) {
new_files_metadata[path_str] = std::move(previous->second);
}
}
}
}
} catch (const std::exception& e [[maybe_unused]]) {
continue; // Skip files that cannot be accessed or processed
}
}

_files_metadata = std::move(new_files_metadata);
}
/*********************************************************************************************
* check_files_thread
Expand Down
79 changes: 79 additions & 0 deletions agent/test/check_windows_files_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -746,4 +746,83 @@ TEST_F(check_files_test, two_checks_same_path) {

// check if a change of lines is detected
ASSERT_EQ(number_lines + 20, new_number_lines);
}

// the status must be re-evaluated on every check.
// A "critical-status": "count > 0" check must go CRITICAL when a matching file
// appears and go back to OK once that file is removed. Before the fix the
// filter metadata map was never cleared, so a deleted file lingered and the
// check stayed CRITICAL forever.
TEST_F(check_files_test, status_updates_when_file_added_and_removed) {
namespace fs = std::filesystem;

fs::path dir = fs::temp_directory_path() / "check_files_add_remove_fixture";
fs::remove_all(dir);
fs::create_directories(dir);
fs::path watched = dir / "test.txt";

std::string json_str = fmt::format(R"cfg({{
"path": "{}",
"max-depth": 0,
"pattern": "test.txt",
"critical-status": "count > 0",
"output-syntax": "${{status}}: ${{problem_count}}/${{count}} files (${{problem_list}})",
"ok-syntax": "${{status}}: ${{ok_count}} files found",
"verbose": false
}})cfg",
dir.generic_string());

std::cout << "JSON String: " << json_str << std::endl;
rapidjson::Document check_args;
check_args.Parse(json_str.c_str());

absl::Mutex wait_m;
std::string output;
int status = -1;
bool complete = false;

auto is_complete = [&]() { return complete; };

auto checker = std::make_shared<check_files>(
g_io_context, spdlog::default_logger(), std::chrono::system_clock::now(),
serv, check_args, nullptr,
[&]([[maybe_unused]] const std::shared_ptr<check>& caller, int st,
[[maybe_unused]] const std::list<com::centreon::common::perfdata>&
perfdata,
const std::list<std::string>& outputs) {
absl::MutexLock lck(wait_m);
complete = true;
status = st;
output = outputs.front();
},
std::make_shared<checks_statistics>());

auto run_one_check = [&]() {
{
absl::MutexLock lk(&wait_m);
complete = false;
}
checker->start_check(std::chrono::seconds(20));
absl::MutexLock lk(&wait_m);
wait_m.Await(absl::Condition(&is_complete));
};

// 1) no matching file yet -> OK
run_one_check();
EXPECT_EQ(status, e_status::ok)
<< "expected OK when no file is present, got: " << output;

// 2) create the file -> count > 0 -> CRITICAL
{ std::ofstream(watched) << "hello\n"; }
run_one_check();
EXPECT_EQ(status, e_status::critical)
<< "expected CRITICAL once the file exists, got: " << output;

// 3) remove the file -> status must return to OK
fs::remove(watched);
run_one_check();
EXPECT_EQ(status, e_status::ok)
<< "expected OK after the file is removed, got: " << output;

fs::remove_all(dir);
}
39 changes: 27 additions & 12 deletions centreon_cmake.bat
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,35 @@ IF ERRORLEVEL 1 (
exit /B
)

if not defined VCPKG_ROOT (
echo "install vcpkg"
set "current_dir=%cd%"
cd /D %USERPROFILE%
git clone https://github.com/microsoft/vcpkg.git
cd vcpkg && bootstrap-vcpkg.bat
cd /D %current_dir%
set "VCPKG_ROOT=%USERPROFILE%\vcpkg"
set "PATH=%VCPKG_ROOT%;%PATH%"
echo "Please add this variables to environment for future compile:"
echo "VCPKG_ROOT=%USERPROFILE%\vcpkg"
echo "PATH=%VCPKG_ROOT%;%PATH%"
:: Use a vcpkg clone local to this repository (like CI does), pinned to the
:: same commit as the builtin-baseline CI injects in
:: .github\scripts\windows-agent-compile.ps1. vcpkg.json has no
:: builtin-baseline (Linux CI resolves a different one), so dependency
:: versions come from whatever VCPKG_ROOT has checked out: if that clone
:: moves, every port's ABI hash changes, the local binary cache misses and
:: grpc/abseil/boost rebuild from source. Pinning the checkout keeps builds
:: reproducible and fast.
set "vcpkg_commit=d015e31e90838a4c9dfa3eed45979bc70d9357fc"
set "VCPKG_ROOT=%~dp0vcpkg"

if not exist "%VCPKG_ROOT%\.git" (
echo install vcpkg in %VCPKG_ROOT%
git clone https://github.com/microsoft/vcpkg.git "%VCPKG_ROOT%"
)

for /f %%i in ('git -C "%VCPKG_ROOT%" rev-parse HEAD') do set "vcpkg_head=%%i"
if not "%vcpkg_head%" == "%vcpkg_commit%" (
echo pinning vcpkg to commit %vcpkg_commit%
git -C "%VCPKG_ROOT%" fetch origin
git -C "%VCPKG_ROOT%" checkout %vcpkg_commit%
call "%VCPKG_ROOT%\bootstrap-vcpkg.bat"
)

if not exist "%VCPKG_ROOT%\vcpkg.exe" (
call "%VCPKG_ROOT%\bootstrap-vcpkg.bat"
)

set "PATH=%VCPKG_ROOT%;%PATH%"

cmake.exe --preset=%build_type%

Expand Down
Loading