Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/38 add fixKeys command - added multi-BU support #1062

Merged
merged 8 commits into from
Aug 1, 2023
30 changes: 24 additions & 6 deletions docs/dist/documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,9 @@ Provides default functionality that can be overwritten by child metadata type cl
<dt><a href="#Mcdev.">Mcdev.(selectedType, buObject)</a> ⇒ <code>Array.&lt;string&gt;</code></dt>
<dd><p>helper for <a href="Mcdev.#runOnBU">Mcdev.#runOnBU</a></p>
</dd>
<dt><a href="#Mcdev.">Mcdev.(cred, bu, type, [keyArr])</a> ⇒ <code>Promise.&lt;Array.&lt;string&gt;&gt;</code></dt>
<dd><p>Updates the key to match the name field</p>
</dd>
<dt><a href="#Automation.">Automation.(metadata)</a> ⇒ <code>boolean</code></dt>
<dd><p>helper for <a href="#Automation.postRetrieveTasks">postRetrieveTasks</a> and <a href="#Automation.execute">execute</a></p>
</dd>
Expand Down Expand Up @@ -519,7 +522,7 @@ main class
* [.schedule(businessUnit, [selectedType], [keys])](#Mcdev.schedule) ⇒ <code>Promise.&lt;Object.&lt;string, Array.&lt;string&gt;&gt;&gt;</code>
* [.execute(businessUnit, [selectedType], [keys])](#Mcdev.execute) ⇒ <code>Promise.&lt;Object.&lt;string, Array.&lt;string&gt;&gt;&gt;</code>
* [.pause(businessUnit, [selectedType], [keys])](#Mcdev.pause) ⇒ <code>Promise.&lt;Object.&lt;string, Array.&lt;string&gt;&gt;&gt;</code>
* [.fixKeys(businessUnit, type, [keys])](#Mcdev.fixKeys) ⇒ <code>Promise.&lt;Object.&lt;string, Array.&lt;string&gt;&gt;&gt;</code>
* [.fixKeys(businessUnit, selectedType, [keys])](#Mcdev.fixKeys) ⇒ <code>Promise.&lt;Object.&lt;string, Array.&lt;string&gt;&gt;&gt;</code>

<a name="Mcdev.setSkipInteraction"></a>

Expand Down Expand Up @@ -815,16 +818,16 @@ pause an item

<a name="Mcdev.fixKeys"></a>

### Mcdev.fixKeys(businessUnit, type, [keys]) ⇒ <code>Promise.&lt;Object.&lt;string, Array.&lt;string&gt;&gt;&gt;</code>
### Mcdev.fixKeys(businessUnit, selectedType, [keys]) ⇒ <code>Promise.&lt;Object.&lt;string, Array.&lt;string&gt;&gt;&gt;</code>
Updates the key to match the name field

**Kind**: static method of [<code>Mcdev</code>](#Mcdev)
**Returns**: <code>Promise.&lt;Object.&lt;string, Array.&lt;string&gt;&gt;&gt;</code> - key: business unit name, value: list of affected item keys
**Returns**: <code>Promise.&lt;Object.&lt;string, Array.&lt;string&gt;&gt;&gt;</code> - key: business unit name, value: list of paused item keys

| Param | Type | Description |
| --- | --- | --- |
| businessUnit | <code>string</code> | name of BU |
| type | <code>TYPE.SupportedMetadataTypes</code> | limit execution to given metadata type |
| selectedType | <code>TYPE.SupportedMetadataTypes</code> | limit to given metadata types |
| [keys] | <code>Array.&lt;string&gt;</code> | customerkey of the metadata |

<a name="Asset"></a>
Expand Down Expand Up @@ -8383,7 +8386,7 @@ run a method across BUs

| Param | Type | Description |
| --- | --- | --- |
| methodName | <code>&#x27;execute&#x27;</code> \| <code>&#x27;pause&#x27;</code> | what to run |
| methodName | <code>&#x27;execute&#x27;</code> \| <code>&#x27;pause&#x27;</code> \| <code>&#x27;fixKeys&#x27;</code> | what to run |
| businessUnit | <code>string</code> | name of BU |
| [selectedType] | <code>TYPE.SupportedMetadataTypes</code> | limit to given metadata types |
| [keys] | <code>Array.&lt;string&gt;</code> | customerkey of the metadata |
Expand All @@ -8398,7 +8401,7 @@ helper for [Mcdev.#runMethod](Mcdev.#runMethod)

| Param | Type | Description |
| --- | --- | --- |
| methodName | <code>&#x27;execute&#x27;</code> \| <code>&#x27;pause&#x27;</code> | what to run |
| methodName | <code>&#x27;execute&#x27;</code> \| <code>&#x27;pause&#x27;</code> \| <code>&#x27;fixKeys&#x27;</code> | what to run |
| cred | <code>string</code> | name of Credential |
| bu | <code>string</code> | name of BU |
| [type] | <code>TYPE.SupportedMetadataTypes</code> | limit execution to given metadata type |
Expand All @@ -8417,6 +8420,21 @@ helper for [Mcdev.#runOnBU](Mcdev.#runOnBU)
| selectedType | <code>TYPE.SupportedMetadataTypes</code> | limit execution to given metadata type |
| buObject | <code>TYPE.BuObject</code> | properties for auth |

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

## Mcdev.(cred, bu, type, [keyArr]) ⇒ <code>Promise.&lt;Array.&lt;string&gt;&gt;</code>
Updates the key to match the name field

**Kind**: global function
**Returns**: <code>Promise.&lt;Array.&lt;string&gt;&gt;</code> - list of keys that were affected

| Param | Type | Description |
| --- | --- | --- |
| cred | <code>string</code> | name of Credential |
| bu | <code>string</code> | name of BU |
| type | <code>TYPE.SupportedMetadataTypes</code> | limit execution to given metadata type |
| [keyArr] | <code>Array.&lt;string&gt;</code> | customerkey of the metadata |

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

## Automation.(metadata) ⇒ <code>boolean</code>
Expand Down
125 changes: 68 additions & 57 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -774,10 +774,21 @@ class Mcdev {
static async pause(businessUnit, selectedType, keys) {
return this.#runMethod('pause', businessUnit, selectedType, keys);
}
/**
* Updates the key to match the name field
*
* @param {string} businessUnit name of BU
* @param {TYPE.SupportedMetadataTypes} selectedType limit to given metadata types
* @param {string[]} [keys] customerkey of the metadata
* @returns {Promise.<Object.<string, string[]>>} key: business unit name, value: list of paused item keys
*/
static async fixKeys(businessUnit, selectedType, keys) {
return this.#runMethod('fixKeys', businessUnit, selectedType, keys);
}
/**
* run a method across BUs
*
* @param {'execute'|'pause'} methodName what to run
* @param {'execute'|'pause'|'fixKeys'} methodName what to run
* @param {string} businessUnit name of BU
* @param {TYPE.SupportedMetadataTypes} [selectedType] limit to given metadata types
* @param {string[]} [keys] customerkey of the metadata
Expand All @@ -788,34 +799,48 @@ class Mcdev {
let lang_past;
let lang_present;
let requireKeyOrLike;
let checkMetadataSupport;
const resultObj = {};

switch (methodName) {
case 'execute': {
lang_past = 'executed';
lang_present = 'executing';
requireKeyOrLike = true;
checkMetadataSupport = true;
break;
}
case 'pause': {
lang_past = 'paused';
lang_present = 'pausing';
requireKeyOrLike = true;
checkMetadataSupport = true;
break;
}
case 'fixKeys': {
lang_past = 'fixed keys';
lang_present = 'fixing keys';
requireKeyOrLike = false;
checkMetadataSupport = false;
break;
}
}

Util.logger.info(`mcdev:: ${methodName} ${selectedType}`);
const properties = await config.getProperties();
let counter_credBu = 0;
let counter_credKeys = 0;
if (!(await config.checkProperties(properties))) {
// return null here to avoid seeing 2 error messages for the same issue
return resultObj;
}
if (!Util._isValidType(selectedType)) {
return resultObj;
}
if (!Object.prototype.hasOwnProperty.call(MetadataTypeInfo[selectedType], methodName)) {
if (
checkMetadataSupport &&
!Object.prototype.hasOwnProperty.call(MetadataTypeInfo[selectedType], methodName)
) {
Util.logger.error(
` ☇ skipping ${selectedType}: ${methodName} is not supported yet for ${selectedType}`
);
Expand Down Expand Up @@ -847,6 +872,7 @@ class Mcdev {
for (const cred in properties.credentials) {
Util.logger.info(`:: ${lang_present} ${selectedType} on all BUs for ${cred}`);
// reset counter per cred
counter_credKeys = 0;
counter_credBu = 0;
for (const bu in properties.credentials[cred].businessUnits) {
resultObj[cred + '/' + bu] = await this.#runOnBU(
Expand All @@ -857,11 +883,12 @@ class Mcdev {
keys
);
counter_credBu++;
counter_credKeys += resultObj[cred + '/' + bu].length;
Util.startLogger(true);
}
counter_credTotal += counter_credBu;
Util.logger.info(
`:: ${lang_past} ${selectedType} on ${counter_credBu} BUs for ${cred}`
`:: ${lang_past} for ${counter_credKeys} ${selectedType}s on ${counter_credBu} BUs for ${cred}`
);
}
Util.logger.info(
Expand Down Expand Up @@ -899,10 +926,11 @@ class Mcdev {
keys
);
counter_credBu++;
counter_credKeys += resultObj[cred + '/' + bu].length;
Util.startLogger(true);
}
Util.logger.info(
`:: ${lang_past} ${selectedType} on ${counter_credBu} BUs for ${cred}`
`:: ${lang_past} for ${counter_credKeys} ${selectedType}s on ${counter_credBu} BUs for ${cred}`
);
} else {
// execute runMethod for the entity on one BU only
Expand All @@ -921,7 +949,7 @@ class Mcdev {
/**
* helper for {@link Mcdev.#runMethod}
*
* @param {'execute'|'pause'} methodName what to run
* @param {'execute'|'pause'|'fixKeys'} methodName what to run
* @param {string} cred name of Credential
* @param {string} bu name of BU
* @param {TYPE.SupportedMetadataTypes} [type] limit execution to given metadata type
Expand All @@ -948,18 +976,27 @@ class Mcdev {
}
Util.logger.info(`:: ${methodName} ${type} on ${cred}/${bu}`);
MetadataTypeInfo[type].client = auth.getSDK(buObject);
if (Util.OPTIONS.like && Object.keys(Util.OPTIONS.like).length) {
keyArr = await this.#retrieveKeysWithLike(type, buObject);
} else {
MetadataTypeInfo[type].properties = properties;
MetadataTypeInfo[type].buObject = buObject;
}
if (!keyArr || (Array.isArray(keyArr) && !keyArr.length)) {
throw new Error('No keys were provided');
}

// result will be undefined (false) if methodName is not supported for the type
resultArr.push(...(await MetadataTypeInfo[type][methodName](keyArr)));
MetadataTypeInfo[type].properties = properties;
MetadataTypeInfo[type].buObject = buObject;
switch (methodName) {
case 'fixKeys': {
{
resultArr.push(...(await this.#fixKeys(cred, bu, type, keyArr)));

break;
}
}
default: {
if (Util.OPTIONS.like && Object.keys(Util.OPTIONS.like).length) {
keyArr = await this.#retrieveKeysWithLike(type, buObject);
}
if (!keyArr || (Array.isArray(keyArr) && !keyArr.length)) {
throw new Error('No keys were provided');
} // result will be undefined (false) if methodName is not supported for the type
resultArr.push(...(await MetadataTypeInfo[type][methodName](keyArr)));
}
}
} catch (ex) {
Util.logger.errorStack(ex, 'mcdev.' + methodName + ' failed');
}
Expand Down Expand Up @@ -1025,7 +1062,7 @@ class Mcdev {
Util.getGrayMsg(
`Identified ${keyArr.length} ${selectedType}${
keyArr.length === 1 ? '' : 's'
} that match${selectedType}${keyArr.length === 1 ? 'es' : ''} the like-filter`
} that match${keyArr.length === 1 ? 'es' : ''} the like-filter`
)
);

Expand All @@ -1034,77 +1071,51 @@ class Mcdev {
/**
* Updates the key to match the name field
*
* @param {string} businessUnit name of BU
* @param {string} cred name of Credential
* @param {string} bu name of BU
* @param {TYPE.SupportedMetadataTypes} type limit execution to given metadata type
* @param {string[]} [keys] customerkey of the metadata
* @returns {Promise.<Object.<string, string[]>>} key: business unit name, value: list of affected item keys
* @param {string[]} [keyArr] customerkey of the metadata
* @returns {Promise.<string[]>} list of keys that were affected
*/
static async fixKeys(businessUnit, type, keys) {
Util.startLogger();
Util.logger.info('mcdev:: fixKeys');
let actuallyFixedKeys = [];
const result = {};
result[businessUnit] = actuallyFixedKeys;
static async #fixKeys(cred, bu, type, keyArr) {
const properties = await config.getProperties();
if (!(await config.checkProperties(properties))) {
// return null here to avoid seeing 2 error messages for the same issue
return result;
}
if (!type || !Util._isValidType(type)) {
return result;
}
let actuallyFixedKeys = [];
const resultArr = [];

if (
MetadataTypeDefinitions[type].keyIsFixed === true ||
MetadataTypeDefinitions[type].keyField === MetadataTypeDefinitions[type].idField
) {
Util.logger.error(`Key cannot be updated for this type`);
return result;
return resultArr;
}
let [cred, bu] = businessUnit ? businessUnit.split('/') : [null, null];

const buObject = await Cli.getCredentialObject(
properties,
cred === null ? null : cred + '/' + bu,
null,
true
);
if (buObject !== null) {
cache.initCache(buObject);
cred = buObject.credential;
bu = buObject.businessUnit;
}
Util.logger.info(
`Updating keys 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 result;
}
try {
Util.logger.info(`Retrieving latest versions of ${type} from server`);
const retriever = new Retriever(properties, buObject);
const retrieved = await retriever.retrieve([type], keys, null, false);
const retrieved = await retriever.retrieve([type], keyArr, null, false);

const metadataMap = Object.values(retrieved)[0][0];
const keysForDeploy = MetadataTypeInfo[type].getKeysForFixing(metadataMap);
if (keysForDeploy.length < 1) {
Util.logger.error(
`No items found with a key-name mismatch that match your criteria.`
`No items found with a key-name mismatch that match your criteria.\n`
);
return result;
return resultArr;
}
this.setOptions({
changeKeyField: MetadataTypeDefinitions[type].nameField,
fromRetrieve: true,
});
const deployed = await Deployer.deploy(businessUnit, [type], keysForDeploy);
const deployed = await Deployer.deploy(cred + '/' + bu, [type], keysForDeploy);
actuallyFixedKeys = Object.keys(Object.values(Object.values(deployed)[0])[0]);
result[cred + '/' + bu] = actuallyFixedKeys;
resultArr.push(...actuallyFixedKeys);
const dependentTypes = await Util.getDependentMetadata(type);
if (actuallyFixedKeys && actuallyFixedKeys.length) {
Util.logger.info(
Expand All @@ -1124,7 +1135,7 @@ class Mcdev {
Util.logger.errorStack(ex, 'mcdev.fixKeys failed');
}
Util.logger.info(`:: Done\n`);
return result;
return resultArr;
}
}

Expand Down
14 changes: 9 additions & 5 deletions lib/metadataTypes/Automation.js
Original file line number Diff line number Diff line change
Expand Up @@ -891,13 +891,8 @@ class Automation extends MetadataType {
if (!metadataMap[key].type) {
// create response does not return the type attribute

// el.schedule.timezoneName
const scheduleHelper =
metadataMap[key].schedule || metadataMap[key].startSource.schedule;
scheduleHelper.timezoneName ||= Util.inverseGet(
this.definition.timeZoneMapping,
scheduleHelper.timezoneId
);

// el.type
metadataMap[key].type = scheduleHelper
Expand All @@ -906,6 +901,15 @@ class Automation extends MetadataType {
? 'triggered'
: undefined;

// el.schedule.timezoneName
if (metadataMap[key].type === 'scheduled') {
// not existing for triggered automations
scheduleHelper.timezoneName ||= Util.inverseGet(
this.definition.timeZoneMapping,
scheduleHelper.timezoneId
);
}

// el.status
metadataMap[key].status ||= Util.inverseGet(
this.definition.statusMapping,
Expand Down
8 changes: 5 additions & 3 deletions lib/metadataTypes/MetadataType.js
Original file line number Diff line number Diff line change
Expand Up @@ -2082,9 +2082,11 @@ class MetadataType {
);
} else {
Util.logger.info(
` ☇ skipping ${this.definition.type} ${
item[this.definition.keyField]
}: key does not need to be updated`
Util.getGrayMsg(
` ☇ skipping ${this.definition.type} ${
item[this.definition.keyField]
}: key does not need to be updated`
)
);
}
}
Expand Down
Loading
Loading