Initial
This commit is contained in:
@@ -4,6 +4,10 @@ import assert from 'node:assert/strict';
|
||||
|
||||
const { listJobs, getJob } = await load('../models/jobModel.js');
|
||||
const { cancelSystemJob, listSystemJobs, runSystemJob } = await load('../services/systemJobService.js');
|
||||
const { createCredential } = await load('../models/credentialModel.js');
|
||||
const { createHost } = await load('../models/hostModel.js');
|
||||
const { updateSettings } = await load('../models/settingsModel.js');
|
||||
const { buildWrapper, executeScriptTest } = await load('../services/powershellRunner.js');
|
||||
|
||||
const owner = makeUser({ email: 'job-owner@test.local' });
|
||||
const stranger = makeUser({ email: 'job-stranger@test.local' });
|
||||
@@ -52,6 +56,68 @@ test('admins can see any job', () => {
|
||||
assert.ok(getJob(jobId, admin, true));
|
||||
});
|
||||
|
||||
test('executeScriptTest creates job host rows before runner starts', async () => {
|
||||
const scriptOwner = makeUser({ email: 'script-test-owner@test.local' });
|
||||
const localScriptId = 'scr_execute_test_1';
|
||||
db.prepare(`INSERT INTO scripts (id, name, content, visibility, owner_user_id, version, created_at, updated_at)
|
||||
VALUES (?, 'Script Execute Test', 'Write-Output test', 'personal', ?, 1, ?, ?)`).run(localScriptId, scriptOwner, ts, ts);
|
||||
const credential = createCredential({
|
||||
name: 'Script Test Credential',
|
||||
kind: 'username_password',
|
||||
username: 'TEST\\svc',
|
||||
secret: 'secret',
|
||||
visibility: 'personal'
|
||||
}, scriptOwner);
|
||||
const host = createHost({
|
||||
name: 'Script Test Host',
|
||||
address: 'script-test.local',
|
||||
fqdn: 'script-test.local',
|
||||
osFamily: 'windows',
|
||||
transport: 'winrm',
|
||||
credentialId: credential.id,
|
||||
visibility: 'personal',
|
||||
tags: []
|
||||
}, scriptOwner);
|
||||
updateSettings({ allow_script_execution: 'false' });
|
||||
|
||||
const job = executeScriptTest(localScriptId, { hostId: host.id, credentialId: credential.id }, scriptOwner);
|
||||
await new Promise((resolve) => setTimeout(resolve, 25));
|
||||
|
||||
const jobHost = db.prepare('SELECT * FROM job_hosts WHERE job_id = ? AND host_id = ?').get(job.id, host.id);
|
||||
const errorLog = db.prepare('SELECT * FROM job_logs WHERE job_id = ? AND stream = ? AND line LIKE ?').get(job.id, 'stderr', '%Script execution is disabled%');
|
||||
assert.equal(jobHost.status, 'failed');
|
||||
assert.ok(errorLog);
|
||||
updateSettings({ allow_script_execution: 'true' });
|
||||
});
|
||||
|
||||
test('PowerShell wrappers fail the host when Invoke-Command writes a terminating error', () => {
|
||||
const wrapper = buildWrapper('Write-Output "remote smoke"', {
|
||||
id: 'hst_wrapper_winrm',
|
||||
name: 'Wrapper WinRM',
|
||||
address: 'dallas.pucknet.local',
|
||||
transport: 'winrm'
|
||||
});
|
||||
|
||||
assert.match(wrapper, /\$ErrorActionPreference = "Stop"/);
|
||||
assert.match(wrapper, /Invoke-Command -ComputerName 'dallas\.pucknet\.local'.*-ErrorAction Stop/);
|
||||
assert.match(wrapper, /catch \{/);
|
||||
assert.match(wrapper, /exit 1/);
|
||||
assert.doesNotMatch(wrapper, /\$ErrorActionPreference = "Continue"/);
|
||||
});
|
||||
|
||||
test('local PowerShell wrappers propagate native command failures', () => {
|
||||
const wrapper = buildWrapper('Write-Output "local smoke"', {
|
||||
id: 'hst_wrapper_local',
|
||||
name: 'Wrapper Local',
|
||||
address: 'localhost',
|
||||
transport: 'local'
|
||||
});
|
||||
|
||||
assert.match(wrapper, /\$global:LASTEXITCODE/);
|
||||
assert.match(wrapper, /exit \$global:LASTEXITCODE/);
|
||||
assert.match(wrapper, /exit 0/);
|
||||
});
|
||||
|
||||
test('system jobs list execution and background jobs', () => {
|
||||
const listJobId = 'job_list_system_test_1';
|
||||
db.prepare(`INSERT INTO jobs (id, runplan_id, script_id, status, triggered_by, started_at, created_at)
|
||||
|
||||
Reference in New Issue
Block a user