From 000778e32b05d68860d24b3f90a16c7b04138bad Mon Sep 17 00:00:00 2001 From: Yuliia Likhytska Date: Thu, 3 Aug 2023 08:57:33 +0200 Subject: [PATCH] #984: added a function to update notifications for Automations --- docs/dist/documentation.md | 63 ++++++++++++----- lib/cli.js | 18 +++-- lib/index.js | 76 +++++++++++++++----- lib/metadataTypes/Automation.js | 118 ++++++++++++++++++++++++++++---- 4 files changed, 224 insertions(+), 51 deletions(-) diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md index 91a9d96b2..0c9648bd7 100644 --- a/docs/dist/documentation.md +++ b/docs/dist/documentation.md @@ -195,6 +195,8 @@ Provides default functionality that can be overwritten by child metadata type cl
Mcdev.(selectedType, buObject)Array.<string>

helper for Mcdev.#runOnBU

+
Mcdev.(cred, bu, type, [keys])Promise.<Array.<string>>
+
Automation.(metadata)boolean

helper for postRetrieveTasks and execute

@@ -216,6 +218,9 @@ Provides default functionality that can be overwritten by child metadata type cl
Automation.(metadataMap, originalMetadataMap, key)Promise.<{key:string, response:object}>

helper for postDeployTasks

+
Automation.()Promise.<Array.<string>>
+

helper function to retrieve data about all automations in the BU

