-
Notifications
You must be signed in to change notification settings - Fork 4
Implement test run #2218
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Implement test run #2218
Changes from all commits
a12068e
c9209d3
f20c600
5f79196
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,21 +8,17 @@ | |
| import com.openframe.data.document.rmm.script.Script; | ||
| import com.openframe.data.document.rmm.script.ScriptEnvVar; | ||
| import com.openframe.data.document.rmm.script.ScriptStatus; | ||
| import org.springframework.beans.factory.annotation.Value; | ||
| import org.springframework.stereotype.Component; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| /** | ||
| * Pure entity ↔ DTO mapping for scripts. Lives in {@code openframe-api-lib} | ||
| * so it can be reused by any service that talks to the script repository, | ||
| * regardless of transport (GraphQL / REST / messaging). | ||
| * | ||
| * <p>GraphQL-specific concerns (cursor pagination, Relay Connection / Edge | ||
| * envelope) live in {@code GraphQLScriptMapper} alongside the DGS resolver. | ||
| */ | ||
| @Component | ||
| public class ScriptMapper { | ||
|
|
||
| @Value("${openframe.rmm.test-mode.enabled}") | ||
| private boolean testModeEnabled; | ||
|
Check failure on line 20 in openframe-api-lib/src/main/java/com/openframe/api/mapper/ScriptMapper.java
|
||
|
|
||
| public Script toEntity(String tenantId, CreateScriptInput input) { | ||
| return Script.builder() | ||
| .tenantId(tenantId) | ||
|
|
@@ -35,6 +31,7 @@ | |
| .defaultTimeoutSeconds(input.getDefaultTimeoutSeconds()) | ||
| .defaultArgs(input.getDefaultArgs()) | ||
| .envVars(ScriptEnvVarMapper.toEntity(input.getEnvVars())) | ||
| .testScript(testModeEnabled) | ||
| .build(); | ||
| } | ||
|
|
||
|
|
@@ -50,25 +47,26 @@ | |
| existing.setEnvVars(ScriptEnvVarMapper.toEntity(input.getEnvVars())); | ||
| } | ||
|
|
||
| public ScriptResponse toResponse(Script entity) { | ||
| return ScriptResponse.builder() | ||
| .id(entity.getId()) | ||
| .name(entity.getName()) | ||
| .description(entity.getDescription()) | ||
| .shell(entity.getShell()) | ||
| .privilegeLevel(entity.getPrivilegeLevel() != null ? entity.getPrivilegeLevel() : PrivilegeLevel.USER) | ||
| .scriptBody(entity.getScriptBody()) | ||
| .supportedPlatforms(entity.getSupportedPlatforms()) | ||
| .defaultTimeoutSeconds(entity.getDefaultTimeoutSeconds()) | ||
| .defaultArgs(entity.getDefaultArgs()) | ||
| .envVars(mapEnvVarsToResponse(entity.getEnvVars())) | ||
| .createdBy(entity.getCreatedBy()) | ||
| .status(entity.getStatus() != null ? entity.getStatus() : ScriptStatus.ACTIVE) | ||
| .statusChangedAt(entity.getStatusChangedAt()) | ||
| .createdAt(entity.getCreatedAt()) | ||
| .updatedAt(entity.getUpdatedAt()) | ||
| .testScript(entity.isTestScript()) | ||
| .build(); | ||
| } | ||
|
Check warning on line 69 in openframe-api-lib/src/main/java/com/openframe/api/mapper/ScriptMapper.java
|
||
|
|
||
| private List<ScriptEnvVarInput> mapEnvVarsToResponse(List<ScriptEnvVar> envVars) { | ||
| if (envVars == null) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,6 +11,7 @@ | |
| import com.openframe.data.document.rmm.schedule.ScheduleScriptTrigger; | ||
| import com.openframe.data.document.rmm.schedule.ScheduleTimeReference; | ||
| import com.openframe.data.document.rmm.script.ScriptStatus; | ||
| import org.springframework.beans.factory.annotation.Value; | ||
| import org.springframework.stereotype.Component; | ||
|
|
||
| import java.util.List; | ||
|
|
@@ -23,6 +24,9 @@ | |
| @Component | ||
| public class ScriptScheduleMapper { | ||
|
|
||
| @Value("${openframe.rmm.test-mode.enabled}") | ||
| private boolean testModeEnabled; | ||
|
|
||
| public ScheduleScript toEntity(String tenantId, CreateScriptScheduleInput input) { | ||
| return ScheduleScript.builder() | ||
| .tenantId(tenantId) | ||
|
|
@@ -37,6 +41,7 @@ | |
| .reconnectWindowSeconds(input.getReconnectWindowSeconds()) | ||
| .startAt(input.getStartAt()) | ||
| .repeat(input.getRepeat()) | ||
| .testScript(testModeEnabled) | ||
| .build(); | ||
| } | ||
|
|
||
|
|
@@ -71,31 +76,32 @@ | |
| return mode != null ? mode : ScheduleDeviceSelectionMode.SPECIFIC; | ||
| } | ||
|
|
||
| public ScriptScheduleResponse toResponse(ScheduleScript entity) { | ||
| return ScriptScheduleResponse.builder() | ||
| .id(entity.getId()) | ||
| .name(entity.getName()) | ||
| .description(entity.getDescription()) | ||
| .supportedPlatforms(entity.getSupportedPlatforms()) | ||
| .scriptIds(entity.getScriptIds()) | ||
| .scriptCustomParams(entity.getScriptCustomParams()) | ||
| .selectionMode(defaultSelectionMode(entity.getSelectionMode())) | ||
| .deviceCriteria(entity.getDeviceCriteria()) | ||
| .trigger(defaultTrigger(entity.getTrigger())) | ||
| .timeReference(defaultTimeReference(entity.getTimeReference())) | ||
| .offlineBehavior(defaultOfflineBehavior(entity.getOfflineBehavior())) | ||
| .reconnectWindowSeconds(entity.getReconnectWindowSeconds()) | ||
| .startAt(entity.getStartAt()) | ||
| .repeat(entity.getRepeat()) | ||
| .nextRunAt(entity.getNextRunAt()) | ||
| .lastRunAt(entity.getLastRunAt()) | ||
| .createdBy(entity.getCreatedBy()) | ||
| .status(entity.getStatus() != null ? entity.getStatus() : ScriptStatus.ACTIVE) | ||
| .statusChangedAt(entity.getStatusChangedAt()) | ||
| .createdAt(entity.getCreatedAt()) | ||
| .updatedAt(entity.getUpdatedAt()) | ||
| .testScript(entity.isTestScript()) | ||
| .build(); | ||
| } | ||
|
Check warning on line 104 in openframe-api-lib/src/main/java/com/openframe/api/mapper/ScriptScheduleMapper.java
|
||
|
|
||
| private static List<ScheduledScriptCustomParams> toCustomParams(List<ScheduledScriptCustomParamsInput> input) { | ||
| if (input == null) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,6 +10,7 @@ | |
| import com.openframe.data.nats.rmm.publisher.CommandNatsPublisher; | ||
| import lombok.RequiredArgsConstructor; | ||
| import lombok.extern.slf4j.Slf4j; | ||
| import org.springframework.beans.factory.annotation.Value; | ||
| import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | ||
| import org.springframework.stereotype.Service; | ||
|
|
||
|
|
@@ -37,6 +38,9 @@ | |
| private final DeviceService deviceService; | ||
| private final CommandExecutionService commandExecutionService; | ||
|
|
||
| @Value("${openframe.rmm.test-mode.enabled}") | ||
| private boolean testModeEnabled; | ||
|
Check warning on line 42 in openframe-api-lib/src/main/java/com/openframe/api/service/rmm/command/CommandDispatchService.java
|
||
|
Comment on lines
+41
to
+42
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🦩 🟠 [warn/recommended] The literal string "${openframe.rmm.test-mode.enabled}" is duplicated verbatim in ScriptMapper, ScriptScheduleMapper, CommandDispatchService, and ScriptDispatchService. Per OFJAVA-005 (named constants for values with meaning) and OPENFRAM-002-21 (grouped configuration via @ConfigurationProperties), this flag should be centralized in a single @ConfigurationProperties-bound class (e.g. RmmTestModeProperties) injected everywhere it's needed, rather than repeating the same @value string in four unrelated components. Evidence🤖 Prompt for AI agentsconfidence: 30 — react 👍/👎 to teach the reviewer |
||
|
|
||
| public DispatchResponse runCommand(RunCommandInput input) { | ||
| deviceService.verifyDispatchable(input.getMachineId()); | ||
|
|
||
|
|
@@ -76,7 +80,8 @@ | |
| // Persist one RUNNING row per machine (tenant-scoped, via the service) before | ||
| // anything hits the wire — the agent's result transitions each row later. | ||
| commandExecutionService.createBatch(executionId, input.getCommand(), input.getShell(), | ||
| machineIds, input.getPrivilegeLevel(), input.getTimeoutSeconds(), initiatedBy); | ||
| machineIds, input.getPrivilegeLevel(), input.getTimeoutSeconds(), initiatedBy, | ||
| testModeEnabled); | ||
|
|
||
| // Fan out the same payload (one executionId) to every machine. | ||
| CommandMessage message = CommandMessage.builder() | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -63,13 +63,14 @@ | |
| * later rename of the source {@code Script} is reflected in History without | ||
| * duplicating the name onto every row. | ||
| */ | ||
| public ScriptExecutionResponse create(String executionId, | ||
| String scriptId, | ||
| String machineId, | ||
| PrivilegeLevel privilegeLevel, | ||
| Integer timeoutSeconds, | ||
| String initiatedBy, | ||
| ExecutionSource source) { | ||
| ExecutionSource source, | ||
| boolean testScript) { | ||
|
Check warning on line 73 in openframe-api-lib/src/main/java/com/openframe/api/service/rmm/script/ScriptExecutionService.java
|
||
| // Single ad-hoc run (runScript) never originates from a schedule → scheduleId null. | ||
| List<ScriptExecution> saved = scriptExecutionRepository.saveRunning(RunningExecutionRows.builder() | ||
| .tenantId(tenantIdProvider.getTenantId()) | ||
|
|
@@ -80,6 +81,7 @@ | |
| .timeoutSeconds(timeoutSeconds) | ||
| .initiatedBy(initiatedBy) | ||
| .source(source) | ||
| .testScript(testScript) | ||
| .build()); | ||
| log.info("Persisted execution row: executionId={} scriptId={} machineId={} initiatedBy={} source={} status=RUNNING", | ||
| executionId, scriptId, machineId, initiatedBy, source); | ||
|
|
@@ -101,7 +103,8 @@ | |
| PrivilegeLevel privilegeLevel, | ||
| Integer timeoutSeconds, | ||
| String initiatedBy, | ||
| ExecutionSource source) { | ||
| ExecutionSource source, | ||
| boolean testScript) { | ||
| List<ScriptExecution> saved = scriptExecutionRepository.saveRunning(RunningExecutionRows.builder() | ||
| .tenantId(tenantIdProvider.getTenantId()) | ||
| .executionId(executionId) | ||
|
|
@@ -112,6 +115,7 @@ | |
| .timeoutSeconds(timeoutSeconds) | ||
| .initiatedBy(initiatedBy) | ||
| .source(source) | ||
| .testScript(testScript) | ||
| .build()); | ||
| log.info("Persisted batch execution rows: executionId={} scriptId={} scheduleId={} machineCount={} initiatedBy={} source={} status=RUNNING", | ||
| executionId, scriptId, scheduleId, machineIds.size(), initiatedBy, source); | ||
|
|
@@ -149,10 +153,11 @@ | |
| .timeoutSeconds(timeoutSeconds) | ||
| .initiatedBy(initiatedBy) | ||
| .source(source) | ||
| .packageManager(packageManager) | ||
| .packageName(packageName) | ||
| .softwareAction(softwareAction) | ||
| .testScript(false) | ||
| .build()); | ||
|
Check warning on line 160 in openframe-api-lib/src/main/java/com/openframe/api/service/rmm/script/ScriptExecutionService.java
|
||
|
Comment on lines
156
to
160
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🦩 🟠 [warn/recommended] Software-install batch rows hardcode testScript(false) instead of honoring the test-mode flag In ScriptExecutionService, the new createBatch(...) overload accepts a Evidence🤖 Prompt for AI agentsconfidence: 35 — react 👍/👎 to teach the reviewer |
||
| log.info("Persisted software batch rows: executionId={} scriptId={} packageManager={} packageName={} action={} machineCount={} initiatedBy={} source={} status=RUNNING", | ||
| executionId, scriptId, packageManager, packageName, softwareAction, machineIds.size(), initiatedBy, source); | ||
| return saved.stream().map(scriptExecutionMapper::toResponse).toList(); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🦩 🔴 [error/action_required]
OFJAVA-011@value property openframe.rmm.test-mode.enabled has no explicit default and no documented environment declarationThe new @value("${openframe.rmm.test-mode.enabled}") bindings (repeated in ScriptMapper, ScriptScheduleMapper, CommandDispatchService, and ScriptDispatchService) have no inline default and there's no evidence in this diff that the property is declared in every environment's config. If the property is missing in any environment, Spring will fail to start that service (fail-fast is fine per the rule), but if it silently falls back due to inconsistent config layering it could cause test scripts/commands to leak into production data. Confirm the property is explicitly declared in all environment YAML files, or supply a safe default consistently.
Evidence
🤖 Prompt for AI agents
confidence: 40 — react 👍/👎 to teach the reviewer