dashboard/models/cis.cattle.io.clusterscan.js

158 lines
4.3 KiB
JavaScript

import { _CREATE, _EDIT } from '@/config/query-params';
import { CIS } from '@/config/types';
import { findBy } from '@/utils/array';
import { downloadFile, generateZip } from '@/utils/download';
import { get, isEmpty, set } from '@/utils/object';
import { sortBy } from '@/utils/sort';
import day from 'dayjs';
import SteveModel from '@/plugins/steve/steve-class';
export default class ClusterScan extends SteveModel {
get _availableActions() {
let out = super._availableActions;
const toFilter = ['cloneYaml', 'goToEditYaml', 'download'];
out = out.filter((action) => {
if (!toFilter.includes(action.action)) {
return action;
}
});
const t = this.$rootGetters['i18n/t'];
const downloadReport = {
action: 'downloadLatestReport',
enabled: this.hasReport,
icon: 'icon icon-fw icon-download',
label: t('cis.downloadReport'),
total: 1,
};
const downloadAllReports = {
action: 'downloadAllReports',
enabled: this.hasReport,
icon: 'icon icon-fw icon-download',
label: t('cis.downloadAllReports'),
total: 1,
};
if (this.hasReports) {
out.unshift({ divider: true });
if (this.spec?.scheduledScanConfig?.cronSchedule) {
out.unshift(downloadAllReports);
downloadReport.label = t('cis.downloadLatestReport');
}
out.unshift(downloadReport);
}
return out;
}
applyDefaults(vm, mode) {
if (mode === _CREATE || mode === _EDIT) {
const includeScheduling = this.canBeScheduled();
const spec = this.spec || {};
spec.scanProfileName = null;
if (includeScheduling) {
spec.scoreWarning = 'pass';
spec.scheduledScanConfig = { scanAlertRule: {}, retentionCount: 3 };
}
set(this, 'spec', spec);
}
}
canBeScheduled() {
const schema = this.$getters['schemaFor'](this.type);
const specSchema = this.$getters['schemaFor'](get(schema, 'resourceFields.spec.type') || '');
if (!specSchema) {
return false;
}
return !!get(specSchema, 'resourceFields.scheduledScanConfig');
}
get isScheduled() {
return !!get(this, 'spec.scheduledScanConfig.cronSchedule');
}
get canUpdate() {
return this.hasLink('update') && this.isScheduled;
}
get hasReports() {
const { relationships = [] } = this.metadata;
const reportRel = findBy(relationships, 'toType', CIS.REPORT);
return !!reportRel;
}
async getReports() {
const owned = await this.findOwned();
const reports = owned.filter(obj => obj.type === CIS.REPORT) || [];
return sortBy(reports, 'metadata.creationTimestamp', true);
}
async downloadLatestReport() {
const reports = await this.getReports() || [];
const report = sortBy(reports, 'metadata.creationTimestamp', true)[0];
const Papa = await import(/* webpackChunkName: "csv" */'papaparse');
try {
const testResults = (report.aggregatedTests || []).map((result) => {
delete result.actual_value_per_node;
return result;
});
const csv = Papa.unparse(testResults);
downloadFile(`${ labelFor(report) }.csv`, csv, 'application/csv');
} catch (err) {
this.$dispatch('growl/fromError', { title: 'Error downloading file', err }, { root: true });
}
}
async downloadAllReports() {
const toZip = {};
const reports = await this.getReports() || [];
const Papa = await import(/* webpackChunkName: "csv" */'papaparse');
reports.forEach((report) => {
try {
const testResults = (report.aggregatedTests || []).map((result) => {
delete result.actual_value_per_node;
return result;
});
const csv = Papa.unparse(testResults);
toZip[`${ labelFor(report) }.csv`] = csv;
} catch (err) {
this.$dispatch('growl/fromError', { title: 'Error downloading file', err }, { root: true });
}
});
if (!isEmpty(toZip)) {
generateZip(toZip).then((zip) => {
downloadFile(`${ this.id }-reports`, zip, 'application/zip');
});
}
}
}
const labelFor = (report) => {
const { creationTimestamp } = report.metadata;
const date = day(creationTimestamp).format('YYYY-MM-DD-HHmmss');
const name = report.id.replace(/^scan-report-/, '');
return `${ name }--${ date }`;
};