feat: add call checks
This commit is contained in:
@ -11,7 +11,7 @@ export class BPManager {
|
|||||||
// ---
|
// ---
|
||||||
|
|
||||||
private readonly bpSets:
|
private readonly bpSets:
|
||||||
Record<string, BPSet | undefined> = {}
|
Record<string, BPSet> = {}
|
||||||
|
|
||||||
private readonly bpSetMetadatas:
|
private readonly bpSetMetadatas:
|
||||||
Record<string, BPSetMetadata> = {}
|
Record<string, BPSetMetadata> = {}
|
||||||
@ -32,10 +32,10 @@ export class BPManager {
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
const bpSetPath = path.join(bpSetFile.parentPath, bpSetFile.name)
|
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))
|
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: [],
|
nonCompliantResources: [],
|
||||||
compliantResources: [],
|
compliantResources: [],
|
||||||
status:'LOADED',
|
status:'LOADED',
|
||||||
|
errorMessage: [],
|
||||||
idx
|
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) =>
|
public readonly getBPSet = (name: string) =>
|
||||||
this.bpSets[name]
|
this.bpSets[name]
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ export class WebServer {
|
|||||||
this.app.use(express.static('./public'))
|
this.app.use(express.static('./public'))
|
||||||
|
|
||||||
this.app.get('/', this.getMainPage.bind(this))
|
this.app.get('/', this.getMainPage.bind(this))
|
||||||
|
this.app.get('/check_all', this.runCheck.bind(this))
|
||||||
this.app.use(this.error404)
|
this.app.use(this.error404)
|
||||||
|
|
||||||
this.app.listen(this.port, this.showBanner.bind(this))
|
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) {
|
private error404 (_: Request, res: Response) {
|
||||||
res.status(404).send({ success: false, message: 'Page not found' })
|
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[]
|
compliantResources: string[]
|
||||||
status: 'LOADED' | 'CHECKING' | 'ERROR' | 'FINISHED'
|
status: 'LOADED' | 'CHECKING' | 'ERROR' | 'FINISHED'
|
||||||
idx: number
|
idx: number
|
||||||
|
errorMessage: {
|
||||||
|
date: Date,
|
||||||
|
message: string
|
||||||
|
}[]
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container p-3">
|
<div class="container p-3">
|
||||||
<h1 class="fw-bold">BPSets (<%= bpLength %>)</h1>
|
<%- include('partial/page_header.ejs') %>
|
||||||
<p>Created by Minhyeok Park</p>
|
|
||||||
|
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<thead>
|
<thead>
|
||||||
@ -31,65 +30,9 @@
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<% metadatas.forEach((metadata) => { %>
|
<% metadatas.forEach((metadata) => { %>
|
||||||
<tr>
|
<%- include('./partial/bpset_item.ejs', { metadata }) %>
|
||||||
<td class="fw-bold">#<%= metadata.idx + 1 %></td>
|
<%- include('./partial/bpset_details.ejs', { metadata }) %>
|
||||||
<td><%= metadata.name %></td>
|
<%- include('./partial/bpset_logs.ejs', { metadata }) %>
|
||||||
<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>
|
|
||||||
<% }) %>
|
<% }) %>
|
||||||
<% }) %>
|
<% }) %>
|
||||||
</tbody>
|
</tbody>
|
||||||
@ -97,5 +40,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
<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>
|
</body>
|
||||||
</html>
|
</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