Skip to content

Commit

Permalink
Merge pull request #94 from mountaindude/85-task-id-lookup
Browse files Browse the repository at this point in the history
85 task id lookup
  • Loading branch information
mountaindude authored Sep 28, 2023
2 parents a1ca058 + 177c643 commit d60bb04
Show file tree
Hide file tree
Showing 9 changed files with 435 additions and 148 deletions.
5 changes: 2 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@

## [0.2.6](https://github.com/ptarmiganlabs/ctrl-q-nr/compare/v0.2.5...v0.2.6) (2023-09-18)


### Bug Fixes

* Pass-through of parts/reset message properties ([2db6663](https://github.com/ptarmiganlabs/ctrl-q-nr/commit/2db66632b36e968b5ab14e36d37a34da2d4cf769)), closes [#81](https://github.com/ptarmiganlabs/ctrl-q-nr/issues/81)
* **qseow:** Respect ignore-anauthorised-cert settings for all calls to QSEoW ([7427151](https://github.com/ptarmiganlabs/ctrl-q-nr/commit/7427151f8a9a0a9f4ec276b049b8f2cc184f0fc7))
- Pass-through of parts/reset message properties ([2db6663](https://github.com/ptarmiganlabs/ctrl-q-nr/commit/2db66632b36e968b5ab14e36d37a34da2d4cf769)), closes [#81](https://github.com/ptarmiganlabs/ctrl-q-nr/issues/81)
- **qseow:** Respect ignore-anauthorised-cert settings for all calls to QSEoW ([7427151](https://github.com/ptarmiganlabs/ctrl-q-nr/commit/7427151f8a9a0a9f4ec276b049b8f2cc184f0fc7))

## [0.2.5](https://github.com/ptarmiganlabs/ctrl-q-nr/compare/v0.2.4...v0.2.5) (2023-09-18)

Expand Down
216 changes: 108 additions & 108 deletions package-lock.json

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@
],
"dependencies": {
"@qlik/sdk": "^0.25.0",
"axios": "^1.5.0",
"axios": "^1.5.1",
"enigma.js": "^2.12.0",
"ws": "^8.14.1"
"ws": "^8.14.2"
},
"devDependencies": {
"esbuild": "^0.19.3",
"eslint": "^8.49.0",
"esbuild": "^0.19.4",
"eslint": "^8.50.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-prettier": "^9.0.0",
"eslint-formatter-table": "^7.32.1",
Expand Down
4 changes: 2 additions & 2 deletions src/lib/qseow/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -639,7 +639,7 @@ async function updateApps(node, apps) {
};
}

// Function to look up apo IDs given app names, colletion names or managed space names
// Function to look up apo IDs given app names, tag names or stream names
// Parameters:
// node: node object
// lookupSource: object containing entities to look up and translate into app IDs
Expand Down Expand Up @@ -725,7 +725,7 @@ async function lookupAppId(node, lookupSource) {

// Make sure we got an array
if (!uniqueAppIds || !Array.isArray(uniqueAppIds)) {
node.log('Error getting unique app IDs in lookupAppId');
node.error('Error getting unique app IDs in lookupAppId');
node.status({ fill: 'red', shape: 'ring', text: 'error getting unique app IDs' });
return false;
}
Expand Down
172 changes: 172 additions & 0 deletions src/lib/qseow/task.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,96 @@
const axios = require('axios');

const { getTaskTags } = require('./tag');
const { getAuth } = require('./auth');

// Function to get tasks from Qlik Sense server, based on task names
// Parameters:
// - node: the node object
// - taskNames: an array of task names
// Return: an object containing an array of task objects
async function getTasksByName(node, taskNames) {
// Make sure appNames is an array
if (!Array.isArray(taskNames)) {
node.status({ fill: 'red', shape: 'ring', text: 'error getting tasks by name' });
node.log(`Error getting tasks from Qlik Sense server: taskNames is not an array.`);
return null;
}

try {
// Set up authentication
const { axiosConfig, xref } = getAuth(node);

// Build url that can be used with QRS API. Quote task names with single quotes
axiosConfig.url = `/qrs/task/full?filter=name%20eq%20'${taskNames.join(`'%20or%20name%20eq%20'`)}'&xrfkey=${xref}`;

// Debug url
node.log(`URL: ${axiosConfig.url}`);

// Get tasks from Qlik Sense server
const response = await axios(axiosConfig);

// Ensure response status is 200
if (response.status !== 200) {
node.status({ fill: 'red', shape: 'ring', text: 'error getting tasks by name' });
node.log(`Error getting tasks from Qlik Sense server: ${response.status} ${response.statusText}`);
return null;
}

// Return object containing an array of task objects
return {
task: response.data,
};
} catch (err) {
// Log error
node.error(`Error when getting tasks by name: ${err}`);
return null;
}
}

// Function to get tasks from Qlik Sense server, based on tag names
// Parameters:
// - node: the node object
// - tagNames: an array of tag names
// Return: an object called "tag" containing an array of task objects
async function getTasksByTagName(node, tagNames) {
// Make sure tagNames is an array
if (!Array.isArray(tagNames)) {
node.status({ fill: 'red', shape: 'ring', text: 'error getting tasks by tag name' });
node.log(`Error getting tasks from Qlik Sense server: tagNames is not an array.`);
return null;
}

try {
// Set up authentication
const { axiosConfig, xref } = getAuth(node);

// Build url that can be used with QRS API. Quote task names with single quotes
axiosConfig.url = `/qrs/task/full?filter=tags.name%20eq%20'${tagNames.join(`'%20or%20tags.name%20eq%20'`)}'&xrfkey=${xref}`;

// Debug url
node.log(`URL: ${axiosConfig.url}`);

// Get tasks from Qlik Sense server
const response = await axios(axiosConfig);

// Ensure response status is 200
if (response.status !== 200) {
node.status({ fill: 'red', shape: 'ring', text: 'error getting tasks by tag name' });
node.log(`Error getting tasks from Qlik Sense server: ${response.status} ${response.statusText}`);
return null;
}

// Return object containing an array of task objects
return {
task: response.data,
};
} catch (err) {
// Log error
node.error(`Error when getting tasks by tag name: ${err}`);
return null;
}
}

// Function to start tasks on Qlik Sense server
// Parameters:
// - node: the node object
Expand Down Expand Up @@ -149,6 +238,89 @@ async function startTasks(node, done, taskIdsToStart) {
};
}

// Function to look up task IDs given task names or tag names
// Parameters:
// - node: the node object
// - lookupSource: object containing entities to look up and translate into task IDs

// Return
// Success: An object containing an array of unique task IDs and an array of unique task objects
// Failure: false
async function lookupTaskId(node, lookupSource) {
const allTaskIds = [];
const allTaskObjects = [];

// lookupSource.taskName is an array of task names
// Build filter string that can be used with QRS API
if (lookupSource.taskName) {
// Get tasks from Qlik Sense server
// Return a task property, which contains an array task objects
const resTasks = await getTasksByName(node, lookupSource.taskName);

// Make sure we got a response that contains the correct data
if (!resTasks || !resTasks.task || !Array.isArray(resTasks.task)) {
node.error('Error when getting tasks by name in lookupTaskIds()');
node.status({ fill: 'red', shape: 'ring', text: 'error getting tasks by name' });
return false;
}

// Loop through array of tasks and add task IDs to allTaskIds array
resTasks.task.forEach((task) => {
allTaskIds.push(task.id);
allTaskObjects.push(task);
});

// Debug
node.log(`allTaskIds: ${JSON.stringify(allTaskIds, null, 4)}`);
}

// lookupSource.tagName is an array of tag names
// Build filter string that can be used with QRS API
if (lookupSource.tagName) {
// Get tasks from Qlik Sense server, based on which tag names they have
const resTasks = await getTasksByTagName(node, lookupSource.tagName);

// Make sure we got a response that contains the correct data
if (!resTasks || !resTasks.task || !Array.isArray(resTasks.task)) {
node.error('Error when getting tasks by tag name in lookupTaskIds()');
node.status({ fill: 'red', shape: 'ring', text: 'error getting tasks by tag name' });
return false;
}

// Loop through array of tasks and add task IDs to allTaskIds array
resTasks.task.forEach((task) => {
allTaskIds.push(task.id);
allTaskObjects.push(task);
});
}

// Remove duplicates from allTaskIds array
const uniqueTaskIds = [...new Set(allTaskIds)];

// Get the task objects for the unique task IDs
const uniqueTaskObjects = [];

// Make sure we got an array
if (!uniqueTaskIds || !Array.isArray(uniqueTaskIds)) {
node.error('Error when getting unique task IDs in lookupTaskIds()');
node.status({ fill: 'red', shape: 'ring', text: 'error getting unique task IDs' });
return false;
}

// Loop through array of unique task IDs and get the task objects
uniqueTaskIds.forEach((taskId) => {
const taskObject = allTaskObjects.find((task) => task.id === taskId);
uniqueTaskObjects.push(taskObject);
});

// Return object containing unique task IDs and unique task objects
return {
uniqueTaskIds,
uniqueTaskObjects,
};
}

module.exports = {
startTasks,
lookupTaskId,
};
2 changes: 1 addition & 1 deletion src/qseow/qseow-app-nr.html
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@
<li><strong>Read:</strong> Read metadata for one or more apps.</li>
<li><strong>Update:</strong> Update metadata for one or more apps.</li>
<li><strong>Delete:</strong> Delete one or more apps.</li>
<li><b>App ID lookup</b> - Lookup all app IDs associated with specified apps or spaces.</li>
<li><b>App ID lookup</b> - Lookup all app IDs associated with specified apps, tags etc.</li>
<li><strong>Duplicate:</strong> Duplicate one or more apps.</li>
<li><strong>Get reload script:</strong> Get the reload script for one or more apps.</li>
<li><strong>Set reload script:</strong> Set the reload script for one or more apps.</li>
Expand Down
13 changes: 6 additions & 7 deletions src/qseow/qseow-app-nr.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable no-underscore-dangle */
const { getApps, deleteApps, duplicateApps, updateApps, getAppLoadScript, setAppLoadScript, lookupAppId } = require('../lib/qseow/app');
const { getCandidateAppsPredefAndIncoming } = require('../lib/qseow/appconfig');

Expand Down Expand Up @@ -284,10 +285,10 @@ module.exports = function (RED) {
return;
}

// If msg.payload.spaceName exists it should be an array
if (msg.payload.spaceName && !Array.isArray(msg.payload.spaceName)) {
node.status({ fill: 'red', shape: 'ring', text: 'msg.payload.spaceName is not an array' });
done('msg.payload.spaceName is not an array');
// If msg.payload.streamName exists it should be an array
if (msg.payload.streamName && !Array.isArray(msg.payload.streamName)) {
node.status({ fill: 'red', shape: 'ring', text: 'msg.payload.streamName is not an array' });
done('msg.payload.streamName is not an array');
return;
}

Expand All @@ -298,7 +299,7 @@ module.exports = function (RED) {
// Get app info from Qlik Sense server
const { uniqueAppIds, uniqueAppObjects } = await lookupAppId(node, msg.payload);

// Di we get any result in quniqueAppIds?
// Did we get any result in uniqueAppIds?
if (!uniqueAppIds || !Array.isArray(uniqueAppIds)) {
node.log('Error getting app IDs in lookupAppId');
node.status({ fill: 'red', shape: 'ring', text: 'error getting app IDs' });
Expand All @@ -320,9 +321,7 @@ module.exports = function (RED) {
if (msg.parts) {
outMsg1.parts = msg.parts;
}
// eslint-disable-next-line no-underscore-dangle
if (msg._msgid) {
// eslint-disable-next-line no-underscore-dangle
outMsg1._msgid = msg._msgid;
}
if (msg.reset) {
Expand Down
Loading

0 comments on commit d60bb04

Please sign in to comment.