1
0
mirror of https://github.com/sasjs/adapter.git synced 2026-01-06 04:00:05 +00:00

Merge branch 'master' into issue-186

This commit is contained in:
Mihajlo Medjedovic
2021-01-04 13:36:44 +01:00
52 changed files with 12119 additions and 955 deletions

View File

@@ -21,6 +21,7 @@ import {
} from './types'
import { formatDataForRequest } from './utils/formatDataForRequest'
import { SessionManager } from './SessionManager'
import { ContextManager } from './ContextManager'
import { timestampToYYYYMMDDHHMMSS } from '@sasjs/utils/time'
import { Logger, LogLevel } from '@sasjs/utils/logger'
@@ -46,6 +47,7 @@ export class SASViyaApiClient {
this.contextName,
this.setCsrfToken
)
private contextManager = new ContextManager(this.serverUrl, this.setCsrfToken)
private folderMap = new Map<string, Job[]>()
public get debug() {
@@ -98,29 +100,23 @@ export class SASViyaApiClient {
* Returns all available compute contexts on this server.
* @param accessToken - an access token for an authorized user.
*/
public async getAllContexts(accessToken?: string) {
const headers: any = {
'Content-Type': 'application/json'
}
public async getComputeContexts(accessToken?: string) {
return await this.contextManager.getComputeContexts(accessToken)
}
if (accessToken) {
headers.Authorization = `Bearer ${accessToken}`
}
/**
* Returns default(system) compute contexts.
*/
public getDefaultComputeContexts() {
return this.contextManager.getDefaultComputeContexts
}
const { result: contexts } = await this.request<{ items: Context[] }>(
`${this.serverUrl}/compute/contexts?limit=10000`,
{ headers }
)
const contextsList = contexts && contexts.items ? contexts.items : []
return contextsList.map((context: any) => ({
createdBy: context.createdBy,
id: context.id,
name: context.name,
version: context.version,
attributes: {}
}))
/**
* Returns all available launcher contexts on this server.
* @param accessToken - an access token for an authorized user.
*/
public async getLauncherContexts(accessToken?: string) {
return await this.contextManager.getLauncherContexts(accessToken)
}
/**
@@ -128,74 +124,12 @@ export class SASViyaApiClient {
* @param accessToken - an access token for an authorized user.
*/
public async getExecutableContexts(accessToken?: string) {
const headers: any = {
'Content-Type': 'application/json'
}
const bindedExecuteScript = this.executeScript.bind(this)
if (accessToken) {
headers.Authorization = `Bearer ${accessToken}`
}
const { result: contexts } = await this.request<{ items: Context[] }>(
`${this.serverUrl}/compute/contexts?limit=10000`,
{ headers }
).catch((err) => {
throw err
})
const contextsList = contexts.items || []
const executableContexts: any[] = []
const promises = contextsList.map((context: any) => {
const linesOfCode = ['%put &=sysuserid;']
return () =>
this.executeScript(
`test-${context.name}`,
linesOfCode,
context.name,
accessToken,
null,
false,
true,
true
).catch((err) => err)
})
let results: any[] = []
for (const promise of promises) results.push(await promise())
results.forEach((result: any, index: number) => {
if (result && result.log) {
try {
const resultParsed = result.log
let sysUserId = ''
const sysUserIdLog = resultParsed
.split('\n')
.find((line: string) => line.startsWith('SYSUSERID='))
if (sysUserIdLog) {
sysUserId = sysUserIdLog.replace('SYSUSERID=', '')
executableContexts.push({
createdBy: contextsList[index].createdBy,
id: contextsList[index].id,
name: contextsList[index].name,
version: contextsList[index].version,
attributes: {
sysUserId
}
})
}
} catch (error) {
throw error
}
}
})
return executableContexts
return await this.contextManager.getExecutableContexts(
bindedExecuteScript,
accessToken
)
}
/**
@@ -248,7 +182,7 @@ export class SASViyaApiClient {
* @param accessToken - an access token for an authorized user.
* @param authorizedUsers - an optional list of authorized user IDs.
*/
public async createContext(
public async createComputeContext(
contextName: string,
launchContextName: string,
sharedAccountId: string,
@@ -256,59 +190,35 @@ export class SASViyaApiClient {
accessToken?: string,
authorizedUsers?: string[]
) {
if (!contextName) {
throw new Error('Context name is required.')
}
if (!launchContextName) {
throw new Error('Launch context name is required.')
}
if (!sharedAccountId) {
throw new Error('Shared account ID is required.')
}
const headers: any = {
'Content-Type': 'application/json'
}
if (accessToken) {
headers.Authorization = `Bearer ${accessToken}`
}
const requestBody: any = {
name: contextName,
launchContext: {
contextName: launchContextName
},
attributes: {
reuseServerProcesses: true,
runServerAs: sharedAccountId
}
}
if (authorizedUsers && authorizedUsers.length) {
requestBody['authorizedUsers'] = authorizedUsers
} else {
requestBody['authorizeAllAuthenticatedUsers'] = true
}
if (autoExecLines) {
requestBody.environment = { autoExecLines }
}
const createContextRequest: RequestInit = {
method: 'POST',
headers,
body: JSON.stringify(requestBody)
}
const { result: context } = await this.request<Context>(
`${this.serverUrl}/compute/contexts`,
createContextRequest
return await this.contextManager.createComputeContext(
contextName,
launchContextName,
sharedAccountId,
autoExecLines,
accessToken,
authorizedUsers
)
}
return context
/**
* Creates a launcher context on the given server.
* @param contextName - the name of the context to be created.
* @param description - the description of the context to be created.
* @param launchType - launch type of the context to be created.
* @param accessToken - an access token for an authorized user.
*/
public async createLauncherContext(
contextName: string,
description: string,
launchType = 'direct',
accessToken?: string
) {
return await this.contextManager.createLauncherContext(
contextName,
description,
launchType,
accessToken
)
}
/**
@@ -317,75 +227,15 @@ export class SASViyaApiClient {
* @param editedContext - an object with the properties to be updated.
* @param accessToken - an access token for an authorized user.
*/
public async editContext(
public async editComputeContext(
contextName: string,
editedContext: EditContextInput,
accessToken?: string
) {
if (!contextName) {
throw new Error('Invalid context name.')
}
const headers: any = {
'Content-Type': 'application/json'
}
if (accessToken) {
headers.Authorization = `Bearer ${accessToken}`
}
let originalContext
originalContext = await this.getComputeContextByName(
return await this.contextManager.editComputeContext(
contextName,
editedContext,
accessToken
).catch((err) => {
throw err
})
// Try to find context by id, when context name has been changed.
if (!originalContext) {
originalContext = await this.getComputeContextById(
editedContext.id!,
accessToken
).catch((err) => {
throw err
})
}
const { result: context, etag } = await this.request<Context>(
`${this.serverUrl}/compute/contexts/${originalContext.id}`,
{
headers
}
).catch((err) => {
if (err && err.status === 404) {
throw new Error(
`The context '${contextName}' was not found on this server.`
)
}
throw err
})
// An If-Match header with the value of the last ETag for the context
// is required to be able to update it
// https://developer.sas.com/apis/rest/Compute/#update-a-context-definition
headers['If-Match'] = etag
const updateContextRequest: RequestInit = {
method: 'PUT',
headers,
body: JSON.stringify({
...context,
...editedContext,
attributes: { ...context.attributes, ...editedContext.attributes }
})
}
return await this.request<Context>(
`${this.serverUrl}/compute/contexts/${context.id}`,
updateContextRequest
)
}
@@ -394,29 +244,10 @@ export class SASViyaApiClient {
* @param contextName - the name of the context to be deleted.
* @param accessToken - an access token for an authorized user.
*/
public async deleteContext(contextName: string, accessToken?: string) {
if (!contextName) {
throw new Error('Invalid context name.')
}
const headers: any = {
'Content-Type': 'application/json'
}
if (accessToken) {
headers.Authorization = `Bearer ${accessToken}`
}
const context = await this.getComputeContextByName(contextName, accessToken)
const deleteContextRequest: RequestInit = {
method: 'DELETE',
headers
}
return await this.request<Context>(
`${this.serverUrl}/compute/contexts/${context.id}`,
deleteContextRequest
public async deleteComputeContext(contextName: string, accessToken?: string) {
return await this.contextManager.deleteComputeContext(
contextName,
accessToken
)
}
@@ -1451,26 +1282,10 @@ export class SASViyaApiClient {
contextName: string,
accessToken?: string
): Promise<Context> {
const headers: any = {
'Content-Type': 'application/json'
}
if (accessToken) {
headers.Authorization = `Bearer ${accessToken}`
}
const { result: contexts } = await this.request<{ items: Context[] }>(
`${this.serverUrl}/compute/contexts?filter=eq(name, "${contextName}")`,
{ headers }
return await this.contextManager.getComputeContextByName(
contextName,
accessToken
)
if (!contexts || !(contexts.items && contexts.items.length)) {
throw new Error(
`The context '${contextName}' was not found at '${this.serverUrl}'.`
)
}
return contexts.items[0]
}
/**
@@ -1482,22 +1297,10 @@ export class SASViyaApiClient {
contextId: string,
accessToken?: string
): Promise<ContextAllAttributes> {
const headers: any = {
'Content-Type': 'application/json'
}
if (accessToken) {
headers.Authorization = `Bearer ${accessToken}`
}
const { result: context } = await this.request<ContextAllAttributes>(
`${this.serverUrl}/compute/contexts/${contextId}`,
{ headers }
).catch((err) => {
throw err
})
return context
return await this.contextManager.getComputeContextById(
contextId,
accessToken
)
}
/**