+
getUserName(userList, item, fieldname)string
setupSDK(sessionKey, authObject)SDK
@@ -520,7 +525,7 @@ main class * [.execute(businessUnit, [selectedType], [keys])](#Mcdev.execute) ⇒ Promise.<Object.<string, Array.<string>>> * [.pause(businessUnit, [selectedType], [keys])](#Mcdev.pause) ⇒ Promise.<Object.<string, Array.<string>>> * [.fixKeys(businessUnit, type, [keys])](#Mcdev.fixKeys) ⇒ Promise.<Object.<string, Array.<string>>> - * [.setNotifEmailAddr(businessUnit, type, keys, emailFailed, emailComplete)](#Mcdev.setNotifEmailAddr) ⇒ Promise.<string> + * [.updateNotifications(businessUnit, type, [keys])](#Mcdev.updateNotifications) ⇒ Promise.<Object.<string, Array.<string>>> @@ -828,18 +833,19 @@ Updates the key to match the name field | type | TYPE.SupportedMetadataTypes | limit execution to given metadata type | | [keys] | Array.<string> | customerkey of the metadata | - + + +### Mcdev.updateNotifications(businessUnit, type, [keys]) ⇒ Promise.<Object.<string, Array.<string>>> +Updates notification email address field -### Mcdev.setNotifEmailAddr(businessUnit, type, keys, emailFailed, emailComplete) ⇒ Promise.<string> **Kind**: static method of [Mcdev](#Mcdev) +**Returns**: Promise.<Object.<string, Array.<string>>> - key: business unit name, value: list of affected item keys -| Param | Type | -| --- | --- | -| businessUnit | \* | -| type | \* | -| keys | \* | -| emailFailed | \* | -| emailComplete | \* | +| Param | Type | Description | +| --- | --- | --- | +| businessUnit | string | name of BU | +| type | TYPE.SupportedMetadataTypes | limit execution to given metadata type | +| [keys] | Array.<string> | customerkey of the metadata | @@ -1398,7 +1404,7 @@ Automation MetadataType * [.getFilesToCommit(keyArr)](#Automation.getFilesToCommit) ⇒ Array.<string> * [.deleteByKey(customerKey)](#Automation.deleteByKey) ⇒ boolean * [.postDeleteTasks(customerKey)](#Automation.postDeleteTasks) ⇒ void - * [.setNotifEmailAddr(keys, emailFailed, emailComplete)](#Automation.setNotifEmailAddr) ⇒ string + * [.updateNotifications(keys)](#Automation.updateNotifications) ⇒ Promise.<Array.<string>> @@ -1665,16 +1671,17 @@ clean up after deleting a metadata item | --- | --- | --- | | customerKey | string | Identifier of metadata item | - + + +### Automation.updateNotifications(keys) ⇒ Promise.<Array.<string>> +A function to update automation email notifications -### Automation.setNotifEmailAddr(keys, emailFailed, emailComplete) ⇒ string **Kind**: static method of [Automation](#Automation) +**Returns**: Promise.<Array.<string>> - keys of the automations where notifications were updated -| Param | Type | -| --- | --- | -| keys | \* | -| emailFailed | \* | -| emailComplete | \* | +| Param | Type | Description | +| --- | --- | --- | +| keys | string | metadata keys | @@ -8503,6 +8510,19 @@ helper for [Mcdev.#runOnBU](Mcdev.#runOnBU) | selectedType | TYPE.SupportedMetadataTypes | limit execution to given metadata type | | buObject | TYPE.BuObject | properties for auth | + + +## Mcdev.(cred, bu, type, [keys]) ⇒ Promise.<Array.<string>> +**Kind**: global function +**Returns**: Promise.<Array.<string>> - keys of the automations where notifications were updated + +| Param | Type | Description | +| --- | --- | --- | +| cred | string | name of Credential | +| bu | string | name of BU | +| type | string | metadata type | +| [keys] | Array.<string> | limit retrieval to given metadata keys | + ## Automation.(metadata) ⇒ boolean @@ -8590,6 +8610,13 @@ helper for [postDeployTasks](#Automation.postDeployTasks) | originalMetadataMap | TYPE.AutomationMap | metadata to be updated (contains additioanl fields) | | key | string | current customer key | + + +## Automation.() ⇒ Promise.<Array.<string>> +helper function to retrieve data about all automations in the BU + +**Kind**: global function +**Returns**: Promise.<Array.<string>> - returns data about automations with the legacy key ## getUserName(userList, item, fieldname) ⇒ string diff --git a/lib/cli.js b/lib/cli.js index 13a298f16..eca03ad9d 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -544,9 +544,9 @@ yargs }, }) .command({ - command: 'setNotifEmailAddr [KEY]', - aliases: ['setNotif'], - desc: 'bulk updates notificaiton email addresses', + command: 'updateNotifications [KEY]', + aliases: ['updNotif'], + desc: 'bulk updates notification email addresses', builder: (yargs) => { yargs .positional('BU', { @@ -561,7 +561,7 @@ yargs type: 'string', describe: 'key(s) of the metadata component(s)', }) - .positional('emailFailed', { + .positional('emailError', { type: 'string', describe: 'email to notify that an error occured during execution', }) @@ -569,6 +569,14 @@ yargs type: 'string', describe: 'email to notify about successfull completion', }) + .positional('errorNote', { + type: 'string', + describe: 'run error note', + }) + .positional('completionNote', { + type: 'string', + describe: 'run completion note', + }) .option('like', { type: 'string', group: 'Options for update notification email address:', @@ -579,7 +587,7 @@ yargs handler: (argv) => { Mcdev.setOptions(argv); // ! do not allow multiple types to be passed in here via csvToArray - Mcdev.setNotifEmailAddr(argv.BU, argv.TYPE, csvToArray(argv.KEY)); + Mcdev.updateNotifications(argv.BU, argv.TYPE, csvToArray(argv.KEY)); }, }) .command({ diff --git a/lib/index.js b/lib/index.js index a70191386..0e94d205f 100644 --- a/lib/index.js +++ b/lib/index.js @@ -64,8 +64,10 @@ class Mcdev { 'refresh', 'schedule', 'skipInteraction', - 'emailFailed', + 'emailError', 'emailComplete', + 'errorNote', + 'completionNote', ]; for (const option of knownOptions) { if (argv[option] !== undefined) { @@ -1129,41 +1131,83 @@ class Mcdev { return result; } /** + * Updates notification email address field * - * @param {*} businessUnit - * @param {*} type - * @param {*} keys - * @param {*} emailFailed - * @param {*} emailComplete - * @returns {Promise.} + * @param {string} businessUnit name of BU + * @param {TYPE.SupportedMetadataTypes} type limit execution to given metadata type + * @param {string[]} [keys] customerkey of the metadata + * @returns {Promise.>} key: business unit name, value: list of affected item keys */ - static async setNotifEmailAddr(businessUnit, type, keys, emailFailed, emailComplete) { - let [cred, bu] = businessUnit ? businessUnit.split('/') : [null, null]; + static async updateNotifications(businessUnit, type, keys) { + const [cred, bu] = businessUnit ? businessUnit.split('/') : [null, null]; + if (Util.OPTIONS.emailComplete == null && Util.OPTIONS.emailError == null) { + Util.logger.error(`No email addresses were provided`); + return null; + } const properties = await config.getProperties(); + const resultsObj = {}; + if (bu === '*') { + Util.logger.info(':: Updating notifications on all BUs for all credentials'); + let counter_credTotal = 0; + for (const cred in properties.credentials) { + Util.logger.info(`:: Updating notifications on BUs for ${cred}`); + let counter_credBu = 0; + for (const bu in properties.credentials[cred].businessUnits) { + resultsObj[`${cred}/${bu}`] = await this.#updateNotificationsBU( + cred, + bu, + type, + keys + ); + counter_credBu++; + Util.startLogger(true); + } + counter_credTotal += counter_credBu; + Util.logger.info(`:: ${counter_credBu} BUs of ${cred}\n`); + } + Util.logger.info(`:: Updated notifications on ${counter_credTotal} BUs of ${cred}\n`); + } else { + resultsObj[`${cred}/${bu}`] = await this.#updateNotificationsBU(cred, bu, type, keys); + } + + return resultsObj; + } + /** + * + * @param {string} cred name of Credential + * @param {string} bu name of BU + * @param {string} type metadata type + * @param {string[]} [keys] limit retrieval to given metadata keys + * @returns {Promise.} keys of the automations where notifications were updated + */ + static async #updateNotificationsBU(cred, bu, type, keys) { + const properties = await config.getProperties(); + if (!(await config.checkProperties(properties))) { + return null; + } const buObject = await Cli.getCredentialObject( properties, cred === null ? null : cred + '/' + bu, null, true ); - Util.logger.info(`${emailFailed} ${emailComplete}`); if (buObject !== null) { cache.initCache(buObject); cred = buObject.credential; bu = buObject.businessUnit; } - Util.logger.info( - `Setting notification email address for ${type} on ${cred}/${bu}` + - (keys ? Util.getKeysString(keys) : '') + - `\n` - ); try { MetadataTypeInfo[type].client = auth.getSDK(buObject); } catch (ex) { Util.logger.error(ex.message); return null; } - return await MetadataTypeInfo[type].setNotifEmailAddr(keys, emailFailed, emailComplete); + Util.logger.info( + `Setting notification email address of type ${type} on ${cred}/${bu}` + + (keys ? Util.getKeysString(keys) : '') + + `\n` + ); + return await MetadataTypeInfo[type].updateNotifications(keys); } } diff --git a/lib/metadataTypes/Automation.js b/lib/metadataTypes/Automation.js index 059a42e47..bb4dd54a9 100644 --- a/lib/metadataTypes/Automation.js +++ b/lib/metadataTypes/Automation.js @@ -1559,20 +1559,114 @@ class Automation extends MetadataType { await super.postDeleteTasks(customerKey, [`${this.definition.type}-doc.md`]); } /** + * helper function to retrieve data about all automations in the BU * - * @param {*} keys - * @param {*} emailFailed - * @param {*} emailComplete - * @returns {string} + * @returns {Promise.} returns data about automations with the legacy key */ - static async setNotifEmailAddr(keys, emailFailed, emailComplete) { - Util.logger.info(`Setting notification email address`); - await this.retrieve(undefined, undefined, undefined, keys); - Util.logger.info(`${emailFailed} ${emailComplete}`); - // this.#updateNotificationInfoREST(); //[ { email: [ 'test@test.com' ], message: '', type: 'Error' } ] - // results.metadata[key].notifications[0].email = Util..; - // await this.#updateNotificationInfoREST(); - return null; + static async #getEncodedAutomationIDs() { + const keyBackup = this.definition.keyField; + const iteratorBackup = this.definition.bodyIteratorField; + this.definition.keyField = 'key'; + this.definition.bodyIteratorField = 'entry'; + const automationLegacyKeys = await super.retrieveREST( + undefined, + `/legacy/v1/beta/bulk/automations/automation/definition/` + ); + this.definition.keyField = keyBackup; + this.definition.bodyIteratorField = iteratorBackup; + return automationLegacyKeys; + } + /** + * A function to update automation email notifications + * + * @param {string} keys metadata keys + * @returns {Promise.} keys of the automations where notifications were updated + */ + static async updateNotifications(keys) { + const emailComplete = Array.isArray(Util.OPTIONS.emailComplete) + ? Util.OPTIONS.emailComplete.join(',') + : Util.OPTIONS.emailComplete; + const emailError = Array.isArray(Util.OPTIONS.emailError) + ? Util.OPTIONS.emailError.join(',') + : Util.OPTIONS.emailError; + const updatedKeys = []; + let notificationsResult; + const automationLegacyMapObj = await this.#getEncodedAutomationIDs(); // retrieve automation legacy keys to update notifications + for (const key of Object.keys(automationLegacyMapObj.metadata)) { + if (Array.isArray(keys) && keys.includes(key)) { + try { + notificationsResult = await this.client.rest.get( + '/legacy/v1/beta/automations/notifications/' + + automationLegacyMapObj.metadata[key].id + ); + } catch (ex) { + Util.logger.error( + `Error retrieving notifications for automation '${key}': ${ex.message} (${ex.code}))` + ); + } + // if the parameters provided are the same as the email addresses/notes already in the notifications - skip this automation + if ( + notificationsResult.workers.find( + (notification) => + (notification.notificationType === 'Complete' && + (emailComplete !== notification.definition || + Util.OPTIONS.completionNote !== notification.body)) || + notificationsResult.workers.find( + (notification) => + notification.notificationType === 'Error' && + (emailError !== notification.definition || + Util.OPTIONS.errorNote !== notification.body) + ) + ) + ) { + // create payload + const notificationBody = { + programId: automationLegacyMapObj.metadata[key].id, + workers: [ + { + programId: automationLegacyMapObj.metadata[key].id, + notificationType: 'Complete', + definition: emailComplete, + body: Util.OPTIONS.completionNote, + channelType: 'Account', + }, + { + programId: automationLegacyMapObj.metadata[key].id, + notificationType: 'Error', + definition: emailError, + body: Util.OPTIONS.errorNote, + channelType: 'Account', + }, + ], + }; + try { + const result = await this.client.rest.post( + '/legacy/v1/beta/automations/notifications/' + + automationLegacyMapObj.metadata[key].id, + notificationBody + ); + if (result) { + // should be empty if all OK + throw new Error(result); + } + updatedKeys.push(key); + } catch (ex) { + Util.logger.error( + `Error updating notifications for automation '${key}': ${ex.message} (${ex.code}))` + ); + } + Util.logger.info( + Util.getGrayMsg(` - updated notifications for automation '${key}'`) + ); + } else { + Util.logger.info( + ` ☇ skipping automation '${key}' - email addresses provided and run notes are the same` + ); + return; + } + } + } + return updatedKeys; } }