-
Notifications
You must be signed in to change notification settings - Fork 3
Make servicenow faster - more resilient #51
Changes from all commits
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 |
---|---|---|
|
@@ -122,20 +122,6 @@ export class ServiceNowClient { | |
const response = await this.request({ url }); | ||
const result = response?.data?.result; | ||
|
||
const redactedResponse = { | ||
status: response.status, | ||
statusText: response.statusText, | ||
headers: response.headers, | ||
responseLength: response.data?.['length'], | ||
responseType: typeof response.data, | ||
}; | ||
this.logger.info( | ||
{ | ||
redactedResponse, | ||
}, | ||
'Redacted response log', | ||
); | ||
|
||
if (Array.isArray(result)) { | ||
const nextLink = getServiceNowNextLink(response?.headers?.link); | ||
return { result, nextLink }; | ||
|
@@ -206,18 +192,13 @@ export class ServiceNowClient { | |
>(url); | ||
|
||
// For some reason Servicenow API sometimes have string responses for paginated endpoints | ||
if (paginatedResponse?.result && Array.isArray(paginatedResponse.result)) { | ||
if ( | ||
paginatedResponse?.result && | ||
Array.isArray(paginatedResponse.result) | ||
) { | ||
for (const r of paginatedResponse.result) { | ||
await callback(r); | ||
} | ||
|
||
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. Removed log |
||
this.logger.info( | ||
{ | ||
resourceCount: paginatedResponse.result.length, | ||
resource: url, | ||
}, | ||
'Received resources for endpoint', | ||
); | ||
} | ||
url = paginatedResponse?.nextLink; | ||
} while (url); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,10 +13,6 @@ export const Steps = { | |
GROUP_MEMBERS: 'step-group-members', | ||
INCIDENTS: 'step-incidents', | ||
CMDB: 'step-cmdb', | ||
USER_OWNS_CMDB: 'step_user_owns_cmdb', | ||
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. Merged this 4 steps into the cmdb step to make the whole process faster |
||
USER_MANAGES_CMDB: 'step_user_manages_cmdb', | ||
GROUP_MANAGES_CMDB: 'step_group_manages_cmdb', | ||
CMDB_ASSIGNED_USER: 'step_cmdb_assigned_user', | ||
}; | ||
|
||
export const Entities = { | ||
|
@@ -49,6 +45,9 @@ export const Entities = { | |
_type: 'service_now_cmdb_object', | ||
_class: 'Configuration', | ||
disableClassMatch: true, | ||
indexMetadata: { | ||
enabled: false, | ||
}, | ||
}, | ||
}; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -153,7 +153,7 @@ exports[`createUserEntity 1`] = ` | |
"_type": "service_now_user", | ||
"active": true, | ||
"createdOn": 1600711037000, | ||
"displayName": "J1 Administrator", | ||
"displayName": "j1-administrator", | ||
"email": "[email protected]", | ||
"id": "5ccbba87db1310109d87a9954b9619db", | ||
"name": "J1 Administrator", | ||
|
Large diffs are not rendered by default.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,113 +35,80 @@ export async function fetchCMDB( | |
|
||
await client.iterateTableResources({ | ||
table: parent, | ||
limit: 3_000, | ||
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. Default for table api is 10_000 so the api is really good at handling large amounts of data. I bumped by x6 to be careful with our memory usage |
||
callback: async (resource: CMDBItem) => { | ||
const sysClassNames = [ | ||
resource.sys_class_name, | ||
...(await getAllParents(client, resource.sys_class_name, logger)), | ||
]; | ||
if (!jobState.hasKey(resource.sys_id)) { | ||
await jobState.addEntity(createCMDBEntity(resource, sysClassNames)); | ||
const cmdbEntity = createCMDBEntity(resource, sysClassNames); | ||
await jobState.addEntity(cmdbEntity); | ||
|
||
if ( | ||
cmdbEntity.managedBy && | ||
jobState.hasKey(cmdbEntity.managedBy as string) | ||
) { | ||
await jobState.addRelationship( | ||
createDirectRelationship({ | ||
_class: RelationshipClass.MANAGES, | ||
fromKey: cmdbEntity.managedBy as string, | ||
fromType: Entities.USER._type, | ||
toKey: cmdbEntity._key, | ||
toType: cmdbEntity._type, | ||
}), | ||
); | ||
} | ||
|
||
if ( | ||
cmdbEntity.ownedBy && | ||
jobState.hasKey(cmdbEntity.ownedBy as string) | ||
) { | ||
await jobState.addRelationship( | ||
createDirectRelationship({ | ||
_class: RelationshipClass.OWNS, | ||
fromKey: cmdbEntity.ownedBy as string, | ||
fromType: Entities.USER._type, | ||
toKey: cmdbEntity._key, | ||
toType: cmdbEntity._type, | ||
}), | ||
); | ||
} | ||
|
||
if ( | ||
cmdbEntity.managedByGroup && | ||
jobState.hasKey(cmdbEntity.managedByGroup as string) | ||
) { | ||
await jobState.addRelationship( | ||
createDirectRelationship({ | ||
_class: RelationshipClass.MANAGES, | ||
fromKey: cmdbEntity.managedByGroup as string, | ||
fromType: Entities.GROUP._type, | ||
toKey: cmdbEntity._key, | ||
toType: cmdbEntity._type, | ||
}), | ||
); | ||
} | ||
|
||
if ( | ||
cmdbEntity.assignedTo && | ||
jobState.hasKey(cmdbEntity.assignedTo as string) | ||
) { | ||
await jobState.addRelationship( | ||
createDirectRelationship({ | ||
_class: RelationshipClass.ASSIGNED, | ||
toKey: cmdbEntity.assignedTo as string, | ||
toType: Entities.USER._type, | ||
fromKey: cmdbEntity._key, | ||
fromType: cmdbEntity._type, | ||
}), | ||
); | ||
} | ||
} | ||
}, | ||
}); | ||
} | ||
export async function buildUserManagesCMDB( | ||
context: IntegrationStepExecutionContext<IntegrationConfig>, | ||
) { | ||
const { jobState } = context; | ||
await jobState.iterateEntities( | ||
{ _type: Entities.CMDB_OBJECT._type }, | ||
async (cmdbEntity) => { | ||
const userId = (cmdbEntity as any).managedBy; | ||
if (!userId) { | ||
return; | ||
} | ||
const userEntity = await jobState.findEntity(userId); | ||
if (userEntity) { | ||
await jobState.addRelationship( | ||
createDirectRelationship({ | ||
_class: RelationshipClass.MANAGES, | ||
from: userEntity, | ||
to: cmdbEntity, | ||
}), | ||
); | ||
} | ||
}, | ||
); | ||
} | ||
export async function buildUserOwnsCMDB( | ||
context: IntegrationStepExecutionContext<IntegrationConfig>, | ||
) { | ||
const { jobState } = context; | ||
await jobState.iterateEntities( | ||
{ _type: Entities.CMDB_OBJECT._type }, | ||
async (cmdbEntity) => { | ||
const userId = (cmdbEntity as any).ownedBy; | ||
if (!userId) { | ||
return; | ||
} | ||
const userEntity = await jobState.findEntity(userId); | ||
if (userEntity) { | ||
await jobState.addRelationship( | ||
createDirectRelationship({ | ||
_class: RelationshipClass.OWNS, | ||
from: userEntity, | ||
to: cmdbEntity, | ||
}), | ||
); | ||
} | ||
}, | ||
); | ||
} | ||
export async function buildGroupManagesCMDB( | ||
context: IntegrationStepExecutionContext<IntegrationConfig>, | ||
) { | ||
const { jobState } = context; | ||
await jobState.iterateEntities( | ||
{ _type: Entities.CMDB_OBJECT._type }, | ||
async (cmdbEntity) => { | ||
const groupId = (cmdbEntity as any).managedByGroup; | ||
if (!groupId) { | ||
return; | ||
} | ||
const groupEntity = await jobState.findEntity(groupId); | ||
if (groupEntity) { | ||
await jobState.addRelationship( | ||
createDirectRelationship({ | ||
_class: RelationshipClass.MANAGES, | ||
from: groupEntity, | ||
to: cmdbEntity, | ||
}), | ||
); | ||
} | ||
}, | ||
); | ||
} | ||
export async function buildCMDBAssignedUser( | ||
context: IntegrationStepExecutionContext<IntegrationConfig>, | ||
) { | ||
const { jobState } = context; | ||
await jobState.iterateEntities( | ||
{ _type: Entities.CMDB_OBJECT._type }, | ||
async (cmdbEntity) => { | ||
const userId = (cmdbEntity as any).assignedTo; | ||
if (!userId) { | ||
return; | ||
} | ||
const userEntity = await jobState.findEntity(userId); | ||
if (userEntity) { | ||
await jobState.addRelationship( | ||
createDirectRelationship({ | ||
_class: RelationshipClass.ASSIGNED, | ||
from: cmdbEntity, | ||
to: userEntity, | ||
}), | ||
); | ||
} | ||
}, | ||
); | ||
} | ||
|
||
async function getAllParents( | ||
client: ServiceNowClient, | ||
sysClassName: string, | ||
|
@@ -198,44 +165,14 @@ export const cmdbIntegrationSteps: Step< | |
ingestionSourceId: IngestionSources.CMDB_ITEMS, | ||
name: 'CMDB Items', | ||
entities: [Entities.CMDB_OBJECT], | ||
relationships: [], | ||
relationships: [ | ||
Relationships.USER_MANAGES_CMDB, | ||
Relationships.USER_OWNS_CMDB, | ||
Relationships.CMDB_ASSIGNED_TO_USER, | ||
Relationships.GROUP_MANAGES_CMDB, | ||
], | ||
dependsOn: [], | ||
dependencyGraphId: 'last', | ||
executionHandler: fetchCMDB, | ||
}, | ||
{ | ||
id: Steps.USER_MANAGES_CMDB, | ||
ingestionSourceId: IngestionSources.CMDB_ITEMS, | ||
name: 'Build user manages CMDB', | ||
entities: [], | ||
relationships: [Relationships.USER_MANAGES_CMDB], | ||
dependsOn: [Steps.CMDB, Steps.USERS], | ||
executionHandler: buildUserManagesCMDB, | ||
}, | ||
{ | ||
id: Steps.USER_OWNS_CMDB, | ||
ingestionSourceId: IngestionSources.CMDB_ITEMS, | ||
name: 'Build user owns CMDB', | ||
entities: [], | ||
relationships: [Relationships.USER_OWNS_CMDB], | ||
dependsOn: [Steps.CMDB, Steps.USERS], | ||
executionHandler: buildUserOwnsCMDB, | ||
}, | ||
{ | ||
id: Steps.CMDB_ASSIGNED_USER, | ||
ingestionSourceId: IngestionSources.CMDB_ITEMS, | ||
name: 'CMDB assigned to user', | ||
entities: [], | ||
relationships: [Relationships.CMDB_ASSIGNED_TO_USER], | ||
dependsOn: [Steps.CMDB, Steps.USERS], | ||
executionHandler: buildCMDBAssignedUser, | ||
}, | ||
{ | ||
id: Steps.GROUP_MANAGES_CMDB, | ||
ingestionSourceId: IngestionSources.CMDB_ITEMS, | ||
name: 'Group manages CMDB', | ||
entities: [], | ||
relationships: [Relationships.GROUP_MANAGES_CMDB], | ||
dependsOn: [Steps.CMDB, Steps.GROUPS], | ||
executionHandler: buildGroupManagesCMDB, | ||
}, | ||
]; |
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.
Removed log