diff --git a/index.js b/index.js index b1dde1b..5a2c297 100644 --- a/index.js +++ b/index.js @@ -276,7 +276,6 @@ module.exports = { if (options.lambdas && options.lambdas.length) { const cwd = inventory.inv._project.src; s3Instance.on('event', (e) => { - console.log('s3rver event', e); const record = e.Records[0]; const { eventName } = record; let triggerParts = eventName.split(':'); @@ -285,12 +284,12 @@ module.exports = { update.status(`S3 ${triggerEvt}:${triggerApi} event for key ${record.s3.object.key} received!`); let lambdasToTrigger = []; options.lambdas.forEach(l => { - Object.keys(l.events).forEach(e => { - let eventParts = e.split(':'); - // TODO: prefix and suffix support + Object.entries(l.events).forEach(([ event, filters ]) => { + let eventParts = event.split(':'); + let filterMatches = findFilterMatches(filters, record); let evt = eventParts[1]; // i.e. ObjectCreated or ObjectRemoved let api = eventParts[2]; // i.e. *, Put, Post, Copy - if (evt === triggerEvt && (api === '*' || triggerApi === api)) { + if (evt === triggerEvt && (api === '*' || triggerApi === api) && filterMatches) { if (!lambdasToTrigger.includes(l)) lambdasToTrigger.push(l); } }); @@ -321,6 +320,30 @@ module.exports = { opts }; +function findFilterMatches (filters, record) { + let filterMatch = {}; + // return true if no filters are applied + if (filters.length === 0) { + return true; + } + + const prefixFilter = filters.filter(([ key, _value ]) => key == 'prefix'); + const suffixFilter = filters.filter(([ key, _value ]) => key == 'suffix'); + + if (prefixFilter.length > 1 || suffixFilter.length > 1) { + throw 'you configured more than one prefix or suffix'; + } + + if (prefixFilter.length == 1) { + filterMatch['prefix'] = prefixFilter[0][1] === record.s3.object.key.split('/')[0]; + } + if (suffixFilter.length == 1) { + filterMatch['suffix'] = suffixFilter[0][1] === record.s3.object.key.split('.').pop(); + } + // check if any prefix or suffix filters fail to match + return !Object.values(filterMatch).includes(false); +} + function opts (pragma) { return pragma.reduce((obj, opt) => { if (Array.isArray(opt)) { @@ -348,15 +371,25 @@ function opts (pragma) { events: {} }; let props = opt[key]; - let lambdaKeys = Object.keys(props); - lambdaKeys.forEach(eventName => { - let filterPairs = props[eventName]; - lambda.events[eventName] = []; - for (let i = 0; i < filterPairs.length - 1; i++) { - if (i % 2 === 1) continue; - lambda.events[eventName].push([ filterPairs[i], filterPairs[i + 1] ]); - } - }); + // if filter options for an event exist, the props are returned as an Array instead of an Object and need to be handled differently + if (Array.isArray(props)) { + let lambdaKeys = props; + lambdaKeys.forEach(eventName => { + lambda.events[eventName] = []; + obj.lambdas.push(lambda); + }); + } else { + let lambdaKeys = Object.keys(props); + lambdaKeys.forEach(eventName => { + let filterPairs = props[eventName]; + lambda.events[eventName] = []; + for (let i = 0; i < filterPairs.length - 1; i++) { + if (i % 2 === 1) continue; + lambda.events[eventName].push([ filterPairs[i], filterPairs[i + 1] ]); + } + }); + obj.lambdas.push(lambda); + } obj.lambdas.push(lambda); } else { obj[key] = opt[key];