From 88772acce28a64d9b6464478d5019f86c29285b3 Mon Sep 17 00:00:00 2001 From: Victor Moene Date: Wed, 23 Apr 2025 11:53:56 +0200 Subject: [PATCH 1/2] Added os_version_minor sys variable Ticket: ENT-8118 Changelog: Title Signed-off-by: Victor Moene --- libenv/sysinfo.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/libenv/sysinfo.c b/libenv/sysinfo.c index 536c88d165..7f369e7679 100644 --- a/libenv/sysinfo.c +++ b/libenv/sysinfo.c @@ -3782,6 +3782,97 @@ static void SysOsVersionMajor(EvalContext *ctx) free(flavor); } +/*****************************************************************************/ + +static const char *OSReleaseGet(EvalContext *ctx, const char *field) +{ + DataType type_out; + const JsonElement *os_rel = EvalContextVariableGetSpecial( + ctx, SPECIAL_SCOPE_SYS, "os_release", &type_out); + + if (type_out != CF_DATA_TYPE_CONTAINER) + { + return NULL; + } + const JsonElement *child = JsonObjectGet(os_rel, field); + if (child == NULL) + { + return NULL; + } + const char *result = JsonPrimitiveGetAsString(child); + return result; +} + +static void OSVersionMinorPut(EvalContext *ctx, const char *minor) +{ + EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, + "os_version_minor", + (minor == NULL) ? "Unknown" : minor, + CF_DATA_TYPE_STRING, + "source=agent,derived-from=os_release"); +} + +static void SysOSVersionMinor(EvalContext *ctx) +{ + #ifndef __MINGW32__ + + const char *version_id = OSReleaseGet(ctx, "VERSION_ID"); + const char *name = OSReleaseGet(ctx, "NAME"); + if (version_id == NULL) + { + return OSVersionMinorPut(ctx, NULL); + } + if (name == NULL) + { + return OSVersionMinorPut(ctx, NULL); + } + Item *version_tuple = SplitString(version_id, '.'); + if (version_tuple == NULL) + { + return OSVersionMinorPut(ctx, NULL); + } + if (name != NULL && (StringStartsWith(name, "solaris") || StringStartsWith(name, "sunos"))) + { + OSVersionMinorPut(ctx, version_tuple->name); + return DeleteItemList(version_tuple); + } + if (version_tuple->next == NULL) + { + OSVersionMinorPut(ctx, NULL); + return DeleteItemList(version_tuple); + } + OSVersionMinorPut(ctx, version_tuple->next->name); + return DeleteItemList(version_tuple); + + #else + + char *release = SafeStringDuplicate(VSYSNAME.release); + char *major = NULL; + char *minor = NULL; + char *rel; + rel = FindNextInteger(release, &major); + if (rel == NULL) + { + free(release); + EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, + "os_version_minor", + "Unknown", + CF_DATA_TYPE_STRING, + "source=agent"); + return; + } + rel = FindNextInteger(rel, &minor); + EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, + "os_version_minor", + (minor == NULL) ? "Unknown" : minor, + CF_DATA_TYPE_STRING, + "source=agent"); + free(release); + + #endif +} + + /*****************************************************************************/ void DetectEnvironment(EvalContext *ctx) @@ -3796,4 +3887,5 @@ void DetectEnvironment(EvalContext *ctx) GetDefVars(ctx); SysOSNameHuman(ctx); SysOsVersionMajor(ctx); + SysOSVersionMinor(ctx); } From 6001b97d50b583b83a80629b4822ad6cbd00e251 Mon Sep 17 00:00:00 2001 From: Victor Moene Date: Tue, 24 Jun 2025 14:50:42 +0200 Subject: [PATCH 2/2] Added test for os minor version Signed-off-by: Victor Moene --- .../01_vars/01_basic/os_version_minor.cf | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 tests/acceptance/01_vars/01_basic/os_version_minor.cf diff --git a/tests/acceptance/01_vars/01_basic/os_version_minor.cf b/tests/acceptance/01_vars/01_basic/os_version_minor.cf new file mode 100644 index 0000000000..54134cbbe6 --- /dev/null +++ b/tests/acceptance/01_vars/01_basic/os_version_minor.cf @@ -0,0 +1,74 @@ +body common control +{ + bundlesequence => { "test", "check" }; +} + +bundle agent test +{ + + vars: + # Platforms to test + any:: + "platforms" + slist => { "debian", "ubuntu", "redhat", "rhel", "centos", "fedora", + "aix", "hpux", "suse", "opensuse", "opensuse_leap", "sles", + "solaris", "sunos", "windows", "freebsd", "macos" }; + + + # Regex matching current platforms OS-class with version numbers + !solaris&!sunos:: + "class_regex" + string => format("^(%s)_[0-9]+_[0-9]+$", join("|", "platforms")); + solaris|sunos:: + "class_regex" + string => format("^(%s)_[0-9]+$", join("|", "platforms")); + + # Regex to extract major version number from OS-class + # Edge cases: + # - On Solaris/SunOS major version comes second + # E.g. Solaris 11 has class "solaris_5_11" + any:: + "extract_regex" + string => ifelse("solaris|sunos", "^[a-z]+_([0-9]+)$", + "opensuse_leap", "^[a-z_]+_[0-9]+_([0-9]+$)", + "^[a-z]+_[0-9]+_([0-9]+$)"); + + # Find OS-class with version numbers using regex + any:: + "os_class" + string => nth(classesmatching("$(class_regex)"), "0"); + + # Get extracted major version number + any:: + "expected" + string => nth("version_number", "1"); + + classes: + any:: + "regextract_success" + expression => regextract("$(extract_regex)", "$(os_class)", "version_number"); +} + +bundle agent check +{ + vars: + any:: + "defined_classes" + slist => classesmatching(".*"); + + classes: + any:: + "passed" + expression => strcmp("$(test.expected)", "$(sys.os_version_minor)"); + + reports: + DEBUG:: + "Version number extracted from class: $(test.os_class)"; + "Defined classes: $(defined_classes)"; + "$(this.promise_filename) Expected: $(test.expected)"; + "$(this.promise_filename) Found: $(sys.os_version_minor)"; + passed:: + "$(this.promise_filename) Pass"; + !passed:: + "$(this.promise_filename) FAIL"; +}