Skip to content

Commit

Permalink
#38: ensure fixKeys also re-schedules if the deployed automation was …
Browse files Browse the repository at this point in the history
…scheduled already
  • Loading branch information
JoernBerkefeld committed Aug 3, 2023
1 parent 0b61fbf commit 2f9e54b
Show file tree
Hide file tree
Showing 6 changed files with 202 additions and 24 deletions.
5 changes: 3 additions & 2 deletions docs/dist/documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ Provides default functionality that can be overwritten by child metadata type cl
<dt><a href="#Automation.">Automation.(metadataMap, key)</a> ⇒ <code>Promise.&lt;void&gt;</code></dt>
<dd><p>helper for <a href="#Automation.postDeployTasks">postDeployTasks</a></p>
</dd>
<dt><a href="#Automation.">Automation.(metadataMap, originalMetadataMap, key)</a> ⇒ <code>Promise.&lt;{key:string, response:object}&gt;</code></dt>
<dt><a href="#Automation.">Automation.(metadataMap, originalMetadataMap, key, [oldKey])</a> ⇒ <code>Promise.&lt;{key:string, response:object}&gt;</code></dt>
<dd><p>helper for <a href="#Automation.postDeployTasks">postDeployTasks</a></p>
</dd>
<dt><a href="#getUserName">getUserName(userList, item, fieldname)</a> ⇒ <code>string</code></dt>
Expand Down Expand Up @@ -8526,7 +8526,7 @@ helper for [postDeployTasks](#Automation.postDeployTasks)

<a name="Automation."></a>

## Automation.(metadataMap, originalMetadataMap, key) ⇒ <code>Promise.&lt;{key:string, response:object}&gt;</code>
## Automation.(metadataMap, originalMetadataMap, key, [oldKey]) ⇒ <code>Promise.&lt;{key:string, response:object}&gt;</code>
helper for [postDeployTasks](#Automation.postDeployTasks)

**Kind**: global function
Expand All @@ -8537,6 +8537,7 @@ helper for [postDeployTasks](#Automation.postDeployTasks)
| metadataMap | <code>TYPE.AutomationMap</code> | metadata mapped by their keyField |
| originalMetadataMap | <code>TYPE.AutomationMap</code> | metadata to be updated (contains additioanl fields) |
| key | <code>string</code> | current customer key |
| [oldKey] | <code>string</code> | old customer key before fixKey / changeKeyValue / changeKeyField |

<a name="getUserName"></a>

Expand Down
54 changes: 33 additions & 21 deletions lib/metadataTypes/Automation.js
Original file line number Diff line number Diff line change
Expand Up @@ -878,6 +878,16 @@ class Automation extends MetadataType {
}
return deployable;
}
/**
* helper for {@link MetadataType.updateREST} and {@link MetadataType.updateSOAP} that removes old files after the key was changed
*
* @private
* @param {TYPE.MetadataTypeItem} metadataEntry a single metadata Entry
* @returns {void}
*/
static async _postChangeKeyTasks(metadataEntry) {
super._postChangeKeyTasks(metadataEntry, true);
}

/**
* Gets executed after deployment of metadata type
Expand All @@ -888,21 +898,25 @@ class Automation extends MetadataType {
*/
static async postDeployTasks(metadataMap, originalMetadataMap) {
for (const key in metadataMap) {
if (!metadataMap[key].type) {
const item = metadataMap[key];

const oldKey = Util.changedKeysMap?.[this.definition.type]?.[key] || key;
delete Util.changedKeysMap?.[this.definition.type]?.[key];

if (!item.type) {
// create response does not return the type attribute

const scheduleHelper =
metadataMap[key].schedule || metadataMap[key].startSource.schedule;
const scheduleHelper = item.schedule || item.startSource.schedule;

// el.type
metadataMap[key].type = scheduleHelper
item.type = scheduleHelper
? 'scheduled'
: metadataMap[key].fileTrigger
: item.fileTrigger
? 'triggered'
: undefined;

// el.schedule.timezoneName
if (metadataMap[key].type === 'scheduled') {
if (item.type === 'scheduled') {
// not existing for triggered automations
scheduleHelper.timezoneName ||= Util.inverseGet(
this.definition.timeZoneMapping,
Expand All @@ -911,21 +925,17 @@ class Automation extends MetadataType {
}

// el.status
metadataMap[key].status ||= Util.inverseGet(
this.definition.statusMapping,
metadataMap[key].statusId
);
item.status ||= Util.inverseGet(this.definition.statusMapping, item.statusId);
}
// need to put schedule on here if status is scheduled
await Automation.#scheduleAutomation(metadataMap, originalMetadataMap, key);
await Automation.#scheduleAutomation(metadataMap, originalMetadataMap, key, oldKey);

// need to update notifications separately if there are any
await Automation.#updateNotificationInfoREST(metadataMap, key);

// rewrite upsert to retrieve fields
const metadata = metadataMap[key];
if (metadata.steps) {
for (const step of metadata.steps) {
if (item.steps) {
for (const step of item.steps) {
step.name = step.annotation;
delete step.annotation;
}
Expand Down Expand Up @@ -989,19 +999,21 @@ class Automation extends MetadataType {
* @param {TYPE.AutomationMap} metadataMap metadata mapped by their keyField
* @param {TYPE.AutomationMap} originalMetadataMap metadata to be updated (contains additioanl fields)
* @param {string} key current customer key
* @param {string} [oldKey] old customer key before fixKey / changeKeyValue / changeKeyField
* @returns {Promise.<{key:string, response:object}>} metadata key and API response
*/
static async #scheduleAutomation(metadataMap, originalMetadataMap, key) {
static async #scheduleAutomation(metadataMap, originalMetadataMap, key, oldKey) {
let response = null;
if (originalMetadataMap[key]?.type === 'scheduled') {
oldKey ||= key;
if (originalMetadataMap[oldKey]?.type === 'scheduled') {
// Starting Source == 'Schedule': Try starting the automation
if (originalMetadataMap[key].status === 'Scheduled') {
if (originalMetadataMap[oldKey].status === 'Scheduled') {
let schedule = null;
try {
schedule = this._buildSchedule(originalMetadataMap[key].schedule);
schedule = this._buildSchedule(originalMetadataMap[oldKey].schedule);
} catch (ex) {
Util.logger.error(
`- Could not create schedule for automation '${originalMetadataMap[key].name}' to start it: ${ex.message}`
`- Could not create schedule for automation '${originalMetadataMap[oldKey].name}' to start it: ${ex.message}`
);
}
if (schedule !== null) {
Expand Down Expand Up @@ -1033,7 +1045,7 @@ class Automation extends MetadataType {
(schedule_interval > 1 ? 's' : ''));
Util.logger.warn(
` - scheduled automation '${
originalMetadataMap[key].name
originalMetadataMap[oldKey].name
}' deployed as Active: runs every ${intervalString} starting ${
schedule_StartDateTime.split('T').join(' ').split('.')[0]
} ${schedule_timezoneString}`
Expand All @@ -1048,7 +1060,7 @@ class Automation extends MetadataType {
} else {
Util.logger.info(
Util.getGrayMsg(
` - scheduled automation '${originalMetadataMap[key].name}' deployed as Paused`
` - scheduled automation '${originalMetadataMap[oldKey].name}' deployed as Paused`
)
);
}
Expand Down
45 changes: 45 additions & 0 deletions test/resources/9999999/automation/patch_fixKeys-expected.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"description": "updated on deploy",
"key": "testExisting_automation_paused",
"name": "testExisting_automation_paused",
"r__folder_Path": "my automations",
"schedule": {
"endDate": "2022-07-30T00:00:00",
"icalRecur": "FREQ=DAILY;COUNT=1;INTERVAL=1",
"startDate": "2022-07-30T00:00:00",
"timezoneName": "W. Europe Standard Time"
},
"status": "Scheduled",
"steps": [
{
"activities": [
{
"name": "testExisting_dataExtract",
"r__type": "dataExtract"
},
{
"name": "testExisting_emailSend",
"r__type": "emailSend"
},
{
"name": "testExisting_fileTransfer",
"r__type": "fileTransfer"
},
{
"name": "testExisting_importFile",
"r__type": "importFile"
},
{
"name": "testExisting_query",
"r__type": "query"
},
{
"name": "testExisting_script",
"r__type": "script"
}
],
"name": ""
}
],
"type": "scheduled"
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"id": "08afb0e2-b00a-4c88-ad2e-pause",
"name": "testExisting_automation_pause",
"name": "testExisting_automation_paused",
"description": "bla bla",
"key": "testExisting_automation_pause",
"typeId": 1,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
{
"legacyId": "RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow-PAUSED",
"name": "testExisting_automation_paused",
"description": "updated on deploy",
"key": "testExisting_automation_paused",
"typeId": 1,
"type": "scheduled",
"statusId": 4,
"status": "Scheduled",
"schedule": {
"id": "b393aa6c-a4a8-4c0f-a148-9250258a7339",
"typeId": 3,
"startDate": "2022-07-30T00:00:00",
"endDate": "2022-07-30T00:00:00",
"scheduledTime": "0001-01-01T07:00:00",
"rangeTypeId": 0,
"occurrences": 1,
"pattern": "<Pattern><PatternType>0</PatternType><DayInterval>1</DayInterval></Pattern>",
"icalRecur": "FREQ=DAILY;COUNT=1;INTERVAL=1",
"timezoneName": "W. Europe Standard Time",
"scheduleStatus": "scheduled",
"timezoneId": 5
},
"steps": [
{
"activities": [
{
"id": "8081a992-a27d-4a43-984a-d60114ea1025",
"name": "testExisting_dataExtract",
"activityObjectId": "56c5370a-f988-4f36-b0ee-0f876573f6d7",
"objectTypeId": 73,
"displayOrder": 1
},
{
"id": "d3774dc2-a271-4a44-8cbe-f630a6d6545e",
"name": "testExisting_emailSend",
"activityObjectId": "9b1c7bf9-4964-ed11-b849-48df37d1de8b",
"objectTypeId": 42,
"displayOrder": 2
},
{
"id": "2c77fc42-85eb-4611-98f9-223d29d89d72",
"name": "testExisting_fileTransfer",
"activityObjectId": "72c328ac-f5b0-4e37-91d3-a775666f15a6",
"objectTypeId": 53,
"displayOrder": 3
},
{
"id": "298b2794-28cb-4c70-b7ad-58b2c8cf48f7",
"name": "testExisting_importFile",
"activityObjectId": "9d16f42c-2260-ed11-b849-48df37d1de8b",
"objectTypeId": 43,
"displayOrder": 4,
"targetDataExtensions": [
{
"id": "21711373-72c1-ec11-b83b-48df37d1deb7",
"name": "testExisting_dataExtension",
"key": "testExisting_dataExtension",
"description": "bla bla",
"rowCount": 0
}
]
},
{
"id": "e3774dc2-a271-4a44-8cbe-f630a6d6545e",
"name": "testExisting_query_WRONG_NAME",
"activityObjectId": "549f0568-607c-4940-afef-437965094dat",
"objectTypeId": 300,
"displayOrder": 5
},
{
"id": "g3774dc2-a271-4a44-8cbe-f630a6d6545e",
"name": "testExisting_script",
"activityObjectId": "39f6a488-20eb-4ba0-b0b9-023725b574e4",
"objectTypeId": 423,
"displayOrder": 6
}
],
"annotation": "",
"stepNumber": 0
}
],
"categoryId": 290937,
"id": "08afb0e2-b00a-4c88-ad2e-1f7f8788c560"
}
35 changes: 35 additions & 0 deletions test/type.automation.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,41 @@ describe('type: automation', () => {
);
return;
});
it('Should fixKeys by key WITHOUT re-retrieving dependent types and schedule one automation', async () => {
// WHEN
handler.setOptions({ skipInteraction: { fixKeysReretrieve: false } });
const resultFixKeys = await handler.fixKeys('testInstance/testBU', 'automation', [
'testExisting_automation_pause',
'testExisting_automation',
]);
assert.equal(
resultFixKeys['testInstance/testBU'].length,
1,
'returned number of keys does not correspond to number of expected fixed keys'
);
assert.equal(
resultFixKeys['testInstance/testBU'][0],
'testExisting_automation_paused',
'returned keys do not correspond to expected fixed keys'
);
// THEN
assert.equal(process.exitCode, false, 'fixKeys should not have thrown an error');
// confirm updated item
assert.deepEqual(
await testUtils.getActualJson('testExisting_automation_paused', 'automation'),
await testUtils.getExpectedJson('9999999', 'automation', 'patch_fixKeys'),
'returned metadata was not equal expected for update automation'
);
expect(file(testUtils.getActualDoc('testExisting_automation_paused', 'automation'))).to
.exist;
// check number of API calls
assert.equal(
testUtils.getAPIHistoryLength(),
29,
'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests'
);
return;
});
});
describe('Templating ================', () => {
it('Should create a automation template via retrieveAsTemplate and build it', async () => {
Expand Down

0 comments on commit 2f9e54b

Please sign in to comment.