Hello community, here is the log from the commit of package cfengine for openSUSE:Factory checked in at 2016-08-12 15:44:33 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/cfengine (Old) and /work/SRC/openSUSE:Factory/.cfengine.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "cfengine" Changes: -------- --- /work/SRC/openSUSE:Factory/cfengine/cfengine.changes 2016-06-23 13:37:34.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.cfengine.new/cfengine.changes 2016-08-12 15:44:34.000000000 +0200 @@ -1,0 +2,22 @@ +Fri Aug 5 10:30:01 UTC 2016 - kkae...@suse.com + +- Update to 3.9.1 + - Change: Log level for keeping verbatim JSON to DEBUG (CFE-2141) + - Change (masterfiles): Definition of from_cfexecd for + cf-execd initiated runs (CFE-2386) + - Change: Switch processes restart_class logging to verbose + - Change: Enable agent component management policy on systemd hosts + (CFE-2429) + - Change: Remove executable bit from systemd units (CFE-2436) + - Change: Require network before cfengine services (CFE-2435) + - Fix 'contain' attribute 'no_output' having no effect when + the 'commands' promise is using 'module => "true"'. (CFE-2412) + - Fix: Services starting or stopping unnecessarily (CFE-2421) + - Fix occasional segfault when running getindices() on a + variable that has indices of multiple depths (e.g. both "a[x]" and + "a[x][y]"). (CFE-2397) + - Fix bug in files promise when multiple owners are promised + but first one doesn't exist, and improve logging . (CFE-2432) + - fix: memory leaks + +------------------------------------------------------------------- Old: ---- cfengine-3.9.0.tar.gz New: ---- cfengine-3.9.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ cfengine.spec ++++++ --- /var/tmp/diff_new_pack.GJlhUH/_old 2016-08-12 15:44:36.000000000 +0200 +++ /var/tmp/diff_new_pack.GJlhUH/_new 2016-08-12 15:44:36.000000000 +0200 @@ -16,7 +16,7 @@ # -%define srcversion 3.9.0 +%define srcversion 3.9.1 %define srcname %{name}-%{srcversion} %define libname libpromises %define libsoname %{libname}3 ++++++ cfengine-3.9.0.tar.gz -> cfengine-3.9.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cfengine-3.9.0/ChangeLog new/cfengine-3.9.1/ChangeLog --- old/cfengine-3.9.0/ChangeLog 2016-06-06 12:01:06.000000000 +0200 +++ new/cfengine-3.9.1/ChangeLog 2016-07-28 23:25:32.000000000 +0200 @@ -1,3 +1,22 @@ +3.9.1: + - Change: Log level for keeping verbatim JSON to DEBUG (CFE-2141) + - Change (masterfiles): Definition of from_cfexecd for + cf-execd initiated runs (CFE-2386) + - Change: Switch processes restart_class logging to verbose + - Change: Enable agent component management policy on systemd hosts + (CFE-2429) + - Change: Remove executable bit from systemd units (CFE-2436) + - Change: Require network before cfengine services (CFE-2435) + - Fix 'contain' attribute 'no_output' having no effect when + the 'commands' promise is using 'module => "true"'. (CFE-2412) + - Fix: Services starting or stopping unnecessarily (CFE-2421) + - Fix occasional segfault when running getindices() on a + variable that has indices of multiple depths (e.g. both "a[x]" and + "a[x][y]"). (CFE-2397) + - Fix bug in files promise when multiple owners are promised + but first one doesn't exist, and improve logging . (CFE-2432) + - fix: memory leaks + 3.9.0: New features/additions: - Classes promise: allow classes without an expression to default to defined. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cfengine-3.9.0/cf-agent/cf-agent.c new/cfengine-3.9.1/cf-agent/cf-agent.c --- old/cfengine-3.9.0/cf-agent/cf-agent.c 2016-06-06 12:01:06.000000000 +0200 +++ new/cfengine-3.9.1/cf-agent/cf-agent.c 2016-07-28 23:25:32.000000000 +0200 @@ -1105,14 +1105,20 @@ Banner("Begin policy/promise evaluation"); - if (config->bundlesequence) + if (config->bundlesequence != NULL) { Log(LOG_LEVEL_INFO, "Using command line specified bundlesequence"); - bundlesequence = config->bundlesequence; + bundlesequence = RlistCopy(config->bundlesequence); } - else if (!(bundlesequence = (Rlist *)EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_BUNDLESEQUENCE))) + else { - RlistAppendScalar(&bundlesequence, "main"); + bundlesequence = RlistCopy((Rlist *) EvalContextVariableControlCommonGet( + ctx, COMMON_CONTROL_BUNDLESEQUENCE)); + + if (bundlesequence == NULL) + { + RlistAppendScalar(&bundlesequence, "main"); + } } bool ok = true; @@ -1225,6 +1231,8 @@ } } } + + RlistDestroy(bundlesequence); } static void AllClassesReport(const EvalContext *ctx) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cfengine-3.9.0/cf-agent/verify_exec.c new/cfengine-3.9.1/cf-agent/verify_exec.c --- old/cfengine-3.9.0/cf-agent/verify_exec.c 2016-06-06 12:01:06.000000000 +0200 +++ new/cfengine-3.9.1/cf-agent/verify_exec.c 2016-07-28 23:25:32.000000000 +0200 @@ -384,7 +384,8 @@ { ModuleProtocol(ctx, cmdline, line, !a.contain.nooutput, module_context, module_tags, &persistence); } - else if ((!a.contain.nooutput) && (!EmptyString(line))) + + if (!a.contain.nooutput && !EmptyString(line)) { lineOutLen = strlen(comm) + strlen(line) + 12; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cfengine-3.9.0/cf-agent/verify_files_utils.c new/cfengine-3.9.1/cf-agent/verify_files_utils.c --- old/cfengine-3.9.0/cf-agent/verify_files_utils.c 2016-06-06 12:01:06.000000000 +0200 +++ new/cfengine-3.9.1/cf-agent/verify_files_utils.c 2016-07-28 23:25:32.000000000 +0200 @@ -3580,93 +3580,97 @@ struct group *gp; UidList *ulp; GidList *glp; - short uidmatch = false, gidmatch = false; - uid_t uid = CF_SAME_OWNER; - gid_t gid = CF_SAME_GROUP; + /* The groups to change ownership to, using lchown(uid,gid). */ + uid_t uid = CF_UNKNOWN_OWNER; /* just init values */ + gid_t gid = CF_UNKNOWN_GROUP; + + /* SKIP if file is already owned by anyone of the promised owners. */ for (ulp = attr.perms.owners; ulp != NULL; ulp = ulp->next) { if (ulp->uid == CF_SAME_OWNER || sb->st_uid == ulp->uid) /* "same" matches anything */ { - uid = ulp->uid; - uidmatch = true; + uid = CF_SAME_OWNER; /* chown(-1) doesn't change ownership */ break; } } - if (attr.perms.groups->next == NULL && attr.perms.groups->gid == CF_UNKNOWN_GROUP) // Only one non.existent item + if (uid != CF_SAME_OWNER) { - cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Unable to make file belong to an unknown group"); - *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); - } - - if (attr.perms.owners->next == NULL && attr.perms.owners->uid == CF_UNKNOWN_OWNER) // Only one non.existent item - { - cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Unable to make file belong to an unknown user"); - *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); + /* Change ownership to the first known user in the promised list. */ + for (ulp = attr.perms.owners; ulp != NULL; ulp = ulp->next) + { + if (ulp->uid != CF_UNKNOWN_OWNER) + { + uid = ulp->uid; + break; + } + } + if (ulp == NULL) + { + cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, + "None of the promised owners for '%s' exist -- see INFO logs for more", + file); + *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); + uid = CF_SAME_OWNER; /* chown(-1) doesn't change ownership */ + } } + assert(uid != CF_UNKNOWN_OWNER); + /* SKIP if file is already group owned by anyone of the promised groups. */ for (glp = attr.perms.groups; glp != NULL; glp = glp->next) { - if (glp->gid == CF_SAME_GROUP || sb->st_gid == glp->gid) /* "same" matches anything */ + if (glp->gid == CF_SAME_GROUP || sb->st_gid == glp->gid) { - gid = glp->gid; - gidmatch = true; + gid = CF_SAME_GROUP; /* chown(-1) doesn't change ownership */ break; } } - if (uidmatch && gidmatch) + /* Change group ownership to the first known group in the promised list. */ + if (gid != CF_SAME_GROUP) { - return false; - } - else - { - if (!uidmatch) + for (glp = attr.perms.groups; glp != NULL; glp = glp->next) { - for (ulp = attr.perms.owners; ulp != NULL; ulp = ulp->next) + if (glp->gid != CF_UNKNOWN_GROUP) { - if (attr.perms.owners->uid != CF_UNKNOWN_OWNER) - { - uid = attr.perms.owners->uid; /* default is first (not unknown) item in list */ - break; - } + gid = glp->gid; + break; } } - - if (!gidmatch) + if (glp == NULL) { - for (glp = attr.perms.groups; glp != NULL; glp = glp->next) - { - if (attr.perms.groups->gid != CF_UNKNOWN_GROUP) - { - gid = attr.perms.groups->gid; /* default is first (not unknown) item in list */ - break; - } - } + cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, + "None of the promised groups for '%s' exist -- see INFO logs for more", + file); + *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); + gid = CF_SAME_GROUP; /* chown(-1) doesn't change ownership */ } + } + assert(gid != CF_UNKNOWN_GROUP); + if (uid == CF_SAME_OWNER && + gid == CF_SAME_GROUP) + { + /* User and group as promised, skip completely. */ + return false; + } + else + { switch (attr.transaction.action) { case cfa_fix: - if (uid == CF_SAME_OWNER && gid == CF_SAME_GROUP) + if (uid != CF_SAME_OWNER) { - Log(LOG_LEVEL_VERBOSE, "Touching '%s'", file); + Log(LOG_LEVEL_DEBUG, "Change owner to uid '%ju' if possible", + (uintmax_t) uid); } - else - { - if (uid != CF_SAME_OWNER) - { - Log(LOG_LEVEL_DEBUG, "Change owner to uid '%ju' if possible", - (uintmax_t) uid); - } - if (gid != CF_SAME_GROUP) - { - Log(LOG_LEVEL_DEBUG, "Change group to gid '%ju' if possible", - (uintmax_t) gid); - } + if (gid != CF_SAME_GROUP) + { + Log(LOG_LEVEL_DEBUG, "Change group to gid '%ju' if possible", + (uintmax_t) gid); } if (!DONTDO && S_ISLNK(sb->st_mode)) @@ -3685,7 +3689,7 @@ } else if (!DONTDO) { - if (!uidmatch) + if (uid != CF_SAME_OWNER) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, attr, "Owner of '%s' was %ju, setting to %ju", @@ -3693,10 +3697,11 @@ *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); } - if (!gidmatch) + if (gid != CF_SAME_GROUP) { - cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, attr, "Group of '%s' was %ju, setting to %ju", file, (uintmax_t)sb->st_gid, - (uintmax_t)gid); + cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, attr, + "Group of '%s' was %ju, setting to %ju", + file, (uintmax_t)sb->st_gid, (uintmax_t)gid); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cfengine-3.9.0/cf-agent/verify_processes.c new/cfengine-3.9.1/cf-agent/verify_processes.c --- old/cfengine-3.9.0/cf-agent/verify_processes.c 2016-06-06 12:01:06.000000000 +0200 +++ new/cfengine-3.9.1/cf-agent/verify_processes.c 2016-07-28 23:25:32.000000000 +0200 @@ -246,8 +246,8 @@ else { PromiseResult status = killed ? PROMISE_RESULT_CHANGE : PROMISE_RESULT_NOOP; - cfPS(ctx, LOG_LEVEL_INFO, status, pp, a, - "Setting restart class '%s' for promise '%s'", a.restart_class, pp->promiser); + cfPS(ctx, LOG_LEVEL_VERBOSE, status, pp, a, + "C: + Global class: %s ", a.restart_class); result = PromiseResultUpdate(result, status); EvalContextClassPutSoft(ctx, a.restart_class, CONTEXT_SCOPE_NAMESPACE, "source=promise"); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cfengine-3.9.0/configure new/cfengine-3.9.1/configure --- old/cfengine-3.9.0/configure 2016-06-06 12:01:47.000000000 +0200 +++ new/cfengine-3.9.1/configure 2016-07-28 23:26:45.000000000 +0200 @@ -3197,7 +3197,7 @@ # Define the identity of the package. PACKAGE=cfengine - VERSION=3.9.0 + VERSION=3.9.1 cat >>confdefs.h <<_ACEOF diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cfengine-3.9.0/configure.ac new/cfengine-3.9.1/configure.ac --- old/cfengine-3.9.0/configure.ac 2016-06-06 12:01:06.000000000 +0200 +++ new/cfengine-3.9.1/configure.ac 2016-07-28 23:25:32.000000000 +0200 @@ -29,7 +29,7 @@ dnl # dnl ########################################################################## -AC_PREREQ(2.59) +AC_PREREQ(2.63) AC_INIT AC_CONFIG_SRCDIR([libpromises/generic_agent.c]) @@ -41,18 +41,18 @@ dnl AC_CHECK_PROG(MAKEINFO, makeinfo, makeinfo) -m4_define([revision], m4_esyscmd_s([git rev-list -1 --abbrev-commit HEAD])) +m4_define([revision], m4_normalize(m4_esyscmd([git rev-list -1 --abbrev-commit HEAD]))) -m4_define([cfversion_from_env], m4_esyscmd_s([echo $EXPLICIT_VERSION])) -m4_ifblank(cfversion_from_env, [ - m4_define([cfversion_from_detect], m4_esyscmd_s([misc/determine-version.py])) +m4_define([cfversion_from_env], m4_normalize(m4_esyscmd([echo $EXPLICIT_VERSION]))) +m4_ifval(cfversion_from_env, [ + m4_define([cfversion], cfversion_from_env) +], [ + m4_define([cfversion_from_detect], m4_normalize(m4_esyscmd([misc/determine-version.py]))) m4_if(m4_sysval, 0, [], [ m4_fatal([Could not determine CFEngine version. Please set EXPLICIT_VERSION in the environment or make sure all git tags are up to date.]) ]) m4_define([cfversion], cfversion_from_detect[]a1.revision) m4_undefine([cfversion_from_detect]) -], [ - m4_define([cfversion], cfversion_from_env) ]) _AM_SET_OPTION([tar-ustar]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cfengine-3.9.0/examples/randomint.cf new/cfengine-3.9.1/examples/randomint.cf --- old/cfengine-3.9.0/examples/randomint.cf 2016-06-06 12:01:06.000000000 +0200 +++ new/cfengine-3.9.1/examples/randomint.cf 2016-07-28 23:25:32.000000000 +0200 @@ -21,12 +21,7 @@ # included file COSL.txt. #+begin_src cfengine3 -body common control -{ - bundlesequence => { "randomint_example" }; -} - -bundle agent randomint_example +bundle agent main { vars: "low" string => "4"; @@ -39,9 +34,20 @@ reports: isabove:: "The generated random number was above 3"; + + show_random:: + "Randomly generated '$(random)'"; } #+end_src ############################################################################### +#+begin_src show_random_example_output +#@ ``` +#@ R: The generated random number was above 3 +#@ R: Randomly generated '9' +#@ R: Randomly generated '52' +#@ R: Randomly generated '26' +#@ ``` +#+end_src #+begin_src example_output #@ ``` #@ R: The generated random number was above 3 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cfengine-3.9.0/examples/regline.cf new/cfengine-3.9.1/examples/regline.cf --- old/cfengine-3.9.0/examples/regline.cf 2016-06-06 12:01:06.000000000 +0200 +++ new/cfengine-3.9.1/examples/regline.cf 2016-07-28 23:25:32.000000000 +0200 @@ -24,39 +24,43 @@ # Function regline(regex,file) ###################################################################### -body common control - -{ - version => "1.2.3"; - bundlesequence => { "example" }; -} - -######################################################## - -bundle agent example - +#+begin_src cfengine3 +bundle agent main +# @brief An example showing how to use regline to see if a pattern exists within +# a file. { - files: + vars: - "/tmp/testfile" + linux:: - edit_line => test; + "file" string => "/proc/sys/net/ipv4/ip_forward"; + "reg_enabled" string => "^1$"; + "reg_disabled" string => "^0$"; -} + classes: -######################################################## + linux:: -bundle edit_line test -{ - classes: + "ipv4_forwarding_enabled" -> { "SecOps" } + expression => regline( $(reg_enabled) , $(file) ), + comment => "We want to know if ip forwarding is enabled because it is a + potential security issue."; - "ok" expression => regline(".*mark.*","$(edit.filename)"); + "ipv4_forwarding_disabled" -> { "SecOps" } + expression => regline( $(reg_disabled) , $(file) ); reports: - ok:: - - "File matched $(edit.filename)"; + ipv4_forwarding_enabled:: + "I found that IPv4 forwarding is enabled!"; + ipv4_forwarding_disabled:: + "I found that IPv4 forwarding is disabled."; } +#+end_src +#+begin_src example_output +#@ ``` +#@ R: I found that IPv4 forwarding is disabled. +#@ ``` +#+end_src diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cfengine-3.9.0/examples/services.cf new/cfengine-3.9.1/examples/services.cf --- old/cfengine-3.9.0/examples/services.cf 1970-01-01 01:00:00.000000000 +0100 +++ new/cfengine-3.9.1/examples/services.cf 2016-07-28 23:25:32.000000000 +0200 @@ -0,0 +1,56 @@ +body file control +{ + inputs => { "$(sys.libdir)/services.cf", "$(sys.libdir)/commands.cf" }; +} + +bundle agent main +# @brief Example showing services promises to manage standard operating system +# services +{ + vars: + + linux:: + "enable[ssh]" + string => ifelse( "debian|ubuntu", "ssh", "sshd"), + comment => "The name of the ssh service varies on different platforms. + Here we set the name of the service based on existing + classes and defaulting to `sshd`"; + + "disable[apache]" + string => ifelse( "debian|ubuntu", "apache2", "httpd" ), + comment => "The name of the apache web service varies on different + platforms. Here we set the name of the service based on + existing classes and defaulting to `httpd`"; + + "enable[cron]" + string => ifelse( "debian|ubuntu", "cron", "crond" ), + comment => "The name of the cron service varies on different + platforms. Here we set the name of the service based on + existing classes and defaulting to `crond`"; + + "disable[cups]" + string => "cups", + comment => "Printing services are not needed on most hosts."; + + "enabled" slist => getvalues( enable ); + "disabled" slist => getvalues( disable ); + + services: + + linux:: + + "$(enabled)" -> { "SysOps" } + service_policy => "start", + comment => "These services should be running because x, y or z."; + + "$(disabled)" -> { "SysOps" } + service_policy => "stop", + comment => "These services should not be running because x, y or z."; + + systemd:: + + "sysstat" + service_policy => "stop", + comment => "Standard service handling for sysstat only works with + systemd. Other inits need cron entries managed."; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cfengine-3.9.0/libcfnet/conn_cache.c new/cfengine-3.9.1/libcfnet/conn_cache.c --- old/cfengine-3.9.0/libcfnet/conn_cache.c 2016-06-06 12:01:06.000000000 +0200 +++ new/cfengine-3.9.1/libcfnet/conn_cache.c 2016-07-28 23:25:32.000000000 +0200 @@ -82,7 +82,7 @@ DisconnectServer(svp->conn); } - SeqClear(conn_cache); + SeqDestroy(conn_cache); conn_cache = NULL; ThreadUnlock(&cft_conncache); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cfengine-3.9.0/libenv/unix_iface.c new/cfengine-3.9.1/libenv/unix_iface.c --- old/cfengine-3.9.0/libenv/unix_iface.c 2016-06-06 12:01:06.000000000 +0200 +++ new/cfengine-3.9.1/libenv/unix_iface.c 2016-07-28 23:25:33.000000000 +0200 @@ -1186,7 +1186,7 @@ EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "inet", inet, CF_DATA_TYPE_CONTAINER, "inventory,networking,/proc,source=agent,attribute_name=none,procfs"); - + JsonDestroy(inet); JsonElement *inet6 = JsonObjectCreate(3); @@ -1247,12 +1247,14 @@ EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "inet6", inet6, CF_DATA_TYPE_CONTAINER, "inventory,networking,/proc,source=agent,attribute_name=none,procfs"); + JsonDestroy(inet6); // Inter-| Receive | Transmit // face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed // eth0: 74850544807 75236137 0 0 0 0 0 1108775 63111535625 74696758 0 0 0 0 0 0 BufferPrintf(pbuf, "%s/proc/net/dev", procdir); + JsonElement *interfaces_data = GetProcFileInfo(ctx, BufferData(pbuf), "interfaces_data", "device", NULL, "^\\s*(?<device>[^:]+)\\s*:\\s*" // All of the below are just decimal digits separated by spaces @@ -1272,7 +1274,7 @@ "(?<transmit_frame>\\d+)\\s+" "(?<transmit_compressed>\\d+)\\s+" "(?<transmit_multicast>\\d+)"); - + JsonDestroy(interfaces_data); BufferDestroy(pbuf); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cfengine-3.9.0/libpromises/attributes.c new/cfengine-3.9.1/libpromises/attributes.c --- old/cfengine-3.9.0/libpromises/attributes.c 2016-06-06 12:01:06.000000000 +0200 +++ new/cfengine-3.9.1/libpromises/attributes.c 2016-07-28 23:25:33.000000000 +0200 @@ -364,7 +364,14 @@ e.owner = PromiseGetConstraintAsUid(ctx, "exec_owner", pp); e.group = PromiseGetConstraintAsGid(ctx, "exec_group", pp); e.preview = PromiseGetConstraintAsBoolean(ctx, "preview", pp); - e.nooutput = PromiseGetConstraintAsBoolean(ctx, "no_output", pp); + if (PromiseBundleOrBodyConstraintExists(ctx, "no_output", pp)) + { + e.nooutput = PromiseGetConstraintAsBoolean(ctx, "no_output", pp); + } + else + { + e.nooutput = PromiseGetConstraintAsBoolean(ctx, "module", pp); + } e.timeout = PromiseGetConstraintAsInt(ctx, "exec_timeout", pp); e.chroot = PromiseGetConstraintAsRval(pp, "chroot", RVAL_TYPE_SCALAR); e.chdir = PromiseGetConstraintAsRval(pp, "chdir", RVAL_TYPE_SCALAR); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cfengine-3.9.0/libpromises/bootstrap.inc new/cfengine-3.9.1/libpromises/bootstrap.inc --- old/cfengine-3.9.0/libpromises/bootstrap.inc 2016-06-06 12:02:41.000000000 +0200 +++ new/cfengine-3.9.1/libpromises/bootstrap.inc 2016-07-28 23:28:55.000000000 +0200 @@ -197,10 +197,10 @@ " handle => \"failsafe_cfe_internal_bootstrap_update_commands_check_sys_cf_execd_start\",\n" " classes => failsafe_results(\"namespace\", \"cf_execd_running\");\n" "\n" - " cf_serverd_not_running.!systemd::\n" + " cf_serverd_not_running.!(windows|systemd)::\n" "\n" - " # cf-serverd is not launched directly on systemd and is handled\n" - " # seperately.\n" + " # cf-serverd is not launched directly on Windows and systemd and is\n" + " # handled separately.\n" "\n" " \"$(sys.cf_serverd)\"\n" " handle => \"failsafe_cfe_internal_bootstrap_update_commands_check_sys_cf_serverd_start\",\n" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cfengine-3.9.0/libpromises/cf3.defs.h new/cfengine-3.9.1/libpromises/cf3.defs.h --- old/cfengine-3.9.0/libpromises/cf3.defs.h 2016-06-06 12:01:06.000000000 +0200 +++ new/cfengine-3.9.1/libpromises/cf3.defs.h 2016-07-28 23:25:33.000000000 +0200 @@ -75,6 +75,7 @@ #define CF_MACROALPHABET 61 /* a-z, A-Z plus a bit */ #define CF_ALPHABETSIZE 256 #define CF_SAMEMODE 7777 +/* CF_SAME_OWNER/GROUP should be -1; chown(-1) doesn't change ownership. */ #define CF_SAME_OWNER ((uid_t)-1) #define CF_UNKNOWN_OWNER ((uid_t)-2) #define CF_SAME_GROUP ((gid_t)-1) @@ -1098,7 +1099,7 @@ char *chdir; char *chroot; int preview; - int nooutput; + bool nooutput; int timeout; } ExecContain; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cfengine-3.9.0/libpromises/eval_context.c new/cfengine-3.9.1/libpromises/eval_context.c --- old/cfengine-3.9.0/libpromises/eval_context.c 2016-06-06 12:01:06.000000000 +0200 +++ new/cfengine-3.9.1/libpromises/eval_context.c 2016-07-28 23:25:33.000000000 +0200 @@ -2245,11 +2245,12 @@ const char *callee_reference, const char *callee_type) { ClassRef ref = IDRefQualify(ctx, callee_reference); - Seq *bodies = SeqNew(2, NULL); + Seq *bodies = NULL; const Body *bp = EvalContextFindFirstMatchingBody(policy, callee_type, ref.ns, ref.name); if (bp) { + bodies = SeqNew(2, NULL); SeqAppend(bodies, (void *)bp); SeqAppend(bodies, (void *)NULL); EvalContextAppendBodyParentsAndArgs(ctx, policy, bodies, bp, callee_type, 1); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cfengine-3.9.0/libpromises/evalfunction.c new/cfengine-3.9.1/libpromises/evalfunction.c --- old/cfengine-3.9.0/libpromises/evalfunction.c 2016-06-06 12:01:06.000000000 +0200 +++ new/cfengine-3.9.1/libpromises/evalfunction.c 2016-07-28 23:25:33.000000000 +0200 @@ -2255,6 +2255,8 @@ static FnCallResult FnCallGetIndices(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { const char *name_str = RlistScalarValueSafe(finalargs); + bool allocated = false; + JsonElement *json = NULL; // Protect against collected args (their rval type will be data // container). This is a special case to preserve legacy behavior @@ -2264,19 +2266,49 @@ VarRef *ref = ResolveAndQualifyVarName(fp, name_str); DataType type = CF_DATA_TYPE_NONE; EvalContextVariableGet(ctx, ref, &type); - VarRefDestroy(ref); - if (type != CF_DATA_TYPE_CONTAINER && - StringMatchFull(".*[a-zA-Z0-9_](\\[[a-zA-Z0-9_]+\\])+$", name_str)) + if (type != CF_DATA_TYPE_CONTAINER) { - return FnCallGetIndicesClassic(ctx, policy, fp, finalargs); + JsonParseError res = JsonParseWithLookup(ctx, &LookupVarRefToJson, &name_str, &json); + if (res == JSON_PARSE_OK) + { + if (JsonGetElementType(json) == JSON_ELEMENT_TYPE_PRIMITIVE) + { + // VarNameOrInlineToJson() would now look up this primitive + // in the variable table, returning a JSON container for + // whatever type it is, but since we already know that it's + // not a native container type (thanks to the + // CF_DATA_TYPE_CONTAINER check above) we skip that, and + // stick to the legacy data types. + JsonDestroy(json); + VarRefDestroy(ref); + return FnCallGetIndicesClassic(ctx, policy, fp, finalargs); + } + else + { + // Inline JSON of some sort. + allocated = true; + } + } + else + { + // Invalid inline JSON. Same case as Classic case above. + VarRefDestroy(ref); + return FnCallGetIndicesClassic(ctx, policy, fp, finalargs); + } + } + else + { + // A variable holding a container. + json = VarRefValueToJson(ctx, fp, ref, NULL, 0, true, &allocated); } - } - // Try to load directly. This case will behave correctly whether - // finalrgs holds a scalar or not. - bool allocated = false; - JsonElement *json = VarNameOrInlineToJson(ctx, fp, finalargs, true, &allocated); + VarRefDestroy(ref); + } + else + { + json = VarNameOrInlineToJson(ctx, fp, finalargs, true, &allocated); + } // we failed to produce a valid JsonElement, so give up if (NULL == json) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cfengine-3.9.0/libpromises/failsafe.cf new/cfengine-3.9.1/libpromises/failsafe.cf --- old/cfengine-3.9.0/libpromises/failsafe.cf 2016-06-06 12:01:06.000000000 +0200 +++ new/cfengine-3.9.1/libpromises/failsafe.cf 2016-07-28 23:25:33.000000000 +0200 @@ -197,10 +197,10 @@ handle => "failsafe_cfe_internal_bootstrap_update_commands_check_sys_cf_execd_start", classes => failsafe_results("namespace", "cf_execd_running"); - cf_serverd_not_running.!systemd:: + cf_serverd_not_running.!(windows|systemd):: - # cf-serverd is not launched directly on systemd and is handled - # seperately. + # cf-serverd is not launched directly on Windows and systemd and is + # handled separately. "$(sys.cf_serverd)" handle => "failsafe_cfe_internal_bootstrap_update_commands_check_sys_cf_serverd_start", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cfengine-3.9.0/libpromises/fncall.c new/cfengine-3.9.1/libpromises/fncall.c --- old/cfengine-3.9.0/libpromises/fncall.c 2016-06-06 12:01:06.000000000 +0200 +++ new/cfengine-3.9.1/libpromises/fncall.c 2016-07-28 23:25:33.000000000 +0200 @@ -334,8 +334,8 @@ Rlist *expargs = NewExpArgs(ctx, policy, fp); - Writer *fncall_writer; - const char *fncall_string; + Writer *fncall_writer = NULL; + const char *fncall_string = ""; if (LogGetGlobalLevel() >= LOG_LEVEL_DEBUG) { fncall_writer = StringWriter(); @@ -345,15 +345,29 @@ if (RlistIsUnresolved(expargs)) { - if (LogGetGlobalLevel() >= LOG_LEVEL_DEBUG) + // Special case: ifelse(isvariable("x"), $(x), "default") + // (the first argument will come down expanded as "!any") + if (0 == strcmp(fp->name, "ifelse") && + RlistLen(expargs) == 3 && + 0 == strcmp("!any", RlistScalarValueSafe(expargs)) && + !RlistIsUnresolved(expargs->next->next)) { - Log(LOG_LEVEL_DEBUG, "Skipping function evaluation for now," - " arguments contain unresolved variables: %s", - fncall_string); - WriterClose(fncall_writer); + Log(LOG_LEVEL_DEBUG, "Allowing ifelse() function evaluation even" + " though its arguments contain unresolved variables: %s", + fncall_string); + } + else + { + if (LogGetGlobalLevel() >= LOG_LEVEL_DEBUG) + { + Log(LOG_LEVEL_DEBUG, "Skipping function evaluation for now," + " arguments contain unresolved variables: %s", + fncall_string); + WriterClose(fncall_writer); + } + RlistDestroy(expargs); + return (FnCallResult) { FNCALL_FAILURE, { FnCallCopy(fp), RVAL_TYPE_FNCALL } }; } - RlistDestroy(expargs); - return (FnCallResult) { FNCALL_FAILURE, { FnCallCopy(fp), RVAL_TYPE_FNCALL } }; } Rval cached_rval; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cfengine-3.9.0/libpromises/var_expressions.c new/cfengine-3.9.1/libpromises/var_expressions.c --- old/cfengine-3.9.0/libpromises/var_expressions.c 2016-06-06 12:01:06.000000000 +0200 +++ new/cfengine-3.9.1/libpromises/var_expressions.c 2016-07-28 23:25:33.000000000 +0200 @@ -419,9 +419,7 @@ BufferAppend(buf, "]", sizeof(char)); } - char *var_string = xstrdup(BufferData(buf)); - BufferDestroy(buf); - return var_string; + return BufferClose(buf); } char *VarRefMangle(const VarRef *ref) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cfengine-3.9.0/libutils/json.c new/cfengine-3.9.1/libutils/json.c --- old/cfengine-3.9.0/libutils/json.c 2016-06-06 12:01:06.000000000 +0200 +++ new/cfengine-3.9.1/libutils/json.c 2016-07-28 23:25:33.000000000 +0200 @@ -1725,7 +1725,7 @@ * \u{hex digits} - we have no way to represent the * character they denote. So keep them verbatim, for * want of any other way to handle them; but warn. */ - Log(LOG_LEVEL_WARNING, + Log(LOG_LEVEL_DEBUG, "Keeping verbatim unrecognised JSON escape '%.6s'", *data - 1); /* i.e. include the \ in the displayed escape */ WriterWriteChar(writer, '\\'); @@ -2375,4 +2375,3 @@ JsonObjectRemoveKey(json, "0"); return json; } - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cfengine-3.9.0/misc/systemd/cfengine3-web.service.in new/cfengine-3.9.1/misc/systemd/cfengine3-web.service.in --- old/cfengine-3.9.0/misc/systemd/cfengine3-web.service.in 2016-06-06 12:01:06.000000000 +0200 +++ new/cfengine-3.9.1/misc/systemd/cfengine3-web.service.in 2016-07-28 23:25:33.000000000 +0200 @@ -1,6 +1,8 @@ [Unit] Description=CFEngine 3 Mission Portal daemons +Documentation=https://docs.cfengine.com After=syslog.target +After=network.target PartOf=cfengine3.service ConditionPathExists=@workdir@/bin/cfengine3-nova-hub-init-d.sh diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cfengine-3.9.0/misc/systemd/cfengine3.service.in new/cfengine-3.9.1/misc/systemd/cfengine3.service.in --- old/cfengine-3.9.0/misc/systemd/cfengine3.service.in 2016-06-06 12:01:06.000000000 +0200 +++ new/cfengine-3.9.1/misc/systemd/cfengine3.service.in 2016-07-28 23:25:33.000000000 +0200 @@ -1,6 +1,8 @@ [Unit] Description=CFEngine 3 daemons +Documentation=https://docs.cfengine.com After=syslog.target +After=network.target Wants=cfengine3-web.service After=cfengine3-web.service diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cfengine-3.9.0/tests/acceptance/01_vars/02_functions/getindices.cf new/cfengine-3.9.1/tests/acceptance/01_vars/02_functions/getindices.cf --- old/cfengine-3.9.0/tests/acceptance/01_vars/02_functions/getindices.cf 2016-06-06 12:01:06.000000000 +0200 +++ new/cfengine-3.9.1/tests/acceptance/01_vars/02_functions/getindices.cf 2016-07-28 23:25:33.000000000 +0200 @@ -13,6 +13,29 @@ ####################################################### +# Do not change the name of this bundle or of variables inside this bundle. The +# original bug CFE-2397 depended on a certain order in the variable table which +# was triggered by these names. +bundle common b +{ + vars: + "d[k]" string => "val1"; + "d[f][f1]" string => "val2"; + "d[s][s1]" string => "val3"; + + "d_keys" slist => getindices("d"); + "d_keys_f" slist => getindices("d[f]"); + "d_keys_s" slist => getindices("d[s]"); + + "c[$(d_keys)]" string => "$(d[$(d_keys)])"; + "c[f][$(d_keys_f)]" string => "$(d[f][$(d_keys_f)])"; + "c[s][$(d_keys_s)]" string => "$(d[s][$(d_keys_s)])"; + + "c_keys" slist => getindices("c"); + "c_keys_f" slist => getindices("c[f]"); + "c_keys_s" slist => getindices("c[s]"); +} + bundle agent test { vars: @@ -27,6 +50,10 @@ "userfields" slist => getindices("user[fullname]"); "inline_fields" slist => getindices('{ "foo": 1, "bar": 2 }'); "inline_numfields" slist => getindices('[ "foo", 1, "bar", 2 ]'); + "inline_function" slist => getindices(parsejson('{ "a": "b", "c": "d" }')); + "c_keys" slist => { @(b.c_keys) }; + "c_keys_f" slist => { @(b.c_keys_f) }; + "c_keys_s" slist => { @(b.c_keys_s) }; } ####################################################### diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cfengine-3.9.0/tests/acceptance/01_vars/02_functions/getindices.cf.expected.json new/cfengine-3.9.1/tests/acceptance/01_vars/02_functions/getindices.cf.expected.json --- old/cfengine-3.9.0/tests/acceptance/01_vars/02_functions/getindices.cf.expected.json 2016-06-06 12:01:06.000000000 +0200 +++ new/cfengine-3.9.1/tests/acceptance/01_vars/02_functions/getindices.cf.expected.json 2016-07-28 23:25:33.000000000 +0200 @@ -1,4 +1,15 @@ { + "c_keys": [ + "s", + "f", + "k" + ], + "c_keys_f": [ + "f1" + ], + "c_keys_s": [ + "s1" + ], "fields": [ "dirs", "fullname", @@ -8,6 +19,10 @@ "foo", "bar" ], + "inline_function": [ + "a", + "c" + ], "inline_numfields": [ "0", "1", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cfengine-3.9.0/tests/acceptance/01_vars/02_functions/ifelse_isvariable.cf new/cfengine-3.9.1/tests/acceptance/01_vars/02_functions/ifelse_isvariable.cf --- old/cfengine-3.9.0/tests/acceptance/01_vars/02_functions/ifelse_isvariable.cf 2016-06-06 12:01:06.000000000 +0200 +++ new/cfengine-3.9.1/tests/acceptance/01_vars/02_functions/ifelse_isvariable.cf 2016-07-28 23:25:33.000000000 +0200 @@ -16,12 +16,7 @@ { meta: "description" - string => "Test that ifelse can use the result of isvariable - as a class identifer"; - - "test_soft_fail" - string => "any", - meta => { "redmine7878" }; + string => "Test that ifelse can use the result of isvariable as a class identifer"; vars: # Since init.passwd_file is defined, I expect the value to be @@ -39,34 +34,8 @@ bundle agent check { - classes: - "ok_passwd_file" - expression => strcmp( "/tmp/custom_passwd", $(init.passwd_file) ); - - "ok_shadow_file" - expression => strcmp( "/etc/shadow", $(init.use_shadow_file) ); - - "ok" and => { "ok_passwd_file", "ok_shadow_file" }; - - reports: - DEBUG:: - "Found test.use_passwd_file = $(test.use_passwd_file) to be as expected" - if => "ok_passwd_file"; - - "Found test.use_shadow_file = $(test.use_shadow_filee) to be as expected" - if => "ok_shadow_file"; - - "Found value for test.use_passwd_file to be INCORRECT - expected '/tmp/custom_passwd' got '$(test.use_passwd_file)'" - unless => "ok_passwd_file"; - - "Found value for test.use_shadow_file to be INCORRECT - expected '/etc/shadow' got '$(test.use_shadow_file)'" - unless => "ok_shadow_file"; - - ok:: - "$(this.promise_filename) Pass"; - - !ok:: - "$(this.promise_filename) FAIL"; + methods: + "check" usebundle => dcs_check_state(test, + "$(this.promise_filename).expected.json", + $(this.promise_filename)); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cfengine-3.9.0/tests/acceptance/01_vars/02_functions/ifelse_isvariable.cf.expected.json new/cfengine-3.9.1/tests/acceptance/01_vars/02_functions/ifelse_isvariable.cf.expected.json --- old/cfengine-3.9.0/tests/acceptance/01_vars/02_functions/ifelse_isvariable.cf.expected.json 1970-01-01 01:00:00.000000000 +0100 +++ new/cfengine-3.9.1/tests/acceptance/01_vars/02_functions/ifelse_isvariable.cf.expected.json 2016-07-28 23:25:33.000000000 +0200 @@ -0,0 +1,4 @@ +{ + "use_passwd_file": "/tmp/custom_passwd", + "use_shadow_file": "/etc/shadow" +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cfengine-3.9.0/tests/acceptance/08_commands/01_modules/module_with_no_output.cf new/cfengine-3.9.1/tests/acceptance/08_commands/01_modules/module_with_no_output.cf --- old/cfengine-3.9.0/tests/acceptance/08_commands/01_modules/module_with_no_output.cf 1970-01-01 01:00:00.000000000 +0100 +++ new/cfengine-3.9.1/tests/acceptance/08_commands/01_modules/module_with_no_output.cf 2016-07-28 23:25:33.000000000 +0200 @@ -0,0 +1,36 @@ +body common control +{ + inputs => { "../../default.cf.sub" }; + bundlesequence => { default($(this.promise_filename)) }; +} + +bundle agent init +{ + methods: + "init" usebundle => file_make("$(G.testdir)/module.output.txt", + "=myvar=good_output_1"); + + "init" usebundle => file_make("$(G.testdir)/module.no_output.txt", + "=myvar=bad_output"); + + "init" usebundle => file_make("$(G.testdir)/module.default.txt", + "=myvar=bad_output"); + + "init" usebundle => file_make("$(G.testdir)/no_module.output.txt", + "=myvar=good_output_2"); + + "init" usebundle => file_make("$(G.testdir)/no_module.no_output.txt", + "=myvar=bad_output"); + + "init" usebundle => file_make("$(G.testdir)/no_module.default.txt", + "=myvar=good_output_3"); +} + +bundle agent check +{ + methods: + "check" usebundle => dcs_passif_output(".*good_output_1.*good_output_2.*good_output_3.*", + ".*bad_output.*", + "$(sys.cf_agent) -D AUTO -Kf $(this.promise_filename).sub", + $(this.promise_filename)); +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cfengine-3.9.0/tests/acceptance/08_commands/01_modules/module_with_no_output.cf.sub new/cfengine-3.9.1/tests/acceptance/08_commands/01_modules/module_with_no_output.cf.sub --- old/cfengine-3.9.0/tests/acceptance/08_commands/01_modules/module_with_no_output.cf.sub 1970-01-01 01:00:00.000000000 +0100 +++ new/cfengine-3.9.1/tests/acceptance/08_commands/01_modules/module_with_no_output.cf.sub 2016-07-28 23:25:33.000000000 +0200 @@ -0,0 +1,33 @@ +body common control +{ + inputs => { "../../default.cf.sub" }; + bundlesequence => { default($(this.promise_filename)) }; +} + +bundle agent test +{ + commands: + "$(G.cat) $(G.testdir)/module.output.txt" + module => "true", + contain => test_contain("false"); + + "$(G.cat) $(G.testdir)/module.no_output.txt" + module => "true", + contain => test_contain("true"); + + "$(G.cat) $(G.testdir)/module.default.txt" + module => "true"; + + "$(G.cat) $(G.testdir)/no_module.output.txt" + contain => test_contain("false"); + + "$(G.cat) $(G.testdir)/no_module.no_output.txt" + contain => test_contain("true"); + + "$(G.cat) $(G.testdir)/no_module.default.txt"; +} + +body contain test_contain(no_output) +{ + no_output => "$(no_output)"; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cfengine-3.9.0/tests/acceptance/10_files/unsafe/multiple-group-candidates-first-found-group-perms-if-no-listed-candidate-matches.cf new/cfengine-3.9.1/tests/acceptance/10_files/unsafe/multiple-group-candidates-first-found-group-perms-if-no-listed-candidate-matches.cf --- old/cfengine-3.9.0/tests/acceptance/10_files/unsafe/multiple-group-candidates-first-found-group-perms-if-no-listed-candidate-matches.cf 1970-01-01 01:00:00.000000000 +0100 +++ new/cfengine-3.9.1/tests/acceptance/10_files/unsafe/multiple-group-candidates-first-found-group-perms-if-no-listed-candidate-matches.cf 2016-07-28 23:25:33.000000000 +0200 @@ -0,0 +1,100 @@ +body common control +{ + inputs => { "../../default.cf.sub" }; + bundlesequence => { default("$(this.promise_filename)") }; + version => "1.0"; +} + +bundle agent _group_state(group, state) +{ + meta: + # no groupadd on windows + "test_skip_unsupported" string => "windows"; + + vars: + !aix:: + "groupadd" string => "/usr/sbin/groupadd"; + "groupdel" string => "/usr/sbin/groupdel"; + aix:: + "groupadd" string => "/usr/bin/mkgroup"; + "groupdel" string => "/usr/sbin/rmgroup"; + + classes: + "_have_group" expression => groupexists( $(group) ); + "_want_$(state)" expression => "any"; + + commands: + !_have_group._want_present:: + "$(groupadd)" + args => "$(group)"; + + _have_group._want_absent:: + "$(groupdel)" + args => "$(group)"; +} +bundle agent init +{ + vars: + # Group lengths up to 8 chars because of AIX and HP-UX limitations + "absent_groups" slist => { "abs_gr_1", "abs_gr_2" }; + "present_groups" slist => { "pr_gr_1", "pr_gr_2" }; + + "groups" slist => { + @(absent_groups), + @(present_groups), + }; + + methods: + "Ensure Groups Absent" + usebundle => _group_state( $(absent_groups), "absent" ); + + "Ensure Groups Present" + usebundle => _group_state( $(present_groups), "present" ); + + files: + "$(G.testfile)" + create => "true", + perms => g("root"); +} + +bundle agent test +{ + meta: + "description" + string => "When a list of perms owners is provided if the perms do not match + at least one of the owners then the perms are set to the first + present owner."; + + files: + "$(G.testfile)" + perms => g( @(init.groups) ); +} + +bundle agent check +{ + vars: + "observed_gid" string => filestat($(G.testfile), gid); + "desired_gid" int => getgid("pr_gr_1"); + + reports: + "$(this.promise_filename) Pass" + if => strcmp( $(observed_gid), $(desired_gid) ); + + "$(this.promise_filename) FAIL" + ifvarclass => not( strcmp( $(observed_gid), $(desired_gid) ) ); + +} +bundle agent cleanup +{ + methods: + + "Ensure Groups Absent" + usebundle => _group_state( $(init.groups), "absent" ); +} +body perms g(g) +# @brief Set the file's group to the first presnet group +# @param g A list of candidate groups for the file +{ + groups => { "$(g)" }; +} + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cfengine-3.9.0/tests/acceptance/10_files/unsafe/multiple-owner-candidates-first-found-user-perms-if-no-listed-candidate-matches.cf new/cfengine-3.9.1/tests/acceptance/10_files/unsafe/multiple-owner-candidates-first-found-user-perms-if-no-listed-candidate-matches.cf --- old/cfengine-3.9.0/tests/acceptance/10_files/unsafe/multiple-owner-candidates-first-found-user-perms-if-no-listed-candidate-matches.cf 1970-01-01 01:00:00.000000000 +0100 +++ new/cfengine-3.9.1/tests/acceptance/10_files/unsafe/multiple-owner-candidates-first-found-user-perms-if-no-listed-candidate-matches.cf 2016-07-28 23:25:33.000000000 +0200 @@ -0,0 +1,72 @@ +body common control +{ + inputs => { "../../default.cf.sub" }; + bundlesequence => { default("$(this.promise_filename)") }; + version => "1.0"; +} + +bundle agent init +{ + vars: + # Username lengths up to 8 chars because of AIX and HP-UX limitations + "absent_users" slist => { "abs_us_1", "abs_us_2" }; + "present_users" slist => { "pr_us_1", "pr_us_2" }; + + "users" slist => { + @(absent_users), + @(present_users), + }; + + users: + "$(absent_users)" + policy => "absent"; + + "$(present_users)" + policy => "present"; + + files: + "$(G.testfile)" + create => "true", + perms => o("root"); +} + +bundle agent test +{ + meta: + "description" + string => "When a list of perms owners is provided if the perms do not match + at least one of the owners then the perms are set to the first + present owner."; + + files: + "$(G.testfile)" + perms => o( @(init.users) ); +} + +bundle agent check +{ + vars: + "observed_uid" string => filestat($(G.testfile), uid); + "desired_uid" int => getuid("pr_us_1"); + + reports: + "$(this.promise_filename) Pass" + if => strcmp( $(observed_uid), $(desired_uid) ); + + "$(this.promise_filename) FAIL" + ifvarclass => not( strcmp( $(observed_uid), $(desired_uid) ) ); + +} +bundle agent cleanup +{ + users: + "$(init.users)" + policy => "absent"; +} +body perms o(u) +# @brief Set the file's owner +# @param u The username of the new owner +{ + owners => { "$(u)" }; +} + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cfengine-3.9.0/tests/acceptance/25_cf-execd/Makefile new/cfengine-3.9.1/tests/acceptance/25_cf-execd/Makefile --- old/cfengine-3.9.0/tests/acceptance/25_cf-execd/Makefile 2016-06-06 12:02:39.000000000 +0200 +++ new/cfengine-3.9.1/tests/acceptance/25_cf-execd/Makefile 2016-07-28 23:28:50.000000000 +0200 @@ -269,7 +269,7 @@ TOKYOCABINET_LDFLAGS = TOKYOCABINET_LIBS = -ltokyocabinet TOKYOCABINET_PATH = /usr -VERSION = 3.9.0 +VERSION = 3.9.1 YACC = bison -y YFLAGS = abs_builddir = /home/jenkins/workspace/bootstrap-packages-3.9.x/core/tests/acceptance/25_cf-execd diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cfengine-3.9.0/tests/unit/rlist_test.c new/cfengine-3.9.1/tests/unit/rlist_test.c --- old/cfengine-3.9.0/tests/unit/rlist_test.c 2016-06-06 12:01:06.000000000 +0200 +++ new/cfengine-3.9.1/tests/unit/rlist_test.c 2016-07-28 23:25:33.000000000 +0200 @@ -720,12 +720,12 @@ } pthread_mutex_t *cft_lock; -int ThreadLock(pthread_mutex_t *name) +int __ThreadLock(pthread_mutex_t *name) { return true; } -int ThreadUnlock(pthread_mutex_t *name) +int __ThreadUnlock(pthread_mutex_t *name) { return true; }