Skip to content

Commit

Permalink
CFE-4408: Fixed package promises with only promisers and no other att…
Browse files Browse the repository at this point in the history
…ributes

CFE-4315 introduced a behavior change so that in the case of a simple package promise with only a promiser:

packages:
  "ed";

Things would just work in the case where there was no default package manager defined with package_module_knowledge.platform_default.

In the case where package_module_knowledge.platform_default was defined this simple case would cause errors.

This change fixes this second case as well as improves logging around the choosing of v1 and v2 package promise implementations.

Some of these changes fix CFE-4398 which noted that too many INFO level messages were produced. These messages are moved to DEBUG and VERBOSE level as appropriate.

Also added "packages" promises to list of exceptions so that a bare promiser-only package promise does not cause warnings.

Ticket: CFE-4408
Changelog: title
  • Loading branch information
craigcomstock committed Jul 9, 2024
1 parent 3297066 commit 8961a77
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 8 deletions.
2 changes: 1 addition & 1 deletion cf-agent/verify_packages.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ PromiseResult VerifyPackagesPromise(EvalContext *ctx, const Promise *pp)
break;
case PACKAGE_PROMISE_TYPE_NEW_ERROR:
cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, &a,
"v1 package promise (package_method) failed sanity check.");
"v2 package promise (package_method) failed sanity check.");
break;
case PACKAGE_PROMISE_TYPE_OLD_ERROR:
cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, &a,
Expand Down
23 changes: 16 additions & 7 deletions libpromises/attributes.c
Original file line number Diff line number Diff line change
Expand Up @@ -1158,11 +1158,15 @@ Packages GetPackageConstraints(const EvalContext *ctx, const Promise *pp)
if (bodies_and_args != NULL &&
SeqLength(bodies_and_args) > 0)
{
Log(LOG_LEVEL_INFO, "Package promise had no package_method attribute so it's being assigned a value of 'generic' as default.");
Log(LOG_LEVEL_VERBOSE, "Package promise had no package_method attribute so it's being assigned a value of 'generic' as default.");
const Body *bp = SeqAt(bodies_and_args, 0); // guaranteed to be non-NULL
CopyBodyConstraintsToPromise((EvalContext*)ctx, (Promise*)pp, bp);
has_generic_package_method = true;
}
else
{
Log(LOG_LEVEL_VERBOSE, "Package promise had no package_method attibute and policy had no 'generic' package_method body so will use v2 package modules.");
}
SeqDestroy(bodies_and_args);
}

Expand Down Expand Up @@ -1257,16 +1261,21 @@ NewPackages GetNewPackageConstraints(const EvalContext *ctx, const Promise *pp)
bool have_package_policy = PromiseBundleOrBodyConstraintExists(ctx, "package_policy", pp);
if (!have_policy && !have_package_policy)
{
Log(LOG_LEVEL_DEBUG, "Package promise has no policy or package_policy attribute. Checking if package_module_knowledge.platform_default is defined to default the policy attribute to 'present' and force use of v2 package promise (package_module).");
Log(LOG_LEVEL_DEBUG, "Package promise has no policy or package_policy attribute. Checking if default:control_common.package_module is defined to default the policy attribute to 'present' and force use of v2 package promise (package_module).");

const void *ret = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_PACKAGE_MODULE);
PackageModuleBody *package_module = GetPackageModuleFromContext(ctx, ret);

