feat: add call checks

This commit is contained in:
2024-12-26 13:06:44 +09:00
parent eb30242fe1
commit abacea4f71
10 changed files with 247 additions and 64 deletions

View File

@ -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]

View File

@ -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
View File

@ -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
}[]
} }

View File

@ -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>

View 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>

View 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>

View 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>

View 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>

View 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>
<% } %>

View 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>