mirror of
https://github.com/sasjs/adapter.git
synced 2026-01-07 20:40:05 +00:00
Merge pull request #830 from sasjs/issue-829
fix(execute-script): fixed executing jobs on viya using compute api
This commit is contained in:
@@ -43,10 +43,10 @@ module.exports = {
|
|||||||
// An object that configures minimum threshold enforcement for coverage results
|
// An object that configures minimum threshold enforcement for coverage results
|
||||||
coverageThreshold: {
|
coverageThreshold: {
|
||||||
global: {
|
global: {
|
||||||
statements: 63.66,
|
statements: 63.61,
|
||||||
branches: 44.74,
|
branches: 44.72,
|
||||||
functions: 53.94,
|
functions: 53.94,
|
||||||
lines: 64.12
|
lines: 64.07
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import { prefixMessage } from '@sasjs/utils/error'
|
|||||||
import { pollJobState } from './api/viya/pollJobState'
|
import { pollJobState } from './api/viya/pollJobState'
|
||||||
import { getTokens } from './auth/getTokens'
|
import { getTokens } from './auth/getTokens'
|
||||||
import { uploadTables } from './api/viya/uploadTables'
|
import { uploadTables } from './api/viya/uploadTables'
|
||||||
import { executeScript } from './api/viya/executeScript'
|
import { executeOnComputeApi } from './api/viya/executeOnComputeApi'
|
||||||
import { getAccessTokenForViya } from './auth/getAccessTokenForViya'
|
import { getAccessTokenForViya } from './auth/getAccessTokenForViya'
|
||||||
import { refreshTokensForViya } from './auth/refreshTokensForViya'
|
import { refreshTokensForViya } from './auth/refreshTokensForViya'
|
||||||
|
|
||||||
@@ -293,7 +293,7 @@ export class SASViyaApiClient {
|
|||||||
printPid = false,
|
printPid = false,
|
||||||
variables?: MacroVar
|
variables?: MacroVar
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
return executeScript(
|
return executeOnComputeApi(
|
||||||
this.requestClient,
|
this.requestClient,
|
||||||
this.sessionManager,
|
this.sessionManager,
|
||||||
this.rootFolderName,
|
this.rootFolderName,
|
||||||
|
|||||||
@@ -15,8 +15,12 @@ import { formatDataForRequest } from '../../utils/formatDataForRequest'
|
|||||||
import { pollJobState, JobState } from './pollJobState'
|
import { pollJobState, JobState } from './pollJobState'
|
||||||
import { uploadTables } from './uploadTables'
|
import { uploadTables } from './uploadTables'
|
||||||
|
|
||||||
|
interface JobRequestBody {
|
||||||
|
[key: string]: number | string | string[]
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes code on the current SAS Viya server.
|
* Executes SAS program on the current SAS Viya server using Compute API.
|
||||||
* @param jobPath - the path to the file being submitted for execution.
|
* @param jobPath - the path to the file being submitted for execution.
|
||||||
* @param linesOfCode - an array of code lines to execute.
|
* @param linesOfCode - an array of code lines to execute.
|
||||||
* @param contextName - the context to execute the code in.
|
* @param contextName - the context to execute the code in.
|
||||||
@@ -29,7 +33,7 @@ import { uploadTables } from './uploadTables'
|
|||||||
* @param printPid - a boolean that indicates whether the function should print (PID) of the started job.
|
* @param printPid - a boolean that indicates whether the function should print (PID) of the started job.
|
||||||
* @param variables - an object that represents macro variables.
|
* @param variables - an object that represents macro variables.
|
||||||
*/
|
*/
|
||||||
export async function executeScript(
|
export async function executeOnComputeApi(
|
||||||
requestClient: RequestClient,
|
requestClient: RequestClient,
|
||||||
sessionManager: SessionManager,
|
sessionManager: SessionManager,
|
||||||
rootFolderName: string,
|
rootFolderName: string,
|
||||||
@@ -46,6 +50,7 @@ export async function executeScript(
|
|||||||
variables?: MacroVar
|
variables?: MacroVar
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
let access_token = (authConfig || {}).access_token
|
let access_token = (authConfig || {}).access_token
|
||||||
|
|
||||||
if (authConfig) {
|
if (authConfig) {
|
||||||
;({ access_token } = await getTokens(requestClient, authConfig))
|
;({ access_token } = await getTokens(requestClient, authConfig))
|
||||||
}
|
}
|
||||||
@@ -85,20 +90,6 @@ export async function executeScript(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const jobArguments: { [key: string]: any } = {
|
|
||||||
_contextName: contextName,
|
|
||||||
_OMITJSONLISTING: true,
|
|
||||||
_OMITJSONLOG: true,
|
|
||||||
_OMITSESSIONRESULTS: true,
|
|
||||||
_OMITTEXTLISTING: true,
|
|
||||||
_OMITTEXTLOG: true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (debug) {
|
|
||||||
jobArguments['_OMITTEXTLOG'] = false
|
|
||||||
jobArguments['_OMITSESSIONRESULTS'] = false
|
|
||||||
}
|
|
||||||
|
|
||||||
let fileName
|
let fileName
|
||||||
|
|
||||||
if (isRelativePath(jobPath)) {
|
if (isRelativePath(jobPath)) {
|
||||||
@@ -107,6 +98,7 @@ export async function executeScript(
|
|||||||
}`
|
}`
|
||||||
} else {
|
} else {
|
||||||
const jobPathParts = jobPath.split('/')
|
const jobPathParts = jobPath.split('/')
|
||||||
|
|
||||||
fileName = jobPathParts.pop()
|
fileName = jobPathParts.pop()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,7 +110,6 @@ export async function executeScript(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (variables) jobVariables = { ...jobVariables, ...variables }
|
if (variables) jobVariables = { ...jobVariables, ...variables }
|
||||||
|
|
||||||
if (debug) jobVariables = { ...jobVariables, _DEBUG: 131 }
|
if (debug) jobVariables = { ...jobVariables, _DEBUG: 131 }
|
||||||
|
|
||||||
let files: any[] = []
|
let files: any[] = []
|
||||||
@@ -145,12 +136,12 @@ export async function executeScript(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Execute job in session
|
// Execute job in session
|
||||||
const jobRequestBody = {
|
const jobRequestBody: JobRequestBody = {
|
||||||
name: fileName,
|
name: fileName || 'Default Job Name',
|
||||||
description: 'Powered by SASjs',
|
description: 'Powered by SASjs',
|
||||||
code: linesOfCode,
|
code: linesOfCode,
|
||||||
variables: jobVariables,
|
variables: jobVariables,
|
||||||
arguments: jobArguments
|
version: 2
|
||||||
}
|
}
|
||||||
|
|
||||||
const { result: postedJob, etag } = await requestClient
|
const { result: postedJob, etag } = await requestClient
|
||||||
@@ -279,7 +270,7 @@ export async function executeScript(
|
|||||||
const error = e as HttpError
|
const error = e as HttpError
|
||||||
|
|
||||||
if (error.status === 404) {
|
if (error.status === 404) {
|
||||||
return executeScript(
|
return executeOnComputeApi(
|
||||||
requestClient,
|
requestClient,
|
||||||
sessionManager,
|
sessionManager,
|
||||||
rootFolderName,
|
rootFolderName,
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { RequestClient } from '../../../request/RequestClient'
|
import { RequestClient } from '../../../request/RequestClient'
|
||||||
import { SessionManager } from '../../../SessionManager'
|
import { SessionManager } from '../../../SessionManager'
|
||||||
import { executeScript } from '../executeScript'
|
import { executeOnComputeApi } from '../executeOnComputeApi'
|
||||||
import { mockSession, mockAuthConfig, mockJob } from './mockResponses'
|
import { mockSession, mockAuthConfig, mockJob } from './mockResponses'
|
||||||
import * as pollJobStateModule from '../pollJobState'
|
import * as pollJobStateModule from '../pollJobState'
|
||||||
import * as uploadTablesModule from '../uploadTables'
|
import * as uploadTablesModule from '../uploadTables'
|
||||||
@@ -25,7 +25,7 @@ describe('executeScript', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should not try to get fresh tokens if an authConfig is not provided', async () => {
|
it('should not try to get fresh tokens if an authConfig is not provided', async () => {
|
||||||
await executeScript(
|
await executeOnComputeApi(
|
||||||
requestClient,
|
requestClient,
|
||||||
sessionManager,
|
sessionManager,
|
||||||
'test',
|
'test',
|
||||||
@@ -38,7 +38,7 @@ describe('executeScript', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should try to get fresh tokens if an authConfig is provided', async () => {
|
it('should try to get fresh tokens if an authConfig is provided', async () => {
|
||||||
await executeScript(
|
await executeOnComputeApi(
|
||||||
requestClient,
|
requestClient,
|
||||||
sessionManager,
|
sessionManager,
|
||||||
'test',
|
'test',
|
||||||
@@ -55,7 +55,7 @@ describe('executeScript', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should get a session from the session manager before executing', async () => {
|
it('should get a session from the session manager before executing', async () => {
|
||||||
await executeScript(
|
await executeOnComputeApi(
|
||||||
requestClient,
|
requestClient,
|
||||||
sessionManager,
|
sessionManager,
|
||||||
'test',
|
'test',
|
||||||
@@ -72,7 +72,7 @@ describe('executeScript', () => {
|
|||||||
.spyOn(sessionManager, 'getSession')
|
.spyOn(sessionManager, 'getSession')
|
||||||
.mockImplementation(() => Promise.reject('Test Error'))
|
.mockImplementation(() => Promise.reject('Test Error'))
|
||||||
|
|
||||||
const error = await executeScript(
|
const error = await executeOnComputeApi(
|
||||||
requestClient,
|
requestClient,
|
||||||
sessionManager,
|
sessionManager,
|
||||||
'test',
|
'test',
|
||||||
@@ -85,7 +85,7 @@ describe('executeScript', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should fetch the PID when printPid is true', async () => {
|
it('should fetch the PID when printPid is true', async () => {
|
||||||
await executeScript(
|
await executeOnComputeApi(
|
||||||
requestClient,
|
requestClient,
|
||||||
sessionManager,
|
sessionManager,
|
||||||
'test',
|
'test',
|
||||||
@@ -113,7 +113,7 @@ describe('executeScript', () => {
|
|||||||
.spyOn(sessionManager, 'getVariable')
|
.spyOn(sessionManager, 'getVariable')
|
||||||
.mockImplementation(() => Promise.reject('Test Error'))
|
.mockImplementation(() => Promise.reject('Test Error'))
|
||||||
|
|
||||||
const error = await executeScript(
|
const error = await executeOnComputeApi(
|
||||||
requestClient,
|
requestClient,
|
||||||
sessionManager,
|
sessionManager,
|
||||||
'test',
|
'test',
|
||||||
@@ -139,7 +139,7 @@ describe('executeScript', () => {
|
|||||||
Promise.resolve([{ tableName: 'test', file: { id: 1 } }])
|
Promise.resolve([{ tableName: 'test', file: { id: 1 } }])
|
||||||
)
|
)
|
||||||
|
|
||||||
await executeScript(
|
await executeOnComputeApi(
|
||||||
requestClient,
|
requestClient,
|
||||||
sessionManager,
|
sessionManager,
|
||||||
'test',
|
'test',
|
||||||
@@ -163,7 +163,7 @@ describe('executeScript', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should format data as CSV when it does not contain semicolons', async () => {
|
it('should format data as CSV when it does not contain semicolons', async () => {
|
||||||
await executeScript(
|
await executeOnComputeApi(
|
||||||
requestClient,
|
requestClient,
|
||||||
sessionManager,
|
sessionManager,
|
||||||
'test',
|
'test',
|
||||||
@@ -189,7 +189,7 @@ describe('executeScript', () => {
|
|||||||
.spyOn(formatDataModule, 'formatDataForRequest')
|
.spyOn(formatDataModule, 'formatDataForRequest')
|
||||||
.mockImplementation(() => ({ sasjs_tables: 'foo', sasjs0data: 'bar' }))
|
.mockImplementation(() => ({ sasjs_tables: 'foo', sasjs0data: 'bar' }))
|
||||||
|
|
||||||
await executeScript(
|
await executeOnComputeApi(
|
||||||
requestClient,
|
requestClient,
|
||||||
sessionManager,
|
sessionManager,
|
||||||
'test',
|
'test',
|
||||||
@@ -217,14 +217,7 @@ describe('executeScript', () => {
|
|||||||
sasjs_tables: 'foo',
|
sasjs_tables: 'foo',
|
||||||
sasjs0data: 'bar'
|
sasjs0data: 'bar'
|
||||||
},
|
},
|
||||||
arguments: {
|
version: 2
|
||||||
_contextName: 'test context',
|
|
||||||
_OMITJSONLISTING: true,
|
|
||||||
_OMITJSONLOG: true,
|
|
||||||
_OMITSESSIONRESULTS: true,
|
|
||||||
_OMITTEXTLISTING: true,
|
|
||||||
_OMITTEXTLOG: true
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
mockAuthConfig.access_token
|
mockAuthConfig.access_token
|
||||||
)
|
)
|
||||||
@@ -235,7 +228,7 @@ describe('executeScript', () => {
|
|||||||
.spyOn(formatDataModule, 'formatDataForRequest')
|
.spyOn(formatDataModule, 'formatDataForRequest')
|
||||||
.mockImplementation(() => ({ sasjs_tables: 'foo', sasjs0data: 'bar' }))
|
.mockImplementation(() => ({ sasjs_tables: 'foo', sasjs0data: 'bar' }))
|
||||||
|
|
||||||
await executeScript(
|
await executeOnComputeApi(
|
||||||
requestClient,
|
requestClient,
|
||||||
sessionManager,
|
sessionManager,
|
||||||
'test',
|
'test',
|
||||||
@@ -264,14 +257,7 @@ describe('executeScript', () => {
|
|||||||
sasjs0data: 'bar',
|
sasjs0data: 'bar',
|
||||||
_DEBUG: 131
|
_DEBUG: 131
|
||||||
},
|
},
|
||||||
arguments: {
|
version: 2
|
||||||
_contextName: 'test context',
|
|
||||||
_OMITJSONLISTING: true,
|
|
||||||
_OMITJSONLOG: true,
|
|
||||||
_OMITSESSIONRESULTS: false,
|
|
||||||
_OMITTEXTLISTING: true,
|
|
||||||
_OMITTEXTLOG: false
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
mockAuthConfig.access_token
|
mockAuthConfig.access_token
|
||||||
)
|
)
|
||||||
@@ -282,7 +268,7 @@ describe('executeScript', () => {
|
|||||||
.spyOn(requestClient, 'post')
|
.spyOn(requestClient, 'post')
|
||||||
.mockImplementation(() => Promise.reject('Test Error'))
|
.mockImplementation(() => Promise.reject('Test Error'))
|
||||||
|
|
||||||
const error = await executeScript(
|
const error = await executeOnComputeApi(
|
||||||
requestClient,
|
requestClient,
|
||||||
sessionManager,
|
sessionManager,
|
||||||
'test',
|
'test',
|
||||||
@@ -302,7 +288,7 @@ describe('executeScript', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should immediately return the session when waitForResult is false', async () => {
|
it('should immediately return the session when waitForResult is false', async () => {
|
||||||
const result = await executeScript(
|
const result = await executeOnComputeApi(
|
||||||
requestClient,
|
requestClient,
|
||||||
sessionManager,
|
sessionManager,
|
||||||
'test',
|
'test',
|
||||||
@@ -322,7 +308,7 @@ describe('executeScript', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should poll for job completion when waitForResult is true', async () => {
|
it('should poll for job completion when waitForResult is true', async () => {
|
||||||
await executeScript(
|
await executeOnComputeApi(
|
||||||
requestClient,
|
requestClient,
|
||||||
sessionManager,
|
sessionManager,
|
||||||
'test',
|
'test',
|
||||||
@@ -352,7 +338,7 @@ describe('executeScript', () => {
|
|||||||
.spyOn(pollJobStateModule, 'pollJobState')
|
.spyOn(pollJobStateModule, 'pollJobState')
|
||||||
.mockImplementation(() => Promise.reject('Poll Error'))
|
.mockImplementation(() => Promise.reject('Poll Error'))
|
||||||
|
|
||||||
const error = await executeScript(
|
const error = await executeOnComputeApi(
|
||||||
requestClient,
|
requestClient,
|
||||||
sessionManager,
|
sessionManager,
|
||||||
'test',
|
'test',
|
||||||
@@ -378,7 +364,7 @@ describe('executeScript', () => {
|
|||||||
Promise.reject({ response: { data: 'err=5113,' } })
|
Promise.reject({ response: { data: 'err=5113,' } })
|
||||||
)
|
)
|
||||||
|
|
||||||
const error = await executeScript(
|
const error = await executeOnComputeApi(
|
||||||
requestClient,
|
requestClient,
|
||||||
sessionManager,
|
sessionManager,
|
||||||
'test',
|
'test',
|
||||||
@@ -404,7 +390,7 @@ describe('executeScript', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should fetch the logs for the job if debug is true and a log URL is available', async () => {
|
it('should fetch the logs for the job if debug is true and a log URL is available', async () => {
|
||||||
await executeScript(
|
await executeOnComputeApi(
|
||||||
requestClient,
|
requestClient,
|
||||||
sessionManager,
|
sessionManager,
|
||||||
'test',
|
'test',
|
||||||
@@ -429,7 +415,7 @@ describe('executeScript', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should not fetch the logs for the job if debug is false', async () => {
|
it('should not fetch the logs for the job if debug is false', async () => {
|
||||||
await executeScript(
|
await executeOnComputeApi(
|
||||||
requestClient,
|
requestClient,
|
||||||
sessionManager,
|
sessionManager,
|
||||||
'test',
|
'test',
|
||||||
@@ -455,7 +441,7 @@ describe('executeScript', () => {
|
|||||||
Promise.resolve(pollJobStateModule.JobState.Failed)
|
Promise.resolve(pollJobStateModule.JobState.Failed)
|
||||||
)
|
)
|
||||||
|
|
||||||
const error: ComputeJobExecutionError = await executeScript(
|
const error: ComputeJobExecutionError = await executeOnComputeApi(
|
||||||
requestClient,
|
requestClient,
|
||||||
sessionManager,
|
sessionManager,
|
||||||
'test',
|
'test',
|
||||||
@@ -490,7 +476,7 @@ describe('executeScript', () => {
|
|||||||
Promise.resolve(pollJobStateModule.JobState.Error)
|
Promise.resolve(pollJobStateModule.JobState.Error)
|
||||||
)
|
)
|
||||||
|
|
||||||
const error: ComputeJobExecutionError = await executeScript(
|
const error: ComputeJobExecutionError = await executeOnComputeApi(
|
||||||
requestClient,
|
requestClient,
|
||||||
sessionManager,
|
sessionManager,
|
||||||
'test',
|
'test',
|
||||||
@@ -519,7 +505,7 @@ describe('executeScript', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should fetch the result if expectWebout is true', async () => {
|
it('should fetch the result if expectWebout is true', async () => {
|
||||||
await executeScript(
|
await executeOnComputeApi(
|
||||||
requestClient,
|
requestClient,
|
||||||
sessionManager,
|
sessionManager,
|
||||||
'test',
|
'test',
|
||||||
@@ -550,7 +536,7 @@ describe('executeScript', () => {
|
|||||||
return Promise.resolve({ result: mockJob, etag: '', status: 200 })
|
return Promise.resolve({ result: mockJob, etag: '', status: 200 })
|
||||||
})
|
})
|
||||||
|
|
||||||
const error = await executeScript(
|
const error = await executeOnComputeApi(
|
||||||
requestClient,
|
requestClient,
|
||||||
sessionManager,
|
sessionManager,
|
||||||
'test',
|
'test',
|
||||||
@@ -584,7 +570,7 @@ describe('executeScript', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should clear the session after execution is complete', async () => {
|
it('should clear the session after execution is complete', async () => {
|
||||||
await executeScript(
|
await executeOnComputeApi(
|
||||||
requestClient,
|
requestClient,
|
||||||
sessionManager,
|
sessionManager,
|
||||||
'test',
|
'test',
|
||||||
@@ -611,7 +597,7 @@ describe('executeScript', () => {
|
|||||||
.spyOn(sessionManager, 'clearSession')
|
.spyOn(sessionManager, 'clearSession')
|
||||||
.mockImplementation(() => Promise.reject('Clear Session Error'))
|
.mockImplementation(() => Promise.reject('Clear Session Error'))
|
||||||
|
|
||||||
const error = await executeScript(
|
const error = await executeOnComputeApi(
|
||||||
requestClient,
|
requestClient,
|
||||||
sessionManager,
|
sessionManager,
|
||||||
'test',
|
'test',
|
||||||
|
|||||||
Reference in New Issue
Block a user