diff --git a/cf-agent/cf-agent.c b/cf-agent/cf-agent.c index a6975c5e9e..b8b0b80c8a 100644 --- a/cf-agent/cf-agent.c +++ b/cf-agent/cf-agent.c @@ -1547,7 +1547,7 @@ static void KeepPromiseBundles(EvalContext *ctx, const Policy *policy, GenericAg if (bp) { BundleBanner(bp,args); - EvalContextStackPushBundleFrame(ctx, bp, args, false); + EvalContextStackPushBundleFrame(ctx, bp, args, false, NULL); ScheduleAgentOperations(ctx, bp); EvalContextStackPopFrame(ctx); EndBundleBanner(bp); diff --git a/cf-agent/verify_files.c b/cf-agent/verify_files.c index e568fb4f86..45cc84bfc0 100644 --- a/cf-agent/verify_files.c +++ b/cf-agent/verify_files.c @@ -894,7 +894,7 @@ static PromiseResult RenderTemplateCFEngine(EvalContext *ctx, a.haveeditline = true; - EvalContextStackPushBundleFrame(ctx, bp, bundle_args, a.edits.inherit); + EvalContextStackPushBundleFrame(ctx, bp, bundle_args, a.edits.inherit, NULL); BundleResolve(ctx, bp); *save_file = ScheduleEditLineOperations(ctx, bp, &a, pp, edcontext); @@ -1154,7 +1154,7 @@ PromiseResult ScheduleEditOperation(EvalContext *ctx, char *filename, const Bundle *bp = EvalContextResolveBundleExpression(ctx, policy, edit_bundle_name, "edit_line"); if (bp) { - EvalContextStackPushBundleFrame(ctx, bp, args, a->edits.inherit); + EvalContextStackPushBundleFrame(ctx, bp, args, a->edits.inherit, NULL); BundleResolve(ctx, bp); @@ -1192,7 +1192,7 @@ PromiseResult ScheduleEditOperation(EvalContext *ctx, char *filename, const Bundle *bp = EvalContextResolveBundleExpression(ctx, policy, edit_bundle_name, "edit_xml"); if (bp) { - EvalContextStackPushBundleFrame(ctx, bp, args, a->edits.inherit); + EvalContextStackPushBundleFrame(ctx, bp, args, a->edits.inherit, NULL); BundleResolve(ctx, bp); ScheduleEditXmlOperations(ctx, bp, a, pp, edcontext); diff --git a/cf-agent/verify_methods.c b/cf-agent/verify_methods.c index 38031e41c5..b19d5952c9 100644 --- a/cf-agent/verify_methods.c +++ b/cf-agent/verify_methods.c @@ -148,7 +148,7 @@ PromiseResult VerifyMethod(EvalContext *ctx, const Rval call, const Attributes * { BundleBanner(bp, args); EvalContextSetBundleArgs(ctx, args); - EvalContextStackPushBundleFrame(ctx, bp, args, a->inherit); + EvalContextStackPushBundleFrame(ctx, bp, args, a->inherit, PromiseGetBundle(pp)); /* Clear all array-variables that are already set in the sub-bundle. Otherwise, array-data accumulates between multiple bundle evaluations. diff --git a/cf-monitord/env_monitor.c b/cf-monitord/env_monitor.c index d46bb96674..fa84e92115 100644 --- a/cf-monitord/env_monitor.c +++ b/cf-monitord/env_monitor.c @@ -1143,7 +1143,7 @@ static void GatherPromisedMeasures(EvalContext *ctx, const Policy *policy) for (size_t i = 0; i < SeqLength(policy->bundles); i++) { const Bundle *bp = SeqAt(policy->bundles, i); - EvalContextStackPushBundleFrame(ctx, bp, NULL, false); + EvalContextStackPushBundleFrame(ctx, bp, NULL, false, NULL); if ((strcmp(bp->type, CF_AGENTTYPES[AGENT_TYPE_MONITOR]) == 0) || (strcmp(bp->type, CF_AGENTTYPES[AGENT_TYPE_COMMON]) == 0)) { diff --git a/cf-serverd/server_transform.c b/cf-serverd/server_transform.c index 2265c4bcaf..a22772089d 100644 --- a/cf-serverd/server_transform.c +++ b/cf-serverd/server_transform.c @@ -641,7 +641,7 @@ static bool IsPromiseTypeNotInTypeSequence(const char *promise_type, static void EvaluateBundle(EvalContext *ctx, const Bundle *bp, const char * const *seq) { - EvalContextStackPushBundleFrame(ctx, bp, NULL, false); + EvalContextStackPushBundleFrame(ctx, bp, NULL, false, NULL); for (int type = 0; seq[type] != NULL; type++) { diff --git a/libpromises/eval_context.c b/libpromises/eval_context.c index 0684e526cb..3f74b3bd57 100644 --- a/libpromises/eval_context.c +++ b/libpromises/eval_context.c @@ -1362,13 +1362,14 @@ static StackFrame *StackFrameNew(StackFrameType type, bool inherit_previous) return frame; } -static StackFrame *StackFrameNewBundle(const Bundle *owner, bool inherit_previous, bool profiling, EventFrame *prev_event) +static StackFrame *StackFrameNewBundle(const Bundle *owner, bool inherit_previous, bool profiling, const Bundle *calling_bundle, EventFrame *prev_event) { StackFrame *frame = StackFrameNew(STACK_FRAME_TYPE_BUNDLE, inherit_previous); frame->data.bundle.owner = owner; frame->data.bundle.classes = ClassTableNew(); frame->data.bundle.vars = VariableTableNew(); + frame->data.bundle.calling_bundle = calling_bundle; frame->event = (profiling) ? BundleToEventFrame(owner, prev_event) : NULL; return frame; @@ -1445,12 +1446,12 @@ static void EvalContextStackPushFrame(EvalContext *ctx, StackFrame *frame) STACK_FRAME_TYPE_STR[frame->type]); } -void EvalContextStackPushBundleFrame(EvalContext *ctx, const Bundle *owner, const Rlist *args, bool inherits_previous) +void EvalContextStackPushBundleFrame(EvalContext *ctx, const Bundle *owner, const Rlist *args, bool inherits_previous, const Bundle *calling_bundle) { assert(ctx != NULL); assert(!LastStackFrame(ctx, 0) || LastStackFrame(ctx, 0)->type == STACK_FRAME_TYPE_PROMISE_ITERATION); - StackFrame *frame = StackFrameNewBundle(owner, inherits_previous, ctx->profiling, EvalContextGetLastEventFrame(ctx)); + StackFrame *frame = StackFrameNewBundle(owner, inherits_previous, ctx->profiling, calling_bundle, EvalContextGetLastEventFrame(ctx)); EvalContextStackPushFrame(ctx, frame); if (RlistLen(args) > 0) @@ -1574,6 +1575,14 @@ void EvalContextStackPushPromiseFrame(EvalContext *ctx, const Promise *owner) EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "bundle", PromiseGetBundle(owner)->name, CF_DATA_TYPE_STRING, "source=promise"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "namespace", PromiseGetNamespace(owner), CF_DATA_TYPE_STRING, "source=promise"); + StackFrame *bundle_frame = LastStackFrameByType(ctx, STACK_FRAME_TYPE_BUNDLE); + if (bundle_frame != NULL && bundle_frame->data.bundle.calling_bundle != NULL) + { + char *calling_bundle_name = StringFormat("%s:%s", bundle_frame->data.bundle.calling_bundle->ns, bundle_frame->data.bundle.calling_bundle->name); + EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "calling_bundle", calling_bundle_name, CF_DATA_TYPE_STRING, "source=promise"); + free(calling_bundle_name); + } + // Recompute `with` for (size_t i = 0; i < SeqLength(owner->conlist); i++) { diff --git a/libpromises/eval_context.h b/libpromises/eval_context.h index c42bc8a8a3..6e7699ba59 100644 --- a/libpromises/eval_context.h +++ b/libpromises/eval_context.h @@ -67,6 +67,7 @@ typedef enum typedef struct { const Bundle *owner; + const Bundle *calling_bundle; ClassTable *classes; VariableTable *vars; @@ -187,7 +188,7 @@ void EvalContextClear(EvalContext *ctx); Rlist *EvalContextGetPromiseCallerMethods(EvalContext *ctx); -void EvalContextStackPushBundleFrame(EvalContext *ctx, const Bundle *owner, const Rlist *args, bool inherits_previous); +void EvalContextStackPushBundleFrame(EvalContext *ctx, const Bundle *owner, const Rlist *args, bool inherits_previous, const Bundle *calling_bundle); void EvalContextStackPushBodyFrame(EvalContext *ctx, const Promise *caller, const Body *body, const Rlist *args); void EvalContextStackPushBundleSectionFrame(EvalContext *ctx, const BundleSection *owner); void EvalContextStackPushPromiseFrame(EvalContext *ctx, const Promise *owner); diff --git a/libpromises/expand.c b/libpromises/expand.c index 0246e1ff74..2a2009a2ce 100644 --- a/libpromises/expand.c +++ b/libpromises/expand.c @@ -1118,7 +1118,7 @@ void PolicyResolve(EvalContext *ctx, const Policy *policy, Bundle *bundle = SeqAt(policy->bundles, i); if (strcmp("common", bundle->type) == 0) { - EvalContextStackPushBundleFrame(ctx, bundle, NULL, false); + EvalContextStackPushBundleFrame(ctx, bundle, NULL, false, NULL); BundleResolve(ctx, bundle); /* PRE-EVAL classes,vars */ EvalContextStackPopFrame(ctx); } @@ -1136,7 +1136,7 @@ void PolicyResolve(EvalContext *ctx, const Policy *policy, Bundle *bundle = SeqAt(policy->bundles, i); if (strcmp("common", bundle->type) != 0) { - EvalContextStackPushBundleFrame(ctx, bundle, NULL, false); + EvalContextStackPushBundleFrame(ctx, bundle, NULL, false, NULL); BundleResolve(ctx, bundle); /* PRE-EVAL vars */ EvalContextStackPopFrame(ctx); } diff --git a/libpromises/loading.c b/libpromises/loading.c index 244a30d7f6..4fbaca6d31 100644 --- a/libpromises/loading.c +++ b/libpromises/loading.c @@ -573,7 +573,7 @@ Policy *LoadPolicy(EvalContext *ctx, GenericAgentConfig *config) for (size_t i = 0; i < SeqLength(policy->bundles); i++) { Bundle *bp = SeqAt(policy->bundles, i); - EvalContextStackPushBundleFrame(ctx, bp, NULL, false); + EvalContextStackPushBundleFrame(ctx, bp, NULL, false, NULL); for (size_t j = 0; j < SeqLength(bp->sections); j++) { diff --git a/tests/acceptance/01_vars/01_basic/calling_bundle.cf b/tests/acceptance/01_vars/01_basic/calling_bundle.cf new file mode 100644 index 0000000000..2fde108f14 --- /dev/null +++ b/tests/acceptance/01_vars/01_basic/calling_bundle.cf @@ -0,0 +1,65 @@ +# Test $(this.calling_bundle) + +body common control +{ + inputs => { "../../default.cf.sub" }; + bundlesequence => { default("$(this.promise_filename)") }; +} + +####################################################### + +bundle agent init +{ + methods: + "a" + usebundle => new_namespace:A, + useresult => "return_var"; +} + +####################################################### + +bundle agent check +{ + vars: + "expected" + string => "default:init/new_namespace:A/B"; + + classes: + "ok" + expression => strcmp("$(init.return_var[1])", "$(expected)"); + + reports: + DEBUG:: + "$(this.promise_filename) expected dirname $(init.return_var[1]), actual $(expected)"; + + ok:: + "$(this.promise_filename) Pass"; + !ok:: + "$(this.promise_filename) FAIL"; +} + +body file control +{ + namespace => "new_namespace"; +} + + +bundle agent A +{ + methods: + "b" + usebundle => new_namespace:B, + useresult => "return_var"; + + reports: + "$(this.calling_bundle)/$(return_var[1])" + bundle_return_value_index => "1"; + +} + +bundle agent B +{ + reports: + "$(this.calling_bundle)/$(this.bundle)" + bundle_return_value_index => "1"; +} diff --git a/tests/unit/eval_context_test.c b/tests/unit/eval_context_test.c index f2f1e6f0e2..e47b6e1a4b 100644 --- a/tests/unit/eval_context_test.c +++ b/tests/unit/eval_context_test.c @@ -55,7 +55,7 @@ static void test_class_persistence(void) Policy *p = PolicyNew(); Bundle *bp = PolicyAppendBundle(p, "ns1", "bundle1", "agent", NULL, NULL, EVAL_ORDER_UNDEFINED); - EvalContextStackPushBundleFrame(ctx, bp, NULL, false); + EvalContextStackPushBundleFrame(ctx, bp, NULL, false, NULL); EvalContextHeapPersistentSave(ctx, "class2", 5, CONTEXT_STATE_POLICY_PRESERVE, "x"); EvalContextStackPopFrame(ctx); diff --git a/tests/unit/expand_test.c b/tests/unit/expand_test.c index 3ae7a168ad..219f07571d 100644 --- a/tests/unit/expand_test.c +++ b/tests/unit/expand_test.c @@ -130,7 +130,7 @@ static void test_map_iterators_from_rval_naked_list_var(void **state) RlistDestroy(list); } - EvalContextStackPushBundleFrame(ctx, bp, NULL, false); + EvalContextStackPushBundleFrame(ctx, bp, NULL, false, NULL); { Rlist *lists = NULL; @@ -203,7 +203,7 @@ static void test_map_iterators_from_rval_naked_list_var_namespace(void **state) RlistDestroy(list); } - EvalContextStackPushBundleFrame(ctx, bp, NULL, false); + EvalContextStackPushBundleFrame(ctx, bp, NULL, false, NULL); { Rlist *lists = NULL; @@ -425,7 +425,7 @@ static void test_expand_promise_array_with_scalar_arg(void **state) BundleSection *section = BundleAppendSection(bundle, "dummy"); Promise *promise = BundleSectionAppendPromise(section, "$(foo[$(bar)])", (Rval) { NULL, RVAL_TYPE_NOPROMISEE }, "any", NULL); - EvalContextStackPushBundleFrame(ctx, bundle, NULL, false); + EvalContextStackPushBundleFrame(ctx, bundle, NULL, false, NULL); EvalContextStackPushBundleSectionFrame(ctx, section); ExpandPromise(ctx, promise, actuator_expand_promise_array_with_scalar_arg, NULL); EvalContextStackPopFrame(ctx); @@ -480,7 +480,7 @@ static void test_expand_promise_slist(void **state) BundleSection *section = BundleAppendSection(bundle, "dummy"); Promise *promise = BundleSectionAppendPromise(section, "$(foo)", (Rval) { NULL, RVAL_TYPE_NOPROMISEE }, "any", NULL); - EvalContextStackPushBundleFrame(ctx, bundle, NULL, false); + EvalContextStackPushBundleFrame(ctx, bundle, NULL, false, NULL); EvalContextStackPushBundleSectionFrame(ctx, section); ExpandPromise(ctx, promise, actuator_expand_promise_slist, NULL); EvalContextStackPopFrame(ctx); @@ -548,7 +548,7 @@ static void test_expand_promise_array_with_slist_arg(void **state) BundleSection *section = BundleAppendSection(bundle, "dummy"); Promise *promise = BundleSectionAppendPromise(section, "$(arr[$(keys)])", (Rval) { NULL, RVAL_TYPE_NOPROMISEE }, "any", NULL); - EvalContextStackPushBundleFrame(ctx, bundle, NULL, false); + EvalContextStackPushBundleFrame(ctx, bundle, NULL, false, NULL); EvalContextStackPushBundleSectionFrame(ctx, section); ExpandPromise(ctx, promise, actuator_expand_promise_array_with_slist_arg, NULL); EvalContextStackPopFrame(ctx); diff --git a/tests/unit/iteration_test.c b/tests/unit/iteration_test.c index 58a5185925..c10c3b46a4 100644 --- a/tests/unit/iteration_test.c +++ b/tests/unit/iteration_test.c @@ -249,7 +249,7 @@ static void IteratorPrepare_TestHelper( Promise *promise = BundleSectionAppendPromise(section, promiser, (Rval) { NULL, RVAL_TYPE_NOPROMISEE }, "any", NULL); - EvalContextStackPushBundleFrame(evalctx, bundle, NULL, false); + EvalContextStackPushBundleFrame(evalctx, bundle, NULL, false, NULL); EvalContextStackPushBundleSectionFrame(evalctx, section); PromiseIterator *iterctx = PromiseIteratorNew(promise); char *promiser_copy = xstrdup(promiser);