Conversation
There was a problem hiding this comment.
CodeQL found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.
b7d8916 to
33ee80a
Compare
| VarRefDestroy(ref); | ||
| } | ||
|
|
||
| static PromiseResult KeepAgentPromise(EvalContext *ctx, const Promise *pp, ARG_UNUSED void *param) |
f98bd05 to
36fa38f
Compare
Signed-off-by: Victor Moene <victor.moene@northern.tech>
36fa38f to
0f805bb
Compare
larsewi
left a comment
There was a problem hiding this comment.
Please do a review with Claude. For me it found a few things that seem plausible:
- A remote
copy_fromin athenbundle crashes cf-reactor - State builds up across repeated runs of the same bundle
- The
EvalAbortedbranch is dead code
1bb39a3 to
5a8c477
Compare
craigcomstock
left a comment
There was a problem hiding this comment.
looks good generally
5a8c477 to
58f4f25
Compare
Better concurrency for cf-reactor static state - No need for map anymore, since watcher keeps track of the promise - No need to keep key as variable anymore, since we do not use a map - No need to run bundle inside watcher.c - No risk of running a bundle from a wrong key between policy reads Signed-off-by: Victor Moene <victor.moene@northern.tech>
Promises are skipped to prevent running them several times. However, on event, we want to run them every single time: - we clear the promise lock cache - we set the default if_elapsed time for bundles run from an events promise to be 0, so it doesn't skip the promises. Fixed also connection cache and custom promise prologue and epilogue. Clear function cache before "then" bundle run Signed-off-by: Victor Moene <victor.moene@northern.tech>
Signed-off-by: Victor Moene <victor.moene@northern.tech>
58f4f25 to
d02b0bb
Compare
|
@cf-bottom jenkins, please |
|
Sure, I triggered a build: Jenkins: https://ci.cfengine.com/job/pr-pipeline/14750/ Packages: http://buildcache.cfengine.com/packages/testing-pr/jenkins-pr-pipeline-14750/ |
Added a fix for the windows failure in enterprise. Restarted it |
|
@victormlg for a rebuild in jenkins, it would be nice if we updated the PR with the links... so here I will do it manually: Jenkins: https://ci.cfengine.com/job/pr-pipeline/14753/ Packages: http://buildcache.cfengine.com/packages/testing-pr/jenkins-pr-pipeline-14753/ |
| included file COSL.txt. | ||
| */ | ||
|
|
||
| /* ScheduleAgentOperations() and the promise actuator it uses: this is what |
There was a problem hiding this comment.
maybe say something more clear here like "This file, agent_operations.c, implements ScheduleAgentOperations() and ..."
| * AGENT_TYPESEQUENCE order, keeping each one with KeepAgentPromise()). It is | ||
| * kept separate from cf-agent.c so that other components (e.g. cf-reactor, | ||
| * running the bundle named in an events promise's "then") can run a bundle | ||
| * the same way cf-agent does, without linking cf-agent's main(). */ |
There was a problem hiding this comment.
Maybe refer to a follow-up/todo ticket to refactor/move this code to libpromises.
| int CFA_BACKGROUND = 0; /* GLOBAL_X */ | ||
| int CFA_BACKGROUND_LIMIT = 1; /* GLOBAL_P */ | ||
|
|
||
| Item *PROCESSREFRESH = NULL; /* GLOBAL_P */ |
There was a problem hiding this comment.
what do these comments indicate? We might want to include a reference to GLOBALS file as well in each of these comments, even expanding them to GLOBAL_P is set during policy parsing and is OK where-as GLOBAL_X is unclassified and dealt with on a case-by-case basis and so here we should describe the case/reason why this global is OK.
There was a problem hiding this comment.
The header file explains does an OK job of explaining the GLOBAL_P globals:
extern int CFA_BACKGROUND; /* GLOBAL_X */
extern int CFA_BACKGROUND_LIMIT; /* GLOBAL_P, body agent control: max_children */
extern Item *PROCESSREFRESH; /* GLOBAL_P, body agent control: refresh_processes */
I see that CFA_BACKGROUND is a counter and is involved primarily in the function ParallelFindAndVerifyFilesPromises() and also referenced in cf-agent.c for a call to EndAudit(ctx, CFA_BACKGROUND) which then calls LogTotalCompliance(version, background_tasks (the value of CFA_BACKGROUND sent in EndAudit()).
LogTotalCompliance() is an enterprise only feature.
The introduction of CFA_BACKGROUND was for "protection against overt use of parallelism" in this commit from Mark in 2009. fd38443
CFA is a short term for cf-agent I believe since in cf3.defs.h in the above commit we also have cfex_ prefix for cf-execd enums.
I wasn't aware of this low-level implementation detail yet and wonder if it is exercised or not.
I think it would be helpful to come back with another commit that adds annotations to this code explaining a few things that we find during review.
| return DefaultVarPromise(ctx, pp); | ||
| } | ||
|
|
||
| PromiseResult ScheduleAgentOperations(EvalContext *ctx, const Bundle *bp) |
There was a problem hiding this comment.
Since this is the crux of this file I think this function deserves some explanation of what it does and such.
There was a problem hiding this comment.
I see you have a comment above at the top, that's probably good. Maybe a comment here would include some sort of "API" like doc tags and such since it is expected to be used in multiple places now: cf-agent and cf-reactor.
| */ | ||
|
|
||
| /* ScheduleAgentOperations() and the promise actuator it uses: this is what | ||
| * cf-agent does with a single bundle (evaluate its promises in |
There was a problem hiding this comment.
maybe "this is the function that cf-agent uses to evaluate a single bundle and it's promises in AGENT_TYPESEQUENCE order" or similar... as a way of making it clear what this function does with less "technical/internal" language like "promise actuator".
| } | ||
|
|
||
| PromiseResult ScheduleAgentOperations(EvalContext *ctx, const Bundle *bp) | ||
| // NB - this function can be called recursively through "methods" |
There was a problem hiding this comment.
a follow up tidy commit might change NB to just NOTE: I assume this NB means nota bene, latin for note well or pay close attention.
| int save_pr_notkept = PR_NOTKEPT; | ||
| struct timespec start = BeginMeasure(); | ||
|
|
||
| if (PROCESSREFRESH == NULL || (PROCESSREFRESH && IsRegexItemIn(ctx, PROCESSREFRESH, bp->name))) |
There was a problem hiding this comment.
would be nice to know what manages PROCESSREFRESH global, I see that cf-agent.c does and there is a bit of TODO in that code in KeepControlPromises()
1027 if (strcmp(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_REFRESH_PROCESSES].lval) == 0)
1028 {
1029 Log(LOG_LEVEL_VERBOSE, "Setting refresh_processes when starting to...");
1030 for (const Rlist *rp = value; rp != NULL; rp = rp->next)
1031 {
1032 Log(LOG_LEVEL_VERBOSE, "%s", RlistScalarValue(rp));
1033 // TODO: why is this only done in verbose mode?
1034 // original commit says 'optimization'.
1035 if (LogGetGlobalLevel() >= LOG_LEVEL_VERBOSE)
1036 {
1037 PrependItem(&PROCESSREFRESH, RlistScalarValue(rp), NULL);
1038 }
1039 }
1040 continue;
1041 }
I see we have a condition of PROCESREFRESH == NULL so no impact here when we call this function from cf-reactor(or other binaries) which will likely not set the control promise to a value.
| { | ||
| EvalContextStackPopFrame(ctx); | ||
| NoteBundleCompliance(bp, save_pr_kept, save_pr_repaired, save_pr_notkept, start); | ||
| return result; |
There was a problem hiding this comment.
I notice that custom promise types don't create/delete a "type context" with NewTypeContext() and DeleteTypeContext(). I see that function only does anything for the deprecated environments promise type and the not so often used storage promise type. Would be nice to know why this type context is skipped for custom promise types. It does seem to be mostly a no-op practically speaking.
| result = PromiseResultUpdate(result, promise_result); | ||
| if (EvalAborted(ctx) || BundleAbort(ctx)) | ||
| { | ||
| EvalContextStackPopFrame(ctx); |
There was a problem hiding this comment.
Here also, we are not calling the "type context" functions. I wonder if we should just remove them entirely or go ahead and include them always. One or the other seems more correct.
| break; | ||
| } | ||
| default: | ||
| /* TODO is CF_DATA_TYPE_NONE acceptable? Today all meta variables |
There was a problem hiding this comment.
we should ensure a ticket exists and is referenced here for this todo. add in a separate commit, like a batch of tidying i suggested.
craigcomstock
left a comment
There was a problem hiding this comment.
a bit more, will continue later today
| struct timespec start = BeginMeasure(); | ||
| PromiseResult result = PROMISE_RESULT_NOOP; | ||
|
|
||
| if (strcmp("meta", PromiseGetPromiseType(pp)) == 0 || |
There was a problem hiding this comment.
this would read easier if we captured the promise type string in a local var.
| { | ||
| if (!LoadProcessTable()) | ||
| { | ||
| Log(LOG_LEVEL_ERR, "Unable to read the process table - cannot keep processes: type promises"); |
There was a problem hiding this comment.
seems like it would be better for VerifyProcessesPromise() to handle the proc load function call and return fail
| result = VerifyProcessesPromise(ctx, pp); | ||
| if (result != PROMISE_RESULT_SKIPPED) | ||
| { | ||
| EndMeasurePromise(start, pp); |
There was a problem hiding this comment.
why are we not calling EndMeasurePromise() for the types above here?
| result = PROMISE_RESULT_NOOP; | ||
| } | ||
|
|
||
| BannerStatusEnd(result, PromiseGetPromiseType(pp), pp->promiser); |
There was a problem hiding this comment.
why not refactor all of the EndMeasurePromise function calls to here?
Follow-up PR: #6375
Depends on: https://github.com/cfengine/enterprise/pull/1004