Skip to content

Commit b98f6bb

Browse files
feat: add status page
1 parent cbd1359 commit b98f6bb

File tree

3 files changed

+158
-2
lines changed

3 files changed

+158
-2
lines changed

proxy/handlers/status.ts

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
import { HttpRequest } from '@azure/functions'
2+
import { CustomerVariables } from '../customer-variables/CustomerVariables'
3+
import { maybeObfuscateVariable } from '../customer-variables/maybeObfuscateVariable'
4+
import { CustomerVariableType } from '../customer-variables/types'
5+
import { HttpResponseSimple } from '@azure/functions/types/http'
6+
import { EnvVarInfo, StatusFormat } from '../../shared/status'
7+
8+
export interface HandleStatusParams {
9+
httpRequest: HttpRequest
10+
customerVariables: CustomerVariables
11+
}
12+
13+
export interface StatusInfo {
14+
version: string
15+
envInfo: EnvVarInfo[]
16+
}
17+
18+
async function getEnvInfo(customerVariables: CustomerVariables) {
19+
const infoArray: EnvVarInfo[] = await Promise.all(
20+
Object.values(CustomerVariableType).map(async (variableType) => {
21+
const value = await customerVariables.getVariable(variableType)
22+
23+
return {
24+
envVarName: variableType,
25+
value: maybeObfuscateVariable(variableType, value.value),
26+
isSet: Boolean(value.value),
27+
resolvedBy: value.resolvedBy,
28+
}
29+
}),
30+
)
31+
32+
return infoArray
33+
}
34+
35+
function renderEnvInfo(envInfo: EnvVarInfo[]) {
36+
const isAlSet = envInfo.every((info) => info.isSet && info.resolvedBy)
37+
38+
if (isAlSet) {
39+
return `
40+
<div>
41+
✅ All environment variables are set
42+
</div>
43+
`
44+
}
45+
46+
const children = envInfo
47+
.filter((info) => !info.isSet || !info.resolvedBy)
48+
.map(
49+
(info) => `
50+
<div class="env-info-item">
51+
⚠️ <strong>${info.envVarName} </strong> is not defined${info.isSet ? ' and uses default value' : ''}
52+
</div>`,
53+
)
54+
55+
return `
56+
<div class="env-info">
57+
${children.join('')}
58+
</div>
59+
`
60+
}
61+
62+
function renderHtml({ version, envInfo }: StatusInfo) {
63+
return `
64+
<html lang="en-US">
65+
<head>
66+
<title>Azure integration status</title>
67+
<meta charset="utf-8">
68+
<style>
69+
body, .env-info {
70+
display: flex;
71+
}
72+
73+
body {
74+
flex-direction: column;
75+
align-items: center;
76+
}
77+
78+
body > * {
79+
margin-bottom: 1em;
80+
}
81+
</style>
82+
</head>
83+
<body>
84+
<h1>Azure integration status</h1>
85+
<div>
86+
Lambda function version: ${version}
87+
</div>
88+
${renderEnvInfo(envInfo)}
89+
<span>
90+
Please reach out our support via <a href="mailto:support@fingerprint.com">support@fingerprint.com</a> if you have any issues
91+
</span>
92+
</body>
93+
</html>
94+
`
95+
}
96+
97+
export async function getStatusInfo(customerVariables: CustomerVariables): Promise<StatusInfo> {
98+
return {
99+
version: '__lambda_func_version__',
100+
envInfo: await getEnvInfo(customerVariables),
101+
}
102+
}
103+
104+
export async function handleStatus({
105+
customerVariables,
106+
httpRequest,
107+
}: HandleStatusParams): Promise<HttpResponseSimple> {
108+
const { format } = httpRequest.query
109+
110+
const info = await getStatusInfo(customerVariables)
111+
112+
if (format === StatusFormat.JSON) {
113+
return {
114+
status: '200',
115+
body: info,
116+
headers: {
117+
'Content-Type': 'application/json',
118+
},
119+
}
120+
}
121+
122+
return {
123+
status: '200',
124+
body: renderHtml(info).trim(),
125+
headers: {
126+
'Content-Type': 'text/html',
127+
},
128+
}
129+
}

proxy/index.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { handleIngress } from './handlers/ingress'
44
import { CustomerVariables } from './customer-variables/CustomerVariables'
55
import { EnvCustomerVariables } from './customer-variables/EnvCustomerVariables'
66
import { CustomerVariableType } from './customer-variables/types'
7+
import { STATUS_PATH } from '../shared/status'
8+
import { handleStatus } from './handlers/status'
79

810
const proxy: AzureFunction = async (context: Context, req: HttpRequest): Promise<void> => {
911
context.log.verbose('Handling request', {
@@ -13,13 +15,22 @@ const proxy: AzureFunction = async (context: Context, req: HttpRequest): Promise
1315

1416
const customerVariables = new CustomerVariables([new EnvCustomerVariables()], context.log)
1517

18+
const path = req.params?.restOfPath
19+
20+
if (path === STATUS_PATH) {
21+
context.res = await handleStatus({
22+
httpRequest: req,
23+
customerVariables,
24+
})
25+
26+
return
27+
}
28+
1629
const [clientPath, resultPath] = await Promise.all([
1730
customerVariables.getVariable(CustomerVariableType.AgentDownloadPath),
1831
customerVariables.getVariable(CustomerVariableType.GetResultPath),
1932
])
2033

21-
const path = req.params?.restOfPath
22-
2334
const get404 = () => ({
2435
status: 404,
2536
body: JSON.stringify({

shared/status.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { CustomerVariableValue } from '../proxy/customer-variables/types'
2+
3+
export enum StatusFormat {
4+
HTML = 'html',
5+
JSON = 'json',
6+
}
7+
8+
export interface EnvVarInfo {
9+
envVarName: string
10+
value: CustomerVariableValue
11+
isSet: boolean
12+
// If null, the variable was resolved with the default value, otherwise it was resolved by the provider with the given name
13+
resolvedBy: string | null
14+
}
15+
16+
export const STATUS_PATH = 'status'

0 commit comments

Comments
 (0)