Project

General

Profile

« Previous | Next » 

Revision 68ebf279

Added by Alexis Mousset over 7 years ago

Fixes #9737: Upgrade CFEngine in Rudder agent to 3.10

View differences:

rudder-agent/SOURCES/Makefile
RUDDER_VERSION_TO_PACKAGE = <put Rudder version or version-snapshot here>
RUDDER_MAJOR_VERSION := $(shell echo ${RUDDER_VERSION_TO_PACKAGE} | cut -d'.' -f 1-2)
CFENGINE_RELEASE = 3.7.4
CFENGINE_RELEASE = 3.10.0b1
FUSION_RELEASE = 2.3.17
LMDB_RELEASE = 0.9.18
OPENSSL_RELEASE = 1.0.2h
rudder-agent/SOURCES/patches/cfengine/01-disable-runlog-file.patch
--- cfengine-3.6.3rc/libpromises/locks.c 2014-11-27 16:02:46.000000000 +0100
+++ cfengine-3.6.3rc/libpromises/locks.c 2014-11-28 14:47:22.222683493 +0100
@@ -395,6 +395,10 @@
static void LogLockCompletion(char *cflog, int pid, char *str, char *op, char *operand)
{
+ // We don't need this function as it opens, writes and closes a file we never read or rotate
+ // Keep the function as it may be called again in the future but make it a dummy function
+ return;
+/*
FILE *fp;
char buffer[CF_MAXVARSIZE];
time_t tim;
@@ -425,6 +429,7 @@
fprintf(fp, "%s:%s:pid=%d:%s:%s\n", buffer, str, pid, op, operand);
fclose(fp);
+*/
}
static void LocksCleanup(void)
rudder-agent/SOURCES/patches/cfengine/10-default-body.patch
From 2c0c092fafd7d8031e3f5a18021beadd3084c11b Mon Sep 17 00:00:00 2001
From: Alexis Mousset <alexis.mousset@normation.com>
Date: Tue, 12 Jan 2016 11:56:28 +0100
Subject: [PATCH] Add default body for all promise types
Changelog: When a bodydefault:<promise_type>_<body_type> body is
defined, it will be used by all promises of type <promise_type>
unless another body is explicitly used.
---
libpromises/eval_context.h | 4 ++
libpromises/promises.c | 41 ++++++++++++
.../00_basics/03_bodies/default_files_action.cf | 76 ++++++++++++++++++++++
3 files changed, 121 insertions(+)
create mode 100644 tests/acceptance/00_basics/03_bodies/default_files_action.cf
diff --git a/libpromises/eval_context.h b/libpromises/eval_context.h
index 558a7ee..db54590 100644
--- a/libpromises/eval_context.h
+++ b/libpromises/eval_context.h
@@ -179,6 +179,9 @@ const Bundle *EvalContextResolveBundleEx
const Body *EvalContextResolveBodyExpression(const EvalContext *ctx, const Policy *policy,
const char *callee_reference, const char *callee_type);
+const Body *EvalContextFindFirstMatchingBody(const Policy *policy, const char *type,
+ const char *namespace, const char *name);
+
/* - Parsing/evaluating expressions - */
void ValidateClassSyntax(const char *str);
bool IsDefinedClass(const EvalContext *ctx, const char *context);
diff --git a/libpromises/promises.c b/libpromises/promises.c
index 2e59769..a346bb3 100644
--- a/libpromises/promises.c
+++ b/libpromises/promises.c
@@ -37,6 +37,7 @@
#include <string_lib.h>
static void DereferenceComment(Promise *pp);
+static void AddDefaultBodiesToPromise(EvalContext *ctx, Promise *promise, const PromiseTypeSyntax *syntax);
void CopyBodyConstraintsToPromise(EvalContext *ctx, Promise *pp,
const Body *bp)
@@ -262,10 +263,50 @@ Promise *DeRefCopyPromise(EvalContext *c
}
}
}
+
+ // Add default body for promise body types that are not present
+ char *bundle_type = pcopy->parent_promise_type->parent_bundle->type;
+ char *promise_type = pcopy->parent_promise_type->name;
+ const PromiseTypeSyntax *syntax = PromiseTypeSyntaxGet(bundle_type, promise_type);
+ AddDefaultBodiesToPromise(ctx, pcopy, syntax);
+
+ // Add default body for global body types that are not present
+ const PromiseTypeSyntax *global_syntax = PromiseTypeSyntaxGet("*", "*");
+ AddDefaultBodiesToPromise(ctx, pcopy, global_syntax);
return pcopy;
}
+// Try to add default bodies to promise for every body type found in syntax
+static void AddDefaultBodiesToPromise(EvalContext *ctx, Promise *promise, const PromiseTypeSyntax *syntax)
+{
+ // do nothing if syntax is not defined
+ if (syntax == NULL) {
+ return;
+ }
+
+ // iterate over possible constraints
+ for (int i = 0; syntax->constraints[i].lval; i++)
+ {
+ // of type body
+ if(syntax->constraints[i].dtype == CF_DATA_TYPE_BODY) {
+ const char *constraint_type = syntax->constraints[i].lval;
+ // if there is no matching body in this promise
+ if(!PromiseBundleOrBodyConstraintExists(ctx, constraint_type, promise)) {
+ const Policy *policy = PolicyFromPromise(promise);
+ // default format is <promise_type>_<body_type>
+ char* default_body_name = StringConcatenate(3, promise->parent_promise_type->name, "_", constraint_type);
+ const Body *bp = EvalContextFindFirstMatchingBody(policy, constraint_type, "bodydefault", default_body_name);
+ if(bp) {
+ Log(LOG_LEVEL_VERBOSE, "Using the default body: %60s", default_body_name);
+ CopyBodyConstraintsToPromise(ctx, promise, bp);
+ }
+ free(default_body_name);
+ }
+ }
+ }
+}
+
/*****************************************************************************/
static bool EvaluateConstraintIteration(EvalContext *ctx, const Constraint *cp, Rval *rval_out)
diff --git a/tests/acceptance/00_basics/03_bodies/default_files_action.cf b/tests/acceptance/00_basics/03_bodies/default_files_action.cf
new file mode 100644
index 0000000..27865b5
--- /dev/null
+++ b/tests/acceptance/00_basics/03_bodies/default_files_action.cf
@@ -0,0 +1,76 @@
+#######################################################
+#
+# Test default body action and overriding with specific action
+#
+#######################################################
+
+body common control
+{
+ inputs => { "../../default.cf.sub" };
+ bundlesequence => { default("$(this.promise_filename)") };
+ version => "1.0";
+}
+
+#######################################################
+
+body file control
+{
+ namespace => "bodydefault";
+}
+
+body action files_action
+{
+ action_policy => "warn";
+}
+
+body file control
+{
+ namespace => "default";
+}
+
+body action specific
+{
+ action_policy => "fix";
+}
+
+#######################################################
+
+bundle agent test_specified_action
+{
+ files:
+ "$(G.testdir)/specified"
+ create => "true",
+ action => specific;
+}
+
+bundle agent test_default_action
+{
+ files:
+ "$(G.testdir)/default"
+ create => "true";
+}
+
+#######################################################
+
+bundle agent test
+{
+ methods:
+ "specified"
+ usebundle => test_specified_action;
+ "default"
+ usebundle => test_default_action;
+}
+
+bundle agent check
+{
+ classes:
+ "default_created" expression => fileexists("$(G.testdir)/default");
+ "specified_created" expression => fileexists("$(G.testdir)/specified");
+ "ok" expression => "specified_created.!default_created";
+
+ reports:
+ ok::
+ "$(this.promise_filename) Pass";
+ !ok::
+ "$(this.promise_filename) FAIL";
+}
rudder-agent/SOURCES/patches/cfengine/11-utility-function-for-default-bodies.patch
From 5a43e6005ae8dcb8163b25664ce0c171871b8da6 Mon Sep 17 00:00:00 2001
From: Ted Zlatanov <tzz@lifelogs.com>
Date: Wed, 1 Jul 2015 23:06:52 -0400
Subject: [PATCH] Redmine#4309: implement inherit_from
Note: This patch covers only the part of 5a43e60 that is needed for the default
body feature. We do not backport body inheritance.
diff -upr cfengine-source/libpromises/eval_context.c cfengine-source-c/libpromises/eval_context.c
--- cfengine-source/libpromises/eval_context.c 2016-06-02 18:20:41.045957637 +0200
+++ cfengine-source-c/libpromises/eval_context.c 2016-06-02 18:54:16.365875477 +0200
@@ -2043,6 +2043,24 @@ const Bundle *EvalContextResolveBundleEx
return bp;
}
+const Body *EvalContextFindFirstMatchingBody(const Policy *policy, const char *type,
+ const char *namespace, const char *name)
+{
+ for (size_t i = 0; i < SeqLength(policy->bodies); i++)
+ {
+ const Body *curr_bp = SeqAt(policy->bodies, i);
+ if ((strcmp(curr_bp->type, type) == 0) &&
+ (strcmp(curr_bp->name, name) == 0) &&
+ StringSafeEqual(curr_bp->ns, namespace))
+ {
+ return curr_bp;
+ }
+ }
+
+ return NULL;
+}
+
+
const Body *EvalContextResolveBodyExpression(const EvalContext *ctx, const Policy *policy,
const char *callee_reference, const char *callee_type)
{
rudder-agent/SOURCES/patches/cfengine/20-add-callstack-call.patch
From 0dcf72efba55fb6ed4aa8e7aa7b0b82b8a878293 Mon Sep 17 00:00:00 2001
From: Kristian Amlie <kristian.amlie@cfengine.com>
Date: Tue, 19 Apr 2016 09:25:59 +0200
Subject: [PATCH] Add callstack_callers() and callstack_promisers() functions.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The former returns a huge data structure full of information about the
callstack. The latter returns a simplified slist, only containing the
names of the bundles leading up to the calling bundle.
The commit consists of contributions from several authors:
- Alexis Mousset <alexis.mousset@normation.com>
- BenoƮt Peccatte <benoit.peccatte@normation.com>
- Ted Zlatanov <tzz@lifelogs.com>
Changelog: Title
---
libpromises/cf3.defs.h | 3 +-
libpromises/eval_context.c | 81 ++++++++++++++++++++++
libpromises/eval_context.h | 5 ++
libpromises/evalfunction.c | 35 +++++++++-
libpromises/policy.c | 4 +-
libpromises/policy.h | 14 ++++
libpromises/syntax.c | 3 +-
.../21_methods/callers/callers_directly.cf | 59 ++++++++++++++++
.../21_methods/callers/promisers_directly.cf | 53 ++++++++++++++
.../21_methods/callers/promisers_indirectly.cf | 71 +++++++++++++++++++
10 files changed, 322 insertions(+), 6 deletions(-)
create mode 100644 tests/acceptance/21_methods/callers/callers_directly.cf
create mode 100644 tests/acceptance/21_methods/callers/promisers_directly.cf
create mode 100644 tests/acceptance/21_methods/callers/promisers_indirectly.cf
diff --git a/libpromises/cf3.defs.h b/libpromises/cf3.defs.h
index 7f17c4a..8c9e382 100644
--- a/libpromises/cf3.defs.h
+++ b/libpromises/cf3.defs.h
@@ -625,7 +625,8 @@ typedef enum
FNCALL_CATEGORY_IO,
FNCALL_CATEGORY_COMM,
FNCALL_CATEGORY_DATA,
- FNCALL_CATEGORY_UTILS
+ FNCALL_CATEGORY_UTILS,
+ FNCALL_CATEGORY_INTERNAL
} FnCallCategory;
struct ConstraintSyntax_
diff --git a/libpromises/eval_context.c b/libpromises/eval_context.c
index 55d6786..3081ff3 100644
--- a/libpromises/eval_context.c
+++ b/libpromises/eval_context.c
@@ -74,6 +74,8 @@ TYPED_MAP_DEFINE(FuncCache, Rlist *, Rva
RvalDestroy2)
+#include <policy.h>
+
static bool BundleAborted(const EvalContext *ctx);
static void SetBundleAborted(EvalContext *ctx);
@@ -1000,6 +1002,85 @@ void EvalContextClear(EvalContext *ctx)
FuncCacheMapClear(ctx->function_cache);
}
+Rlist *EvalContextGetPromiseCallerMethods(EvalContext *ctx) {
+ Rlist *callers_promisers = NULL;
+
+ for (size_t i = 0; i < SeqLength(ctx->stack); i++)
+ {
+ StackFrame *frame = SeqAt(ctx->stack, i);
+ switch (frame->type)
+ {
+ case STACK_FRAME_TYPE_BODY:
+ break;
+
+ case STACK_FRAME_TYPE_BUNDLE:
+ break;
+
+ case STACK_FRAME_TYPE_PROMISE_ITERATION:
+ break;
+
+ case STACK_FRAME_TYPE_PROMISE:
+ if (strcmp(frame->data.promise.owner->parent_promise_type->name, "methods") == 0) {
+ RlistAppendScalar(&callers_promisers, frame->data.promise.owner->promiser);
+ }
+ break;
+
+ case STACK_FRAME_TYPE_PROMISE_TYPE:
+ break;
+ }
+ }
+ return callers_promisers;
+}
+
+JsonElement *EvalContextGetPromiseCallers(EvalContext *ctx) {
+ JsonElement *callers = JsonArrayCreate(4);
+ size_t depth = SeqLength(ctx->stack);
+
+ for (size_t i = 0; i < depth; i++)
+ {
+ StackFrame *frame = SeqAt(ctx->stack, i);
+ JsonElement *f = JsonObjectCreate(10);
+ JsonObjectAppendInteger(f, "frame", depth-i);
+ JsonObjectAppendInteger(f, "depth", i);
+
+ switch (frame->type)
+ {
+ case STACK_FRAME_TYPE_BODY:
+ JsonObjectAppendString(f, "type", "body");
+ JsonObjectAppendObject(f, "body", BodyToJson(frame->data.body.owner));
+ break;
+
+ case STACK_FRAME_TYPE_BUNDLE:
+ JsonObjectAppendString(f, "type", "bundle");
+ JsonObjectAppendObject(f, "bundle", BundleToJson(frame->data.bundle.owner));
+ break;
+
+ case STACK_FRAME_TYPE_PROMISE_ITERATION:
+ JsonObjectAppendString(f, "type", "iteration");
+ JsonObjectAppendInteger(f, "iteration_index", frame->data.promise_iteration.index);
+
+ break;
+
+ case STACK_FRAME_TYPE_PROMISE:
+ JsonObjectAppendString(f, "type", "promise");
+ JsonObjectAppendString(f, "promise_type", frame->data.promise.owner->parent_promise_type->name);
+ JsonObjectAppendString(f, "promiser", frame->data.promise.owner->promiser);
+ JsonObjectAppendString(f, "promise_classes", frame->data.promise.owner->classes);
+ JsonObjectAppendString(f, "promise_comment", NULL == frame->data.promise.owner->comment ? "" : frame->data.promise.owner->comment);
+ break;
+
+ case STACK_FRAME_TYPE_PROMISE_TYPE:
+ JsonObjectAppendString(f, "type", "promise_type");
+ JsonObjectAppendString(f, "promise_type", frame->data.promise_type.owner->name);
+ break;
+ }
+
+ JsonArrayAppendObject(callers, f);
+ }
+
+ return callers;
+}
+
void EvalContextSetBundleArgs(EvalContext *ctx, const Rlist *args)
{
if (ctx->args)
diff --git a/libpromises/eval_context.h b/libpromises/eval_context.h
index d4e5941..15c0ed6 100644
--- a/libpromises/eval_context.h
+++ b/libpromises/eval_context.h
@@ -131,6 +131,8 @@ ClassTableIterator *EvalContextClassTableIteratorNewLocal(const EvalContext *ctx
void EvalContextClear(EvalContext *ctx);
+Rlist *EvalContextGetPromiseCallerMethods(EvalContext *ctx);
+
void EvalContextStackPushBundleFrame(EvalContext *ctx, const Bundle *owner, const Rlist *args, bool inherits_previous);
void EvalContextStackPushBodyFrame(EvalContext *ctx, const Promise *caller, const Body *body, const Rlist *args);
void EvalContextStackPushPromiseTypeFrame(EvalContext *ctx, const PromiseType *owner);
@@ -149,6 +151,9 @@ const Promise *EvalContextStackCurrentPromise(const EvalContext *ctx);
const Bundle *EvalContextStackCurrentBundle(const EvalContext *ctx);
const RingBuffer *EvalContextStackCurrentMessages(const EvalContext *ctx);
+Rlist *EvalContextGetPromiseCallerMethods(EvalContext *ctx);
+JsonElement *EvalContextGetPromiseCallers(EvalContext *ctx);
+
bool EvalContextVariablePut(EvalContext *ctx, const VarRef *ref, const void *value, DataType type, const char *tags);
bool EvalContextVariablePutSpecial(EvalContext *ctx, SpecialScope scope, const char *lval, const void *value, DataType type, const char *tags);
const void *EvalContextVariableGet(const EvalContext *ctx, const VarRef *ref, DataType *type_out);
diff --git a/libpromises/evalfunction.c b/libpromises/evalfunction.c
index 348f348..9ede974 100644
--- a/libpromises/evalfunction.c
+++ b/libpromises/evalfunction.c
@@ -24,7 +24,6 @@
#include <evalfunction.h>
-#include <eval_context.h>
#include <promises.h>
#include <dir.h>
#include <dbm_api.h>
@@ -7184,6 +7183,22 @@ void ModuleProtocol(EvalContext *ctx, ch
}
/*********************************************************************/
+
+static FnCallResult FnCallCFEngineCallers(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, ARG_UNUSED const Rlist *finalargs)
+{
+ bool promisersmode = (0 == strcmp(fp->name, "callstack_promisers"));
+
+ if (promisersmode)
+ {
+ Rlist *returnlist = EvalContextGetPromiseCallerMethods(ctx);
+ return (FnCallResult) { FNCALL_SUCCESS, { returnlist, RVAL_TYPE_LIST } };
+ }
+
+ JsonElement *callers = EvalContextGetPromiseCallers(ctx);
+ return (FnCallResult) { FNCALL_SUCCESS, { callers, RVAL_TYPE_CONTAINER } };
+}
+
+/*********************************************************************/
/* Level */
/*********************************************************************/
@@ -8062,6 +8077,16 @@ static const FnCallArg STRING_MUSTACHE_A
{NULL, CF_DATA_TYPE_NONE, NULL}
};
+static const FnCallArg CFENGINE_PROMISERS_ARGS[] =
+{
+ {NULL, CF_DATA_TYPE_NONE, NULL}
+};
+
+static const FnCallArg CFENGINE_CALLERS_ARGS[] =
+{
+ {NULL, CF_DATA_TYPE_NONE, NULL}
+};
+
/*********************************************************/
/* FnCalls are rvalues in certain promise constraints */
/*********************************************************/
@@ -8375,7 +8400,13 @@ const FnCallType CF_FNCALL_TYPES[] =
FnCallTypeNew("variance", CF_DATA_TYPE_REAL, STAT_FOLD_ARGS, &FnCallFold, "Return the variance of a list",
FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL),
- // Data container functions
+ // CFEngine internal functions
+ FnCallTypeNew("callstack_promisers", CF_DATA_TYPE_STRING_LIST, CFENGINE_PROMISERS_ARGS, &FnCallCFEngineCallers, "Get the list of promisers to the current promise execution path",
+ FNCALL_OPTION_NONE, FNCALL_CATEGORY_INTERNAL, SYNTAX_STATUS_NORMAL),
+ FnCallTypeNew("callstack_callers", CF_DATA_TYPE_CONTAINER, CFENGINE_CALLERS_ARGS, &FnCallCFEngineCallers, "Get the current promise execution stack in detail",
+ FNCALL_OPTION_NONE, FNCALL_CATEGORY_INTERNAL, SYNTAX_STATUS_NORMAL),
+
+ // Data container functions
FnCallTypeNew("data_regextract", CF_DATA_TYPE_CONTAINER, DATA_REGEXTRACT_ARGS, &FnCallRegExtract, "Matches the regular expression in arg 1 against the string in arg2 and returns a data container holding the backreferences by name",
FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL),
FnCallTypeNew("data_expand", CF_DATA_TYPE_CONTAINER, DATA_EXPAND_ARGS, &FnCallDataExpand, "Expands any CFEngine variables in a data container, keys or values",
diff --git a/libpromises/policy.c b/libpromises/policy.c
index 2a656ce..7fe6952 100644
--- a/libpromises/policy.c
+++ b/libpromises/policy.c
@@ -1761,7 +1761,7 @@ static JsonElement *BundleContextsToJson(const Seq *promises)
return json_contexts;
}
-static JsonElement *BundleToJson(const Bundle *bundle)
+JsonElement *BundleToJson(const Bundle *bundle)
{
JsonElement *json_bundle = JsonObjectCreate(10);
@@ -1810,7 +1810,7 @@ static JsonElement *BundleToJson(const Bundle *bundle)
}
-static JsonElement *BodyToJson(const Body *body)
+JsonElement *BodyToJson(const Body *body)
{
JsonElement *json_body = JsonObjectCreate(10);
diff --git a/libpromises/policy.h b/libpromises/policy.h
index e0331a9..2b0b0c0 100644
--- a/libpromises/policy.h
+++ b/libpromises/policy.h
@@ -221,6 +221,20 @@ Body *PolicyAppendBody(Policy *policy, const char *ns, const char *name, const c
JsonElement *PolicyToJson(const Policy *policy);
/**
+ * @brief Serialize a bundle as JSON
+ * @param bundle The bundle to serialize
+ * @return A JsonElement representing the input bundle
+ */
+JsonElement *BundleToJson(const Bundle *bundle);
+
+/**
+ * @brief Serialize a body as JSON
+ * @param body The body to serialize
+ * @return A JsonElement representing the input body
+ */
+JsonElement *BodyToJson(const Body *body);
+
+/**
* @brief Deserialize a policy from JSON
* @param json_policy JSON to deserialize
* @return A policy DOM
diff --git a/libpromises/syntax.c b/libpromises/syntax.c
index e2f7e06..7f6fe5d 100644
--- a/libpromises/syntax.c
+++ b/libpromises/syntax.c
@@ -1195,7 +1195,8 @@ static const char *FnCallCategoryToString(FnCallCategory category)
[FNCALL_CATEGORY_FILES] = "files",
[FNCALL_CATEGORY_IO] = "io",
[FNCALL_CATEGORY_SYSTEM] = "system",
- [FNCALL_CATEGORY_UTILS] = "utils"
+ [FNCALL_CATEGORY_UTILS] = "utils",
+ [FNCALL_CATEGORY_INTERNAL] = "internal"
};
return category_str[category];
diff --git a/tests/acceptance/21_methods/callers/callers_directly.cf b/tests/acceptance/21_methods/callers/callers_directly.cf
new file mode 100644
index 0000000..0ddd755
--- /dev/null
+++ b/tests/acceptance/21_methods/callers/callers_directly.cf
@@ -0,0 +1,59 @@
+#######################################################
+#
+# Test the variable this.callers_promisers with one bundle
+#
+#######################################################
+
+body common control
+{
+ inputs => { "../../default.cf.sub" };
+ bundlesequence => { default("$(this.promise_filename)") };
+ version => "1.0";
+}
+
+#######################################################
+
+bundle agent init {
+}
+
+bundle agent test {
+ methods:
+ "test" usebundle => "caller";
+}
+
+bundle agent check {
+ vars:
+ "callers_expect" string => "agent";
+ # Due to the 4K variable limit we cannot test the whole structure, so
+ # just test one element within it. At least it's not completely broken
+ # if we find it.
+ "callers_actual" string => "$(dummy.callers[0][bundle][bundleType])";
+
+ classes:
+ "success" expression => strcmp("${callers_expect}", "${callers_actual}"),
+ scope => "namespace";
+
+ reports:
+ success::
+ "$(this.promise_filename) Pass";
+ !success::
+ "$(this.promise_filename) FAIL";
+
+ methods:
+ "any" usebundle => file_make($(G.testfile), $(callers_actual));
+
+ reports:
+ DEBUG::
+ "EXPECT: callers_string = ${callers_expect}";
+ "ACTUAL: callers_string = $(callers_actual)";
+}
+
+bundle agent caller {
+ methods:
+ "first call" usebundle => dummy;
+}
+
+bundle agent dummy {
+ vars:
+ "callers" data => callstack_callers();
+}
diff --git a/tests/acceptance/21_methods/callers/promisers_directly.cf b/tests/acceptance/21_methods/callers/promisers_directly.cf
new file mode 100644
index 0000000..14edfd4
--- /dev/null
+++ b/tests/acceptance/21_methods/callers/promisers_directly.cf
@@ -0,0 +1,53 @@
+#######################################################
+#
+# Test the variable this.callers_promisers with one bundle
+#
+#######################################################
+
+body common control
+{
+ inputs => { "../../default.cf.sub" };
+ bundlesequence => { default("$(this.promise_filename)") };
+ version => "1.0";
+}
+
+#######################################################
+
+bundle agent init {
+}
+
+bundle agent test {
+ methods:
+ "test" usebundle => "caller";
+}
+
+bundle agent check {
+ reports:
+ success::
+ "$(this.promise_filename) Pass";
+ !success::
+ "$(this.promise_filename) FAIL";
+}
+
+bundle agent caller {
+ methods:
+ "first call" usebundle => dummy;
+}
+
+bundle agent dummy {
+ vars:
+ "callers_promisers" slist => callstack_promisers();
+
+ "callers_promisers_expect" string => "any, any, test, first call";
+ "callers_promisers_actual" string => join(", ", "callers_promisers");
+
+ classes:
+ "success" expression => strcmp("${callers_promisers_expect}", "${callers_promisers_actual}"),
+ scope => "namespace";
+
+ reports:
+ DEBUG::
+ "EXPECT: callers_promisers_string = ${callers_promisers_expect}";
+ "ACTUAL: callers_promisers_string = ${callers_promisers_actual}";
+}
+
diff --git a/tests/acceptance/21_methods/callers/promisers_indirectly.cf b/tests/acceptance/21_methods/callers/promisers_indirectly.cf
new file mode 100644
index 0000000..4e14576
--- /dev/null
+++ b/tests/acceptance/21_methods/callers/promisers_indirectly.cf
@@ -0,0 +1,71 @@
+#######################################################
+#
+# Test the variable this.callers_promisers with one bundle called twice
+#
+#######################################################
+
+body common control
+{
+ inputs => { "../../default.cf.sub" };
+ bundlesequence => { default("$(this.promise_filename)") };
+ version => "1.0";
+}
+
+#######################################################
+
+bundle agent init {
+}
+
+bundle agent test {
+ methods:
+ "test" usebundle => "caller";
+}
+
+bundle agent check {
+ reports:
+ success_first.success_second::
+ "$(this.promise_filename) Pass";
+ !(success_first.success_second)::
+ "$(this.promise_filename) FAIL";
+}
+
+bundle agent caller {
+
+ methods:
+ "first call" usebundle => dummy;
+ "second call" usebundle => dummy_inter;
+
+}
+
+bundle agent dummy_inter {
+
+ methods:
+ "inter" usebundle => dummy;
+
+}
+
+bundle agent dummy {
+
+ vars:
+ # This bundle gets called twice, once directly, and once via dummy_inter
+ "callers_promisers" slist => callstack_promisers();
+
+ "callers_promisers_expect_first" string => "any, any, test, first call";
+ "callers_promisers_expect_second" string => "any, any, test, second call, inter";
+ "callers_promisers_actual" string => join(", ", "callers_promisers");
+
+ classes:
+ "success_first" expression => strcmp("${callers_promisers_expect_first}", "${callers_promisers_actual}"),
+ scope => "namespace";
+ "success_second" expression => strcmp("${callers_promisers_expect_second}", "${callers_promisers_actual}"),
+ scope => "namespace";
+
+ reports:
+ DEBUG::
+ "EXPECT (first in ${this.bundle}): callers_promisers_string = ${callers_promisers_expect_first}";
+ "ACTUAL (first in ${this.bundle}): callers_promisers_string = ${callers_promisers_actual}";
+
+ "EXPECT (second in ${this.bundle}): callers_promisers_string = ${callers_promisers_expect_second}";
+ "ACTUAL (second in ${this.bundle}): callers_promisers_string = ${callers_promisers_actual}";
+}
+
rudder-agent/SOURCES/patches/cfengine/31-fix-symlink-traversal.patch
diff --git a/libutils/file_lib.c b/libutils/file_lib.c
index 0b1394d..616fea9 100644
--- a/libutils/file_lib.c
+++ b/libutils/file_lib.c
@@ -380,6 +380,7 @@ int safe_open(const char *pathname, int flags, ...)
char *next_component;
diff -upr cfengine-a/libutils/file_lib.c cfengine-b/libutils/file_lib.c
--- cfengine-a/libutils/file_lib.c 2016-11-01 08:47:08.000000000 +0100
+++ cfengine-b/libutils/file_lib.c 2016-11-25 18:21:44.163553332 +0100
@@ -387,6 +387,7 @@ int safe_open(const char *pathname, int
bool trunc = false;
int orig_flags = flags;
const int orig_flags = flags;
char *next_component = path;
+ bool p_uid;
if (flags & O_TRUNC)
if (*next_component == '/')
{
@@ -412,6 +413,9 @@ int safe_open(const char *pathname, int flags, ...)
@@ -408,6 +409,9 @@ int safe_open(const char *pathname, int
return -1;
}
+ // current process user id
+ p_uid = geteuid();
+
size_t final_size = (size_t) -1;
while (next_component)
{
char *component = next_component;
@@ -528,7 +532,9 @@ int safe_open(const char *pathname, int flags, ...)
@@ -558,8 +562,13 @@ int safe_open(const char *pathname, int
close(currentfd);
return -1;
}
- if (stat_before.st_uid != stat_after.st_uid || stat_before.st_gid != stat_after.st_gid)
- if (stat_before.st_uid != stat_after.st_uid ||
- stat_before.st_gid != stat_after.st_gid)
+ // The probable logic behind the user matching test is that some attacks use symlink creation to exploit a race condition
+ // This attack is not useful if the symlink has been created by root
+ // This attack is not useful if the process's user is the owner of the symlink
......
{
close(currentfd);
// Return ENOLINK to signal that the link cannot be followed
@@ -691,6 +697,7 @@ static int safe_open_true_parent_dir(const char *path,
@@ -736,6 +745,7 @@ static int safe_open_true_parent_dir(con
char *parent_dir = dirname(parent_dir_alloc);
char *leaf = basename(leaf_alloc);
struct stat statbuf;
......
if ((dirfd = safe_open(parent_dir, O_RDONLY)) == -1)
{
@@ -702,7 +709,10 @@ static int safe_open_true_parent_dir(const char *path,
@@ -747,7 +757,14 @@ static int safe_open_true_parent_dir(con
goto cleanup;
}
......
{
errno = ENOLINK;
ret = -1;
0
rudder-agent/SOURCES/patches/cfengine/35-allow-edit-fields-4k.patch
From d3fedf7d4d2903bcb889f212d417cde9c97f5bdf Mon Sep 17 00:00:00 2001
From: Alexis Mousset <contact@amousset.me>
Date: Fri, 29 Jul 2016 21:08:09 +0200
Subject: [PATCH] CFE-2438: Allow editing fields in lines longer than 4k
Replace the CF_BUFSIZE buffer by a Writer in Rlist2String to
allow writing long lines.
Changelog: Title
(cherry picked from commit 049e8187bb2390bceb6a1ae59b903011bed77091)
---
libpromises/conversion.c | 15 ++--
.../10_files/08_field_edits/set_value_line_long.cf | 80 ++++++++++++++++++++++
2 files changed, 86 insertions(+), 9 deletions(-)
create mode 100644 tests/acceptance/10_files/08_field_edits/set_value_line_long.cf
diff --git a/libpromises/conversion.c b/libpromises/conversion.c
index d90c240..33b3612 100644
--- a/libpromises/conversion.c
+++ b/libpromises/conversion.c
@@ -199,22 +199,19 @@ PackageActionPolicy PackageActionPolicyFromString(const char *s)
char *Rlist2String(Rlist *list, char *sep)
{
- char line[CF_BUFSIZE];
- Rlist *rp;
-
- line[0] = '\0';
+ Writer *writer = StringWriter();
- for (rp = list; rp != NULL; rp = rp->next)
+ for (const Rlist *rp = list; rp != NULL; rp = rp->next)
{
- strcat(line, RlistScalarValue(rp));
+ RvalWrite(writer, rp->val);
- if (rp->next)
+ if (rp->next != NULL)
{
- strcat(line, sep);
+ WriterWrite(writer, sep);
}
}
- return xstrdup(line);
+ return StringWriterClose(writer);
}
/***************************************************************************/
diff --git a/tests/acceptance/10_files/08_field_edits/set_value_line_long.cf b/tests/acceptance/10_files/08_field_edits/set_value_line_long.cf
new file mode 100644
index 0000000..088f063
--- /dev/null
+++ b/tests/acceptance/10_files/08_field_edits/set_value_line_long.cf
@@ -0,0 +1,80 @@
+#######################################################
+#
+# Test setting a field in a line longer than 4k
+#
+#######################################################
+
+body common control
+{
+ inputs => { "../../default.cf.sub" };
+ bundlesequence => { default("$(this.promise_filename)") };
+ version => "1.0";
+}
+
+bundle agent init
+{
+ vars:
+ "states" slist => { "actual", "expected" };
+
+ "actual" string =>
+ "a:a:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaend";
+
+ "expected" string =>
+ "a:b:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaend";
+
+ files:
+ "$(G.testfile).$(states)"
+ create => "true",
+ edit_line => init_insert("$(init.$(states))"),
+ edit_defaults => init_empty;
+}
+
+bundle edit_line init_insert(str)
+{
+ insert_lines:
+ "$(str)";
+}
+
+body edit_defaults init_empty
+{
+ empty_file_before_editing => "true";
+}
+
+#######################################################
+
+bundle agent test
+{
+ files:
+ "$(G.testfile).actual"
+ edit_line => test_edit;
+
+}
+
+bundle edit_line test_edit
+{
+ field_edits:
+ "a.*"
+ edit_field => test_col;
+}
+
+body edit_field test_col
+{
+ allow_blank_fields => "true";
+ extend_fields => "true";
+ field_operation => "set";
+ field_separator => ":";
+ field_value => "b";
+ select_field => "2";
+ start_fields_from_zero => "false";
+ value_separator => "+";
+}
+
+#######################################################
+
+bundle agent check
+{
+ methods:
+ "any" usebundle => dcs_check_diff("$(G.testfile).actual",
+ "$(G.testfile).expected",
+ "$(this.promise_filename)");
+}
rudder-agent/SOURCES/patches/cfengine/36-define-kept-edit-line-warn.patch
From bb6a85f25d74551697eb28cb0917045619a9aa99 Mon Sep 17 00:00:00 2001
From: Alexis Mousset <alexis.mousset@normation.com>
Date: Wed, 6 Jul 2016 17:58:02 +0200
Subject: [PATCH] CFE-2424: define kept outcome with action warn if edit_line
is as expected
Changelog: Title
(cherry picked from commit dbb44af5a0b8f8794d506683840675f43fe99dbf)
---
cf-agent/files_edit.c | 2 +
.../08_field_edits/set_classes_in_warn_only.cf | 121 +++++++++++++++++++++
2 files changed, 123 insertions(+)
create mode 100644 tests/acceptance/10_files/08_field_edits/set_classes_in_warn_only.cf
diff --git a/cf-agent/files_edit.c b/cf-agent/files_edit.c
index c9d8159..238e596 100644
--- a/cf-agent/files_edit.c
+++ b/cf-agent/files_edit.c
@@ -115,6 +115,8 @@ void FinishEditContext(EvalContext *ctx, EditContext *ec, Attributes a, const Pr
}
else
{
+ cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a,
+ "No edit changes to file '%s' need saving", ec->filename);
*result = PROMISE_RESULT_NOOP;
}
}
diff --git a/tests/acceptance/10_files/08_field_edits/set_classes_in_warn_only.cf b/tests/acceptance/10_files/08_field_edits/set_classes_in_warn_only.cf
new file mode 100644
index 0000000..f77f084
--- /dev/null
+++ b/tests/acceptance/10_files/08_field_edits/set_classes_in_warn_only.cf
@@ -0,0 +1,121 @@
+#######################################################
+#
+#Tries to edit a file in warn_only, and must have a kept class defined
+#
+#######################################################
+
+body common control
+{
+ inputs => { "../../default.cf.sub" };
+ bundlesequence => { default("$(this.promise_filename)") };
+ version => "1.0";
+}
+
+#######################################################
+
+bundle agent init
+{
+ vars:
+ "filename_kept" string => "shadow.kept";
+ "filename_failed" string => "shadow.failed";
+
+ "content" string =>
+ "nicolas:$1$NoSH4e.u$U4uEzaOuC0tmQThtI3hj00:16988:0:99999:7:::";
+
+ "name" string =>
+ "nicolas";
+
+ "field_kept" string =>
+ "$1$NoSH4e.u$U4uEzaOuC0tmQThtI3hj00";
+
+ "field_failed" string =>
+ "bad";
+
+ files:
+ "$(G.testfile).$(init.filename_kept)"
+ create => "true",
+ edit_line => init_insert("$(init.content)"),
+ edit_defaults => init_empty;
+
+ "$(G.testfile).$(init.filename_failed)"
+ create => "true",
+ edit_line => init_insert("$(init.content)"),
+ edit_defaults => init_empty;
+}
+
+bundle edit_line init_insert(str)
+{
+ insert_lines:
+ "$(str)";
+}
+
+body edit_defaults init_empty
+{
+ empty_file_before_editing => "true";
+}
+
+#######################################################
+
+bundle agent test
+{
+ files:
+ "$(G.testfile).$(init.filename_kept)"
+ create => "false",
+ edit_line => test_set_user_field("${init.name}", 2, "${init.field_kept}"),
+ action => test_warn_only,
+ classes => test_classes_generic("test_result_kept");
+
+ "$(G.testfile).$(init.filename_failed)"
+ create => "false",
+ edit_line => test_set_user_field("${init.name}", 2, "${init.field_failed}"),
+ action => test_warn_only,
+ classes => test_classes_generic("test_result_failed");
+}
+
+bundle edit_line test_set_user_field(user,field,val)
+{
+ field_edits:
+ "$(user):.*"
+ comment => "Edit a user attribute in the password file",
+ edit_field => test_col(":","$(field)","$(val)","set");
+}
+
+body edit_field test_col(split,col,newval,method)
+{
+ field_separator => "$(split)";
+ select_field => "$(col)";
+ value_separator => ",";
+ field_value => "$(newval)";
+ field_operation => "$(method)";
+ extend_fields => "true";
+ allow_blank_fields => "true";
+}
+
+body action test_warn_only
+{
+ action_policy => "warn";
+ ifelapsed => "60";
+}
+
+body classes test_classes_generic(x)
+{
+ promise_repaired => { "$(x)_repaired" };
+ repair_failed => { "$(x)_failed" };
+ repair_denied => { "$(x)_denied" };
+ repair_timeout => { "$(x)_timeout" };
+ promise_kept => { "$(x)_ok" };
+}
+
+
+#######################################################
+
+bundle agent check
+{
+ reports:
+ test_result_kept_ok.test_result_failed_failed::
+ "$(this.promise_filename) Pass";
+
+ !(test_result_kept_ok.test_result_failed_failed)::
+ "$(this.promise_filename) FAIL";
+}
+
rudder-agent/SOURCES/patches/cfengine/38-escape-json-string-in-dynamic-buffer.patch
From 3704a0ca683577ff98d4748c06c1806523dccd02 Mon Sep 17 00:00:00 2001
From: Alexis Mousset <alexis.mousset@normation.com>
Date: Tue, 19 Jul 2016 18:34:03 +0200
Subject: [PATCH] CFE-2383: Use a dynamic buffer to escape json strings
Changelog: Remove 2k limit on strings length when writing JSON policies
(cherry picked from commit dab2d270a6bed5beff797b67aa1404228d769634)
---
libpromises/policy.c | 23 +++++------
.../01_compiler/cf-promises-json-long-strings.cf | 29 +++++++++++++
.../cf-promises-json-long-strings.cf.sub | 47 ++++++++++++++++++++++
3 files changed, 85 insertions(+), 14 deletions(-)
create mode 100644 tests/acceptance/00_basics/01_compiler/cf-promises-json-long-strings.cf
create mode 100644 tests/acceptance/00_basics/01_compiler/cf-promises-json-long-strings.cf.sub
diff --git a/libpromises/policy.c b/libpromises/policy.c
index 2a656ce..bfc28c7 100644
--- a/libpromises/policy.c
+++ b/libpromises/policy.c
@@ -1525,30 +1525,23 @@ const PromiseType *BundleGetPromiseType(const Bundle *bp, const char *name)
/****************************************************************************/
-static char *EscapeQuotes(const char *s, char *out, int outSz)
+static Buffer *EscapeQuotes(const char *raw, Buffer *out)
{
- char *spt;
const char *spf;
- int i = 0;
-
- memset(out, 0, outSz);
- for (spf = s, spt = out; (i < outSz - 2) && (*spf != '\0'); spf++, spt++, i++)
+ for (spf = raw; *spf != '\0'; spf++)
{
switch (*spf)
{
case '\'':
case '\"':
- *spt++ = '\\';
- *spt = *spf;
- i += 3;
+ BufferAppendChar(out, '\\');
break;
default:
- *spt = *spf;
- i++;
break;
}
+ BufferAppendChar(out, *spf);
}
return out;
@@ -1565,9 +1558,9 @@ static JsonElement *AttributeValueToJson(Rval rval, bool symbolic_reference)
case RVAL_TYPE_SCALAR:
{
- char buffer[CF_BUFSIZE];
+ Buffer *buffer = BufferNewWithCapacity(strlen(rval.item));
- EscapeQuotes((const char *) rval.item, buffer, sizeof(buffer));
+ EscapeQuotes((const char *) rval.item, buffer);
JsonElement *json_attribute = JsonObjectCreate(10);
@@ -1579,7 +1572,9 @@ static JsonElement *AttributeValueToJson(Rval rval, bool symbolic_reference)
{
JsonObjectAppendString(json_attribute, "type", "string");
}
- JsonObjectAppendString(json_attribute, "value", buffer);
+ JsonObjectAppendString(json_attribute, "value", BufferData(buffer));
+
+ BufferDestroy(buffer);
return json_attribute;
}
diff --git a/tests/acceptance/00_basics/01_compiler/cf-promises-json-long-strings.cf b/tests/acceptance/00_basics/01_compiler/cf-promises-json-long-strings.cf
new file mode 100644
index 0000000..ae751ef
--- /dev/null
+++ b/tests/acceptance/00_basics/01_compiler/cf-promises-json-long-strings.cf
@@ -0,0 +1,29 @@
+# Test that cf-promises doesn't fail if ppkeys are missing
+
+body common control
+{
+ inputs => { "../../default.cf.sub" };
+ bundlesequence => { default("$(this.promise_filename)") };
+ version => "1.0";
+}
+
+bundle agent init
+{
+}
+
+bundle agent test
+{
+classes:
+ "validated_ok" expression => returnszero("$(sys.cf_promises) -p json -f $(this.promise_filename).sub | $(G.grep) endflag", "useshell"),
+ scope => "namespace";
+}
+
+bundle agent check
+{
+
+ reports:
+ validated_ok::
+ "$(this.promise_filename) Pass";
+ !validated_ok::
+ "$(this.promise_filename) FAIL";
+}
diff --git a/tests/acceptance/00_basics/01_compiler/cf-promises-json-long-strings.cf.sub b/tests/acceptance/00_basics/01_compiler/cf-promises-json-long-strings.cf.sub
new file mode 100644
index 0000000..3c2beb8
--- /dev/null
+++ b/tests/acceptance/00_basics/01_compiler/cf-promises-json-long-strings.cf.sub
@@ -0,0 +1,47 @@
+bundle agent main
+{
+vars:
+ "content" string =>
+ "flag
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+This is a file template containing variables to expan
+endflag";
+
+}
rudder-agent/SOURCES/patches/cfengine/70-fix-connection-cache.patch
From 7ba51548b2a5e8d90f75f95adf6978992cc90d07 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Eystein=20M=C3=A5l=C3=B8y=20Stenberg?=
<eystein.maloy.stenberg@cfengine.com>
Date: Wed, 6 Jul 2016 13:35:57 -0700
Subject: [PATCH] CFE-2447: Fix connection cache, reuse connections when
possible.
Changelog: Title
---
libcfnet/conn_cache.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcfnet/conn_cache.c b/libcfnet/conn_cache.c
index db20025..8da4502 100644
--- a/libcfnet/conn_cache.c
+++ b/libcfnet/conn_cache.c
@@ -106,7 +106,7 @@ AgentConnection *ConnCache_FindIdleMarkBusy(const char *server,
if (strcmp(server, svp->conn->this_server) == 0 &&
- ConnectionFlagsEqual(&flags, &svp->conn->flags) == 0 &&
+ ConnectionFlagsEqual(&flags, &svp->conn->flags) &&
(port == svp->conn->this_port
||
(port != NULL && svp->conn->this_port != NULL &&
rudder-agent/SOURCES/patches/cfengine/80-add-dumpdatatstate-function.patch
diff -upr cfengine-source/libpromises/evalfunction.c cfengine-source-3/libpromises/evalfunction.c
--- cfengine-source/libpromises/evalfunction.c 2015-09-06 12:39:13.000000000 +0200
+++ cfengine-source-3/libpromises/evalfunction.c 2016-09-22 17:13:02.125381566 +0200
@@ -2956,6 +2956,33 @@ static FnCallResult FnCallDatastate(Eval
diff -upr cfengine-a/libpromises/evalfunction.c cfengine-b/libpromises/evalfunction.c
--- cfengine-a/libpromises/evalfunction.c 2016-11-01 08:47:08.000000000 +0100
+++ cfengine-b/libpromises/evalfunction.c 2016-11-25 18:24:48.634260465 +0100
@@ -3422,6 +3422,33 @@ static FnCallResult FnCallDatastate(Eval
return (FnCallResult) { FNCALL_SUCCESS, (Rval) { state, RVAL_TYPE_CONTAINER } };
}
......
+ ARG_UNUSED const FnCall *fp,
+ const Rlist *args)
+{
+ char *path = RlistScalarValue(args);
+ char *path = RlistScalarValue(args);
+
+ FILE *fout;
+ if ((fout = fopen(path, "w")) == NULL)
......
static FnCallResult FnCallBundlestate(EvalContext *ctx,
ARG_UNUSED const Policy *policy,
ARG_UNUSED const FnCall *fp,
@@ -8109,6 +8136,8 @@ const FnCallType CF_FNCALL_TYPES[] =
FNCALL_OPTION_NONE, FNCALL_CATEGORY_IO, SYNTAX_STATUS_NORMAL),
FnCallTypeNew("datastate", CF_DATA_TYPE_CONTAINER, DATASTATE_ARGS, &FnCallDatastate, "Construct a container of the variable and class state",
FNCALL_OPTION_NONE, FNCALL_CATEGORY_UTILS, SYNTAX_STATUS_NORMAL),
@@ -8828,6 +8855,8 @@ const FnCallType CF_FNCALL_TYPES[] =
FNCALL_OPTION_NONE, FNCALL_CATEGORY_FILES, SYNTAX_STATUS_NORMAL),
FnCallTypeNew("diskfree", CF_DATA_TYPE_INT, DISKFREE_ARGS, &FnCallDiskFree, "Return the free space (in KB) available on the directory's current partition (0 if not found)",
FNCALL_OPTION_NONE, FNCALL_CATEGORY_FILES, SYNTAX_STATUS_NORMAL),
+ FnCallTypeNew("dumpdatastate", CF_DATA_TYPE_CONTEXT, FILESTAT_ARGS, &FnCallDumpDatastate, "Dump the current datastate() into the given file",
+ FNCALL_OPTION_NONE, FNCALL_CATEGORY_FILES, SYNTAX_STATUS_NORMAL),
FnCallTypeNew("difference", CF_DATA_TYPE_STRING_LIST, SETOP_ARGS, &FnCallSetop, "Returns all the unique elements of list arg1 that are not in list arg2",
+ FNCALL_OPTION_NONE, FNCALL_CATEGORY_FILES, SYNTAX_STATUS_NORMAL),
FnCallTypeNew("escape", CF_DATA_TYPE_STRING, ESCAPE_ARGS, &FnCallEscape, "Escape regular expression characters in a string",
FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL),
FnCallTypeNew("dirname", CF_DATA_TYPE_STRING, DIRNAME_ARGS, &FnCallDirname, "Return the parent directory name for given path",
FnCallTypeNew("eval", CF_DATA_TYPE_STRING, EVAL_ARGS, &FnCallEval, "Evaluate a mathematical expression",

Also available in: Unified diff