VarRef *ref = VarRefParseFromScope("package_module_knowledge.platform_default", NULL);
const void *ret = EvalContextVariableGet(ctx, ref, NULL);
if (ret != NULL)
if (package_module != NULL)
{
Log(LOG_LEVEL_INFO, "Package promise had no policy or package_policy attribute and package_module_knowledge.platform_default is defined so defaulting to v2 package promise (package_module) and setting 'policy' attribute to 'present'.");
Log(LOG_LEVEL_DEBUG, "Package promise had no policy or package_policy attribute and default:control_common.package_module is defined so defaulting to v2 package promise (package_module) and setting 'policy' attribute to 'present' and 'package_module' to %s.", package_module->name);
PromiseAppendConstraint((Promise*)pp, "policy", (Rval) {xstrdup("present"), RVAL_TYPE_SCALAR }, false);
PromiseAppendConstraint((Promise*)pp, "package_module_name", (Rval) {xstrdup(package_module->name), RVAL_TYPE_SCALAR }, false);
}
else
{
Log(LOG_LEVEL_VERBOSE, "Package promise had no policy or package_policy attribute and default:control_common.package_module is undefined so will use v1 package promise (package_method).");
}
VarRefDestroy(ref);
}
p.package_policy = GetNewPackagePolicy(PromiseGetConstraintAsRval(pp, "policy", RVAL_TYPE_SCALAR),
new_packages_actions);
Expand Down
1 change: 1 addition & 0 deletions libpromises/cf3parse_logic.h
Original file line number Diff line number Diff line change
Expand Up @@ -1084,6 +1084,7 @@ static inline void ParserCheckPromiseLine()
// The following promise types does not require any actions
static const char *const exceptions[] = {
"classes", "commands", "methods", "reports", "insert_lines",
"packages",
"delete_lines", "build_xpath", "insert_tree" };
static const size_t num_exceptions = sizeof(exceptions) / sizeof(exceptions[0]);

Expand Down
48 changes: 48 additions & 0 deletions tests/acceptance/07_packages/default_package_module.cf
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Based on 07_package/package_module_path.cf

body common control
{
inputs => { "../default.cf.sub" };
bundlesequence => { default("$(this.promise_filename)") };
package_module => test_module; # important! part of this specific test
}

bundle agent init
{
files:
"$(sys.workdir)/modules/packages/."
create => "true";
"$(sys.workdir)/modules/packages/test_module_script.sh"
copy_from => local_cp("$(this.promise_filename).module"),
perms => m("ugo+x");
}

body package_module test_module
{
query_installed_ifelapsed => "60";
query_updates_ifelapsed => "14400";
default_options => { "$(G.testfile)" };
module_path => "$(sys.workdir)/modules/packages/test_module_script.sh";
}

bundle agent test
{
meta:
"description"
string => "Test that a package with no attributes uses a configured common control package_module",
meta => { "CFE-4408" };
"test_soft_fail" string => "windows",
meta => { "ENT-10217" };

packages:
"first_pkg";
"second_pkg";
}

bundle agent check
{
methods:
"any" usebundle => dcs_check_diff($(G.testfile),
"$(this.promise_filename).expected",
$(this.promise_filename));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Name=first_pkg
Version=1.0
Architecture=generic
Name=second_pkg
Version=1.0
Architecture=generic
69 changes: 69 additions & 0 deletions tests/acceptance/07_packages/default_package_module.cf.module
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!/bin/sh

set -e

remove_prefix()
{
echo "$1" | sed "s/$2//"
}

case "$1" in
supports-api-version)
echo 1
;;
get-package-data)
while read line; do
case "$line" in
File=*)
echo PackageType=repo
echo Name=`remove_prefix "${line}" "File="`
;;
*)
true
;;
esac
done
;;
list-installed)
while read line; do
case "$line" in
options=*)
OUTPUT=`remove_prefix "${line}" "options="`
;;
*)
exit 1
;;
esac
done
if [ -f "$OUTPUT" ]; then
cat "$OUTPUT"
fi
;;
list-*)
# Drain input.
cat > /dev/null
;;
repo-install)
while read line; do
case "$line" in
options=*)
OUTPUT=`remove_prefix "${line}" "options="`
;;
Name=*)
NAME=`remove_prefix "${line}" "Name="`
;;
*)
exit 1
;;
esac
done
echo "Name=$NAME" >> "$OUTPUT"
echo "Version=1.0" >> "$OUTPUT"
echo "Architecture=generic" >> "$OUTPUT"
;;
*)
exit 1
;;
esac

exit 0

0 comments on commit 8961a77

Please sign in to comment.