Revision 68ebf279
Added by Alexis Mousset over 7 years ago
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
Fixes #9737: Upgrade CFEngine in Rudder agent to 3.10