haufe-azure-arm-utils
Version:
Azure ARM Node Utilities
266 lines (234 loc) • 8.38 kB
JavaScript
;
const debug = require('debug')('haufe-azure-arm-utils:filter-utils');
const filterUtils = function () { };
// FIXME: this should not be decided in a filter-class, much less in a utils-package
// and even lesser in a library-repository.
const FILTER_OPTIONS = {
keepWeekly: true,
weeklyDay: 3,
weeklyThreshold: 14,
keepMonthly: true,
monthlyThreshold: 60
};
filterUtils.filterByTags = (list, filterTags) => {
debug('filterByTags: ' + filterTags);
const filterList = [];
for (let i = 0; i < list.length; ++i) {
const tags = list[i].tags;
if (tagsMatch(tags, filterTags)) {
filterList.push(list[i]);
}
}
debug('result: ' + JSON.stringify(filterList));
return filterList;
};
filterUtils.getByName = (list, name) => {
debug('getByName(): ' + name);
const entry = list.find(e => e.name.toUpperCase() === name.toUpperCase());
if (entry) {
debug('Result: ' + JSON.stringify(entry));
} else {
debug('name not found, returning null');
}
return entry;
};
const sortDescending = (list) => {
// Clone the list; sort changes the original; we don't want that
const copyList = [];
for (let i = 0; i < list.length; ++i) {
copyList.push(list[i]);
}
return copyList.sort((a, b) => {
const aDate = new Date(a.timeCreated);
const bDate = new Date(b.timeCreated);
return bDate.getTime() - aDate.getTime();
});
};
filterUtils.getNewest = (list, tags) => {
let filteredList = list;
if (tags) {
filteredList = filterUtils.filterByTags(list, tags);
}
if (filteredList.length === 0) {
return null;
}
if (filteredList.length === 1) {
return filteredList[0];
}
// Sort in descending order by timeCreated
const sortedList = sortDescending(filteredList);
return sortedList[0];
};
const isSameDay = (d1, d2) => {
return (d1.getUTCFullYear() === d2.getUTCFullYear() &&
d1.getUTCMonth() === d2.getUTCMonth() &&
d1.getUTCDate() === d2.getUTCDate());
};
const filterForToday = (list, filterOptions) => {
// filterOptions are not used here currently
const today = new Date();
return list.filter(entry => {
const d = new Date(entry.timeCreated);
return isSameDay(today, d);
});
};
const filterForYesterday = (list, filterOptions) => {
// filterOptions are not used here currently
const yesterday = new Date((new Date()).getTime() - (24 * 60 * 60 * 1000));
return list.filter(entry => {
const d = new Date(entry.timeCreated);
return isSameDay(yesterday, d);
});
};
const filterForWeekDay = (list, filterOptions) => {
// Do we want to keep weekly backups?
if (!filterOptions.keepWeekly) {
return [];
}
// Yes, check which ones we have and filter out too old ones
const weeklyThresholdDate = (new Date()).getTime() - (filterOptions.weeklyThreshold * 24 * 60 * 60 * 1000);
return list.filter(entry => {
const d = new Date(entry.timeCreated);
return (d.getUTCDay() === filterOptions.weeklyDay && d.getTime() > weeklyThresholdDate); // week day, and not older than threshold
});
};
const filterForFirstDayInMonth = (list, filterOptions) => {
// Do we want to keep monthly backups?
if (!filterOptions.keepMonthly) {
return [];
}
// Yes, check which ones we have and filter out too old ones
const monthlyThresholdDate = (new Date()).getTime() - (filterOptions.monthlyThreshold * 24 * 60 * 60 * 1000);
return list.filter(entry => {
const d = new Date(entry.timeCreated);
return (d.getUTCDate() === 1 && d.getTime() > monthlyThresholdDate); // 1st in each month, and not older than threshold
});
};
const filterDayDuplicates = (list) => {
debug('filterDayDuplicates()');
if (list.length === 0) {
return [];
}
const sortedList = sortDescending(list);
debug('sortedList');
debug(sortedList);
const resultList = [sortedList[0]]; // we will definitely need the first entry
let currentDate = new Date(sortedList[0].timeCreated);
for (let i = 1; i < sortedList.length; ++i) {
const nextEntryDate = new Date(sortedList[i].timeCreated);
if (!isSameDay(currentDate, nextEntryDate)) {
// Skip if it's the same date; we already have the newest
resultList.push(sortedList[i]);
currentDate = nextEntryDate;
} else {
debug('removing day duplicate for ' + currentDate.toUTCString());
}
}
debug('result filterDayDuplicates');
debug(resultList);
return resultList;
};
const mergeLists = (lists) => {
debug('mergeLists()');
const resultList = [];
for (let i = 0; i < lists.length; ++i) {
for (let j = 0; j < lists[i].length; ++j) {
const entry = lists[i][j];
if (!resultList.find(e => e.id === entry.id)) {
debug('Seeing new ID ' + entry.id);
resultList.push(entry);
} else {
debug('Filtering out duplicate ID ' + entry.id);
}
}
}
return filterDayDuplicates(resultList);
};
const findEntriesNotInKeepList = (fullList, keepList) => {
// Remove by IDs
const resultList = [];
for (let i = 0; i < fullList.length; ++i) {
const entry = fullList[i];
const findEntry = keepList.find(e => e.id === entry.id);
if (findEntry) {
continue;
}
resultList.push(entry);
}
return resultList;
};
filterUtils.getKeepList = (list, tags, options) => {
debug('getKeepList()');
const filterOptions = FILTER_OPTIONS;
if (options) {
for (let key in filterOptions) {
if (options[key]) {
filterOptions[key] = options[key];
}
}
}
const taggedList = filterUtils.filterByTags(list, tags);
if (taggedList.length === 0) {
return taggedList;
}
// We have at least one image; make sure we don't delete the newest image,
// in case we only have one, and we have no current ones.
const newestList = [filterUtils.getNewest(taggedList)];
debug('newestList:');
debug(newestList);
// Which backups were created today?
const todayList = filterForToday(taggedList, filterOptions);
debug('todayList:');
debug(todayList);
// Which backups were created yesterday?
const yesterdayList = filterForYesterday(taggedList, filterOptions);
debug('yesterdayList:');
debug(yesterdayList);
// Which backups were created on a certain week day?
const weekList = filterForWeekDay(taggedList, filterOptions);
debug('weekList:');
debug(weekList);
// Which backups were created on the first of a month?
const monthList = filterForFirstDayInMonth(taggedList, filterOptions);
debug('monthList:');
debug(monthList);
// Merge the list; we know the newest backup is definitely part of this list.
const mergedList = mergeLists([newestList, todayList, yesterdayList, weekList, monthList]);
debug('mergedList:');
debug(mergedList);
return mergedList;
};
filterUtils.getDeleteList = (list, tags, options) => {
debug('getDeleteList()');
const keepList = filterUtils.getKeepList(list, tags, options);
const fullList = filterUtils.filterByTags(list, tags);
// Remove the entries from the keepList from the fullList, these
// are the disks we want to remove.
const deleteList = findEntriesNotInKeepList(fullList, keepList);
debug('deleteList:');
debug(deleteList);
return deleteList;
};
const tagsMatch = (tags, filterTags) => {
debug('tagsMatch(): ' + tags + ', ' + filterTags);
// Do we have tags to filter for?
if (!filterTags || filterTags.length === 0) {
return true;
}
// Does the item have tags, if not, it's not a match
if (!tags || tags.length === 0) {
return false;
}
for (let key in filterTags) {
if (!tags[key]) {
return false;
}
const filterValue = filterTags[key].toUpperCase();
const tagValue = tags[key].toUpperCase();
if (filterValue !== tagValue) {
return false;
}
}
return true;
};
module.exports = filterUtils;