feat: add call checks
This commit is contained in:
@ -11,7 +11,7 @@ export class BPManager {
|
||||
// ---
|
||||
|
||||
private readonly bpSets:
|
||||
Record<string, BPSet | undefined> = {}
|
||||
Record<string, BPSet> = {}
|
||||
|
||||
private readonly bpSetMetadatas:
|
||||
Record<string, BPSetMetadata> = {}
|
||||
@ -32,10 +32,10 @@ export class BPManager {
|
||||
continue
|
||||
|
||||
const bpSetPath = path.join(bpSetFile.parentPath, bpSetFile.name)
|
||||
const bpSetClasses = await import('../' + bpSetPath) as Record<string, BPSet>
|
||||
const bpSetClasses = await import('../' + bpSetPath) as Record<string, new () => BPSet>
|
||||
|
||||
for (const bpSetClass of Object.keys(bpSetClasses))
|
||||
this.bpSets[bpSetClass] = bpSetClasses[bpSetClass]
|
||||
this.bpSets[bpSetClass] = new bpSetClasses[bpSetClass]()
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,11 +49,36 @@ export class BPManager {
|
||||
nonCompliantResources: [],
|
||||
compliantResources: [],
|
||||
status:'LOADED',
|
||||
errorMessage: [],
|
||||
idx
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async runCheck() {
|
||||
for (const name in this.bpSets) {
|
||||
this.bpSetMetadatas[name].status = 'CHECKING'
|
||||
|
||||
const result = await this.bpSets[name].check()
|
||||
.catch((err) => {
|
||||
this.bpSetMetadatas[name].status = 'ERROR'
|
||||
this.bpSetMetadatas[name].errorMessage.push({
|
||||
date: new Date(),
|
||||
message: err
|
||||
})
|
||||
|
||||
return undefined
|
||||
})
|
||||
|
||||
if (result === undefined)
|
||||
continue
|
||||
|
||||
this.bpSetMetadatas[name].compliantResources = result.compliantResources
|
||||
this.bpSetMetadatas[name].nonCompliantResources = result.nonCompliantResources
|
||||
this.bpSetMetadatas[name].status = 'FINISHED'
|
||||
}
|
||||
}
|
||||
|
||||
public readonly getBPSet = (name: string) =>
|
||||
this.bpSets[name]
|
||||
|
||||
|
@ -15,6 +15,7 @@ export class WebServer {
|
||||
this.app.use(express.static('./public'))
|
||||
|
||||
this.app.get('/', this.getMainPage.bind(this))
|
||||
this.app.get('/check_all', this.runCheck.bind(this))
|
||||
this.app.use(this.error404)
|
||||
|
||||
this.app.listen(this.port, this.showBanner.bind(this))
|
||||
@ -41,6 +42,12 @@ export class WebServer {
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
private runCheck(_: Request, res: Response) {
|
||||
void this.bpManager.runCheck()
|
||||
res.redirect('/')
|
||||
}
|
||||
|
||||
private error404 (_: Request, res: Response) {
|
||||
res.status(404).send({ success: false, message: 'Page not found' })
|
||||
}
|
||||
|
4
src/types.d.ts
vendored
4
src/types.d.ts
vendored
@ -51,4 +51,8 @@ export interface BPSetMetadata {
|
||||
compliantResources: string[]
|
||||
status: 'LOADED' | 'CHECKING' | 'ERROR' | 'FINISHED'
|
||||
idx: number
|
||||
errorMessage: {
|
||||
date: Date,
|
||||
message: string
|
||||
}[]
|
||||
}
|
||||
|
@ -9,8 +9,7 @@
|
||||
</head>
|
||||
<body>
|
||||
<div class="container p-3">
|
||||
<h1 class="fw-bold">BPSets (<%= bpLength %>)</h1>
|
||||
<p>Created by Minhyeok Park</p>
|
||||
<%- include('partial/page_header.ejs') %>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
@ -31,65 +30,9 @@
|
||||
</tr>
|
||||
|
||||
<% metadatas.forEach((metadata) => { %>
|
||||
<tr>
|
||||
<td class="fw-bold">#<%= metadata.idx + 1 %></td>
|
||||
<td><%= metadata.name %></td>
|
||||
<td><%= metadata.bestPracticeCategory %></td>
|
||||
<td>
|
||||
<span class="badge text-bg-<%= ['danger', 'warning', 'secondary'][metadata.priority-1] %>"><%= metadata.priority %> - <%= ['CRITICAL', 'Required', 'Recommend'][metadata.priority-1] %></span>
|
||||
</td>
|
||||
<% if (metadata.status === 'FINISHED') { %>
|
||||
<% if (metadata.nonCompliantResources.length < 1) { %>
|
||||
<td><span class="badge text-bg-success">Pass</span></td>
|
||||
<% } else { %>
|
||||
<td><span class="badge text-bg-danger">Fail</span></td>
|
||||
<% } %>
|
||||
<td>
|
||||
<div class="progress" role="progressbar">
|
||||
<div class="progress-bar" style="width: <%= metadata.compliantResources.length / metadata.nonCompliantResources.length + metadata.compliantResources.length %>%"></div>
|
||||
</div>
|
||||
(<%= metadata.compliantResources.length %>/<%= metadata.nonCompliantResources.length + metadata.compliantResources.length %>)
|
||||
</td>
|
||||
<% } else if (metadata.status === 'CHECKING') { %>
|
||||
<td colspan="2">
|
||||
<div class="progress" role="progressbar">
|
||||
<div class="progress-bar progress-bar-striped progress-bar-animated bg-secondary" style="width: 100%"></div>
|
||||
</div>
|
||||
</td>
|
||||
<% } else if (metadata.status === 'ERROR') { %>
|
||||
<td colspan="2">
|
||||
<div class="progress" role="progressbar">
|
||||
<div class="progress-bar progress-bar-striped bg-danger" style="width: 100%"></div>
|
||||
</div>
|
||||
</td>
|
||||
<% } else if (metadata.status === 'LOADED') { %>
|
||||
<td colspan="2">
|
||||
<div class="progress" role="progressbar">
|
||||
<div class="progress-bar" style="width: 0%"></div>
|
||||
</div>
|
||||
</td>
|
||||
<% } %>
|
||||
<td>
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-primary">Recheck</button>
|
||||
<button type="button" class="btn btn-secondary">Fix</button>
|
||||
<button type="button" class="btn btn-secondary" data-bs-toggle="collapse" data-bs-target="#detail-<%= metadata.idx %>">Details</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="7" class="p-0">
|
||||
<div class="collapse" id="detail-<%= metadata.idx %>">
|
||||
<div class="card card-body border-0 bg-light">
|
||||
<h3><%= metadata.name %></h3>
|
||||
<p><%= metadata.description %></p>
|
||||
|
||||
<p>Category: <span class="badge text-bg-secondary"><%= metadata.bestPracticeCategory %></span> <%= metadata.awsServiceCategory %> - <%= metadata.awsService %></p>
|
||||
<p>Priority: <span class="badge text-bg-<%= ['danger', 'warning', 'secondary'][metadata.priority-1] %>"><%= metadata.priority %> - <%= ['CRITICAL', 'Required', 'Recommend'][metadata.priority-1] %></span> (<%= metadata.priorityReason %>)</p>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<%- include('./partial/bpset_item.ejs', { metadata }) %>
|
||||
<%- include('./partial/bpset_details.ejs', { metadata }) %>
|
||||
<%- include('./partial/bpset_logs.ejs', { metadata }) %>
|
||||
<% }) %>
|
||||
<% }) %>
|
||||
</tbody>
|
||||
@ -97,5 +40,9 @@
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script>
|
||||
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]')
|
||||
const tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl))
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
8
views/partial/bpset_actions.ejs
Normal file
8
views/partial/bpset_actions.ejs
Normal file
@ -0,0 +1,8 @@
|
||||
<td>
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-primary">Fix</button>
|
||||
<button type="button" class="btn btn-secondary">Recheck</button>
|
||||
<button type="button" class="btn btn-secondary" data-bs-toggle="collapse" data-bs-target="#detail-<%= metadata.idx %>">Details</button>
|
||||
<button type="button" class="btn btn-secondary" data-bs-toggle="collapse" data-bs-target="#logs-<%= metadata.idx %>">Logs</button>
|
||||
</div>
|
||||
</td>
|
59
views/partial/bpset_details.ejs
Normal file
59
views/partial/bpset_details.ejs
Normal file
@ -0,0 +1,59 @@
|
||||
<%
|
||||
const priorityLabel = ['CRITICAL', 'Required', 'Recommend'][metadata.priority-1] || 'Recommend'
|
||||
const priorityColor = ['danger', 'warning', 'secondary'][metadata.priority-1] || 'secondary'
|
||||
%>
|
||||
|
||||
<tr>
|
||||
<td colspan="7" class="p-0">
|
||||
<div class="collapse" id="detail-<%= metadata.idx %>">
|
||||
<div class="bg-light p-3">
|
||||
<h3><%= metadata.name %></h3>
|
||||
<p><%= metadata.description %></p>
|
||||
|
||||
<p>
|
||||
Category:
|
||||
<span class="badge text-bg-secondary"><%= metadata.bestPracticeCategory %></span>
|
||||
<%= metadata.awsServiceCategory %> - <%= metadata.awsService %>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Priority:
|
||||
<span class="badge text-bg-<%= priorityColor %>">
|
||||
<%= metadata.priority %> - <%= priorityLabel %>
|
||||
</span>
|
||||
|
||||
<%= metadata.priorityReason %>
|
||||
</p>
|
||||
|
||||
<h4>Operations used in check function</h4>
|
||||
<div class="row row-cols-3">
|
||||
<% metadata.commandUsedInCheckFunction.forEach(({ name, reason }) => { %>
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<h5 class="card-header"><%= name %></h5>
|
||||
<div class="card-body">
|
||||
<%= reason %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
</div>
|
||||
<br>
|
||||
|
||||
<h4>Operations used in fix function</h4>
|
||||
<div class="row row-cols-3">
|
||||
<% metadata.commandUsedInFixFunction.forEach(({ name, reason }) => { %>
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<h5 class="card-header"><%= name %></h5>
|
||||
<div class="card-body">
|
||||
<%= reason %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
19
views/partial/bpset_item.ejs
Normal file
19
views/partial/bpset_item.ejs
Normal file
@ -0,0 +1,19 @@
|
||||
<%
|
||||
const priorityLabel = ['CRITICAL', 'Required', 'Recommend'][metadata.priority-1] || 'Recommend'
|
||||
const priorityColor = ['danger', 'warning', 'secondary'][metadata.priority-1] || 'secondary'
|
||||
%>
|
||||
|
||||
<tr>
|
||||
<td class="fw-bold">#<%= metadata.idx + 1 %></td>
|
||||
<td><%= metadata.name %></td>
|
||||
<td><%= metadata.bestPracticeCategory %></td>
|
||||
|
||||
<td>
|
||||
<span class="badge text-bg-<%= priorityColor %>">
|
||||
<%= metadata.priority %> - <%= priorityLabel %>
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<%- include('./bpset_progress.ejs', { metadata }) %>
|
||||
<%- include('./bpset_actions.ejs', { metadata }) %>
|
||||
</tr>
|
34
views/partial/bpset_logs.ejs
Normal file
34
views/partial/bpset_logs.ejs
Normal file
@ -0,0 +1,34 @@
|
||||
<tr>
|
||||
<td colspan="7" class="p-0">
|
||||
<div class="collapse" id="logs-<%= metadata.idx %>">
|
||||
<div class="bg-light p-3">
|
||||
<h4>Non-Compliant Resources</h4>
|
||||
<ul>
|
||||
<% metadata.nonCompliantResources.forEach((id) => { %>
|
||||
<li><%= id %></li>
|
||||
<% }) %>
|
||||
</ul>
|
||||
|
||||
<br>
|
||||
|
||||
<h4>Compliant Resources</h4>
|
||||
<ul>
|
||||
<% metadata.compliantResources.forEach((id) => { %>
|
||||
<li><%= id %></li>
|
||||
<% }) %>
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
<h4>Error Logs</h4>
|
||||
<ul>
|
||||
<% metadata.errorMessage.forEach((log) => { %>
|
||||
<li>
|
||||
<p><%= log.date %></p>
|
||||
<pre><%= log.message %></pre>
|
||||
</li>
|
||||
<% }) %>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
57
views/partial/bpset_progress.ejs
Normal file
57
views/partial/bpset_progress.ejs
Normal file
@ -0,0 +1,57 @@
|
||||
<%
|
||||
const passResources = metadata.compliantResources.length
|
||||
const failResources = metadata.nonCompliantResources.length
|
||||
|
||||
const totalResources = passResources + failResources
|
||||
const passPercent =
|
||||
totalResources > 0
|
||||
? passResources / totalResources * 100
|
||||
: 100
|
||||
|
||||
const isPass = failResources < 1
|
||||
%>
|
||||
|
||||
<% if (metadata.status === 'FINISHED') { %>
|
||||
<td>
|
||||
<span class="badge text-bg-<%= isPass ? 'success' : 'danger' %>">
|
||||
<%= isPass ? 'Pass' : 'Fail' %>
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<div class="progress" role="progressbar">
|
||||
<div class="progress-bar" style="width: <%= passPercent %>%"></div>
|
||||
</div>
|
||||
(<%= passResources %>/<%= totalResources %>)
|
||||
</td>
|
||||
<% } %>
|
||||
|
||||
<% if (metadata.status === 'CHECKING') { %>
|
||||
<td colspan="2">
|
||||
<div class="progress" role="progressbar">
|
||||
<div class="progress-bar progress-bar-striped progress-bar-animated bg-secondary" style="width: 100%"></div>
|
||||
</div>
|
||||
|
||||
<p>Progressing</p>
|
||||
</td>
|
||||
<% } %>
|
||||
|
||||
<% if (metadata.status === 'ERROR') { %>
|
||||
<td colspan="2">
|
||||
<div class="progress" role="progressbar">
|
||||
<div class="progress-bar progress-bar-striped bg-danger" style="width: 100%"></div>
|
||||
</div>
|
||||
|
||||
<p>Error</p>
|
||||
</td>
|
||||
<% } %>
|
||||
|
||||
<% if (metadata.status === 'LOADED') { %>
|
||||
<td colspan="2">
|
||||
<div class="progress" role="progressbar">
|
||||
<div class="progress-bar" style="width: 0%"></div>
|
||||
</div>
|
||||
|
||||
<p>Ready</p>
|
||||
</td>
|
||||
<% } %>
|
23
views/partial/page_header.ejs
Normal file
23
views/partial/page_header.ejs
Normal file
@ -0,0 +1,23 @@
|
||||
<div class="d-flex justify-content-between align-items-end">
|
||||
<div>
|
||||
<h1 class="fw-bold">BPSets (<%= bpLength %>)</h1>
|
||||
<p>Created by Minhyeok Park</p>
|
||||
</div>
|
||||
|
||||
<div class="d-flex">
|
||||
<div>
|
||||
<p>Pass</p>
|
||||
<p><%= %></p>
|
||||
</div>
|
||||
<div>
|
||||
<p>Fail</p>
|
||||
</div>
|
||||
<div>
|
||||
<p>Error</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="btn-group">
|
||||
<a href="/check_all" type="button" class="btn btn-primary">Check All</a>
|
||||
</div>
|
||||
</div>
|
Reference in New Issue
Block a user