From f2c1a96547b6fe917d640632090fbec35ffe3ac6 Mon Sep 17 00:00:00 2001 From: Yiming Luo Date: Wed, 4 Sep 2024 18:07:36 -0400 Subject: [PATCH] Add function return type for Lambda and Step Function code --- src/commands/lambda/flare.ts | 35 +++++++++++------ src/commands/lambda/functions/commons.ts | 39 ++++++++++++------- src/commands/lambda/functions/instrument.ts | 2 +- src/commands/lambda/functions/uninstrument.ts | 5 ++- src/commands/lambda/instrument.ts | 8 ++-- src/commands/lambda/loggroup.ts | 27 +++++++++---- src/commands/lambda/prompt.ts | 10 ++--- src/commands/lambda/tags.ts | 16 +++++--- src/commands/lambda/uninstrument.ts | 4 +- src/commands/stepfunctions/instrument.ts | 2 +- src/commands/stepfunctions/uninstrument.ts | 2 +- 11 files changed, 97 insertions(+), 53 deletions(-) diff --git a/src/commands/lambda/flare.ts b/src/commands/lambda/flare.ts index 42a60cbf4..a5b1c2113 100644 --- a/src/commands/lambda/flare.ts +++ b/src/commands/lambda/flare.ts @@ -83,7 +83,7 @@ export class LambdaFlareCommand extends Command { * Lambda function and sends them to Datadog support. * @returns 0 if the command ran successfully, 1 otherwise. */ - public async execute() { + public async execute(): Promise<0 | 1> { this.context.stdout.write(helpersRenderer.renderFlareHeader('Lambda', this.isDryRun)) // Validate function name @@ -425,7 +425,7 @@ export class LambdaFlareCommand extends Command { * @param config * @returns a summarized config */ -export const summarizeConfig = (config: any) => { +export const summarizeConfig = (config: any): any => { const summarizedConfig: any = {} for (const key in config) { if (SUMMARIZED_FIELDS.has(key)) { @@ -450,7 +450,7 @@ export const getLogStreamNames = async ( logGroupName: string, startMillis?: number, endMillis?: number -) => { +): Promise => { const config = { logGroupName, descending: true, @@ -507,7 +507,7 @@ export const getLogEvents = async ( logStreamName: string, startMillis?: number, endMillis?: number -) => { +): Promise => { const config: any = { logGroupName, logStreamName, @@ -537,7 +537,12 @@ export const getLogEvents = async ( * @param endMillis end time in milliseconds or undefined if no end time is specified * @returns a map of log stream names to log events or an empty map if no logs are found */ -export const getAllLogs = async (region: string, functionName: string, startMillis?: number, endMillis?: number) => { +export const getAllLogs = async ( + region: string, + functionName: string, + startMillis?: number, + endMillis?: number +): Promise> => { const logs = new Map() const cwlClient = new CloudWatchLogsClient({region, retryStrategy: EXPONENTIAL_BACKOFF_RETRY_STRATEGY}) if (functionName.startsWith('arn:aws')) { @@ -574,7 +579,11 @@ export const getAllLogs = async (region: string, functionName: string, startMill * @returns the tags or an empty object if no tags are found * @throws Error if the tags cannot be retrieved */ -export const getTags = async (lambdaClient: LambdaClient, region: string, arn: string) => { +export const getTags = async ( + lambdaClient: LambdaClient, + region: string, + arn: string +): Promise> => { if (!arn.startsWith('arn:aws')) { throw Error(`Invalid function ARN: ${arn}`) } @@ -601,7 +610,7 @@ export const getTags = async (lambdaClient: LambdaClient, region: string, arn: s * @param filePaths the list of file paths * @returns a mapping of file paths to new file names */ -export const getUniqueFileNames = (filePaths: Set) => { +export const getUniqueFileNames = (filePaths: Set): Map => { // Count occurrences of each filename const fileNameCount: {[fileName: string]: number} = {} filePaths.forEach((filePath) => { @@ -634,7 +643,7 @@ export const getUniqueFileNames = (filePaths: Set) => { * @param logEvents array of log events * @returns the CSV string */ -export const convertToCSV = (logEvents: OutputLogEvent[]) => { +export const convertToCSV = (logEvents: OutputLogEvent[]): string => { const rows = [['timestamp', 'datetime', 'message']] for (const logEvent of logEvents) { const timestamp = `"${logEvent.timestamp ?? ''}"` @@ -653,7 +662,7 @@ export const convertToCSV = (logEvents: OutputLogEvent[]) => { /** * @param ms number of milliseconds to sleep */ -export const sleep = async (ms: number) => { +export const sleep = async (ms: number): Promise => { await new Promise((resolve) => setTimeout(resolve, ms)) } @@ -661,7 +670,7 @@ export const sleep = async (ms: number) => { * Get the framework used based on the files in the directory * @returns the framework used or undefined if no framework is found */ -export const getFramework = () => { +export const getFramework = (): string => { const frameworks = new Set() const files = fs.readdirSync(process.cwd()) files.forEach((file) => { @@ -683,7 +692,11 @@ export const getFramework = () => { * @param isDryRun whether or not this is a dry run * @param config Lambda function configuration */ -export const generateInsightsFile = (insightsFilePath: string, isDryRun: boolean, config: FunctionConfiguration) => { +export const generateInsightsFile = ( + insightsFilePath: string, + isDryRun: boolean, + config: FunctionConfiguration +): void => { const lines: string[] = [] // Header lines.push('# Flare Insights') diff --git a/src/commands/lambda/functions/commons.ts b/src/commands/lambda/functions/commons.ts index 6b846b709..587c79a5e 100644 --- a/src/commands/lambda/functions/commons.ts +++ b/src/commands/lambda/functions/commons.ts @@ -54,7 +54,11 @@ import {applyTagConfig} from '../tags' * @param layerARNs an array of layer ARNs. * @returns an array of layer ARNs. */ -export const addLayerArn = (fullLayerArn: string | undefined, previousLayerName: string, layerARNs: string[]) => { +export const addLayerArn = ( + fullLayerArn: string | undefined, + previousLayerName: string, + layerARNs: string[] +): string[] => { if (fullLayerArn) { if (!layerARNs.includes(fullLayerArn)) { // Remove any other versions of the layer @@ -137,7 +141,7 @@ export const collectFunctionsByRegion = ( * @param region the region where the layer is stored. * @returns the latest version of the layer to find. */ -export const findLatestLayerVersion = async (layer: LayerKey, region: string) => { +export const findLatestLayerVersion = async (layer: LayerKey, region: string): Promise => { let latestVersion = 0 let searchStep = latestVersion > 0 ? 1 : 100 @@ -218,7 +222,7 @@ export const getAWSFileCredentialsParams = (profile: string): FromIniInit => { * @param {string} profile the AWS Credentials profile * @returns {AwsCredentialIdentity} credentials object. */ -export const getAWSProfileCredentials = async (profile: string) => { +export const getAWSProfileCredentials = async (profile: string): Promise => { const init = getAWSFileCredentialsParams(profile) try { @@ -233,7 +237,7 @@ export const getAWSProfileCredentials = async (profile: string) => { } } -export const getAWSCredentials = async () => { +export const getAWSCredentials = async (): Promise => { const provider = fromNodeProviderChain() try { @@ -250,24 +254,25 @@ export const getAWSCredentials = async () => { } } -export const isMissingAnyDatadogApiKeyEnvVar = () => +export const isMissingAnyDatadogApiKeyEnvVar = (): boolean => !( process.env[CI_API_KEY_ENV_VAR] || process.env[API_KEY_ENV_VAR] || process.env[CI_KMS_API_KEY_ENV_VAR] || process.env[CI_API_KEY_SECRET_ARN_ENV_VAR] ) -export const isMissingDatadogEnvVars = () => +export const isMissingDatadogEnvVars = (): boolean => !isValidDatadogSite(process.env[CI_SITE_ENV_VAR]) || isMissingAnyDatadogApiKeyEnvVar() -export const getAllLambdaFunctionConfigs = async (lambdaClient: LambdaClient) => +export const getAllLambdaFunctionConfigs = async (lambdaClient: LambdaClient): Promise => getLambdaFunctionConfigsFromRegex(lambdaClient, '.') // Returns false if not all runtimes are of the same RuntimeType across multiple functions -export const checkRuntimeTypesAreUniform = (configList: FunctionConfiguration[]) => +export const checkRuntimeTypesAreUniform = (configList: FunctionConfiguration[]): boolean => configList .map((item) => item.lambdaConfig.Runtime) .every((runtime) => RUNTIME_LOOKUP[runtime!] === RUNTIME_LOOKUP[configList[0].lambdaConfig.Runtime!]) + /** * Given a Lambda instance and a regular expression, * returns all the Function Configurations that match. @@ -321,6 +326,7 @@ export const getLambdaFunctionConfigs = ( * and settings (optional). * * @param config a Lambda FunctionConfiguration. + * @param layer a Lambda layer. * @param region a region where the layer is hosted. * @param settings instrumentation settings, mainly used to change the AWS account that contains the Layer. * @returns the ARN of a **Specific Runtime Layer** with the correct region, account, architecture, and name. @@ -330,7 +336,7 @@ export const getLayerArn = ( layer: LayerKey, region: string, settings?: InstrumentationSettings -) => { +): string => { let layerName = LAYER_LOOKUP[layer] if (ARM_LAYERS.includes(layer) && config.Architectures?.includes(ARM64_ARCHITECTURE)) { layerName += ARM_LAYER_SUFFIX @@ -350,7 +356,7 @@ export const getLayerNameWithVersion = (layerArn: string): string | undefined => return name && version ? `${name}:${version}` : undefined } -export const getLayers = (config: LFunctionConfiguration) => (config.Layers ?? []).map((layer) => layer.Arn!) +export const getLayers = (config: LFunctionConfiguration): string[] => (config.Layers ?? []).map((layer) => layer.Arn!) /** * Call the aws-sdk Lambda api to get a Function given @@ -406,7 +412,7 @@ export const updateLambdaFunctionConfig = async ( lambdaClient: LambdaClient, cloudWatchLogsClient: CloudWatchLogsClient, config: FunctionConfiguration -) => { +): Promise => { if (config.updateFunctionConfigurationCommandInput !== undefined) { await updateFunctionConfiguration(lambdaClient, config.updateFunctionConfigurationCommandInput) } @@ -421,12 +427,15 @@ export const updateLambdaFunctionConfig = async ( export const updateFunctionConfiguration = async ( client: LambdaClient, input: UpdateFunctionConfigurationCommandInput -) => { +): Promise => { const command = new UpdateFunctionConfigurationCommand(input) await client.send(command) } -export const handleLambdaFunctionUpdates = async (configGroups: InstrumentedConfigurationGroup[], stdout: Writable) => { +export const handleLambdaFunctionUpdates = async ( + configGroups: InstrumentedConfigurationGroup[], + stdout: Writable +): Promise => { let totalFunctions = 0 let totalFailedUpdates = 0 for (const group of configGroups) { @@ -482,7 +491,7 @@ export const handleLambdaFunctionUpdates = async (configGroups: InstrumentedConf } } -export const willUpdateFunctionConfigs = (configs: FunctionConfiguration[]) => { +export const willUpdateFunctionConfigs = (configs: FunctionConfiguration[]): boolean => { let willUpdate = false for (const config of configs) { if ( @@ -507,7 +516,7 @@ export const willUpdateFunctionConfigs = (configs: FunctionConfiguration[]) => { * @param config * @returns masked config */ -export const maskConfig = (config: any) => { +export const maskConfig = (config: any): any => { // We stringify and parse again to make a deep copy const configCopy = JSON.parse(JSON.stringify(config)) const vars = configCopy.Environment?.Variables diff --git a/src/commands/lambda/functions/instrument.ts b/src/commands/lambda/functions/instrument.ts index 8410ffc60..354a6d0dd 100644 --- a/src/commands/lambda/functions/instrument.ts +++ b/src/commands/lambda/functions/instrument.ts @@ -156,7 +156,7 @@ export const calculateUpdateRequest = async ( settings: InstrumentationSettings, region: string, runtime: Runtime -) => { +): Promise => { const oldEnvVars: Record = {...config.Environment?.Variables} const changedEnvVars: Record = {} const functionARN = config.FunctionArn diff --git a/src/commands/lambda/functions/uninstrument.ts b/src/commands/lambda/functions/uninstrument.ts index 5fe36c34d..26e80745e 100644 --- a/src/commands/lambda/functions/uninstrument.ts +++ b/src/commands/lambda/functions/uninstrument.ts @@ -116,7 +116,10 @@ export const getUninstrumentedFunctionConfigsFromRegEx = async ( return functionsToUpdate } -export const calculateUpdateRequest = (config: LFunctionConfiguration, runtime: Runtime) => { +export const calculateUpdateRequest = ( + config: LFunctionConfiguration, + runtime: Runtime +): UpdateFunctionConfigurationRequest | undefined => { const oldEnvVars: Record = {...config.Environment?.Variables} const functionARN = config.FunctionArn diff --git a/src/commands/lambda/instrument.ts b/src/commands/lambda/instrument.ts index 01f97f634..91ffbdd27 100644 --- a/src/commands/lambda/instrument.ts +++ b/src/commands/lambda/instrument.ts @@ -83,7 +83,7 @@ export class InstrumentCommand extends Command { private credentials?: AwsCredentialIdentity - public async execute() { + public async execute(): Promise<0 | 1> { this.context.stdout.write(instrumentRenderer.renderLambdaHeader(Object.getPrototypeOf(this), this.dryRun)) const lambdaConfig = {lambda: this.config} @@ -392,7 +392,7 @@ export class InstrumentCommand extends Command { return {commitSha: currentStatus.hash, gitRemote} } - private async uploadGitData() { + private async uploadGitData(): Promise { const cli = new Cli() cli.register(UploadCommand) if ((await cli.run(['git-metadata', 'upload'], this.context)) !== 0) { @@ -499,7 +499,7 @@ export class InstrumentCommand extends Command { } } - private printPlannedActions(configs: FunctionConfiguration[]) { + private printPlannedActions(configs: FunctionConfiguration[]): void { const willUpdate = willUpdateFunctionConfigs(configs) if (!willUpdate) { this.context.stdout.write(instrumentRenderer.renderNoUpdatesApplied(this.dryRun)) @@ -568,7 +568,7 @@ export class InstrumentCommand extends Command { } } - private setEnvServiceVersion() { + private setEnvServiceVersion(): void { this.environment = process.env[ENVIRONMENT_ENV_VAR] || undefined this.service = process.env[SERVICE_ENV_VAR] || undefined this.version = process.env[VERSION_ENV_VAR] || undefined diff --git a/src/commands/lambda/loggroup.ts b/src/commands/lambda/loggroup.ts index 49b99d47b..a1c09a147 100644 --- a/src/commands/lambda/loggroup.ts +++ b/src/commands/lambda/loggroup.ts @@ -10,6 +10,7 @@ import { DescribeSubscriptionFiltersCommandInput, PutSubscriptionFilterCommand, PutSubscriptionFilterCommandInput, + SubscriptionFilter, } from '@aws-sdk/client-cloudwatch-logs' import {SUBSCRIPTION_FILTER_NAME} from './constants' @@ -24,7 +25,10 @@ export enum SubscriptionState { const MAX_LOG_GROUP_SUBSCRIPTIONS = 2 -export const applyLogGroupConfig = async (client: CloudWatchLogsClient, config: LogGroupConfiguration) => { +export const applyLogGroupConfig = async ( + client: CloudWatchLogsClient, + config: LogGroupConfiguration +): Promise => { const {createLogGroupCommandInput, deleteSubscriptionFilterCommandInput, putSubscriptionFilterCommandInput} = config if (createLogGroupCommandInput !== undefined) { await createLogGroup(client, createLogGroupCommandInput) @@ -37,7 +41,10 @@ export const applyLogGroupConfig = async (client: CloudWatchLogsClient, config: } } -export const createLogGroup = async (client: CloudWatchLogsClient, input: CreateLogGroupCommandInput) => { +export const createLogGroup = async ( + client: CloudWatchLogsClient, + input: CreateLogGroupCommandInput +): Promise => { const command = new CreateLogGroupCommand(input) await client.send(command) } @@ -50,7 +57,10 @@ export const deleteSubscriptionFilter = async ( await client.send(command) } -export const putSubscriptionFilter = async (client: CloudWatchLogsClient, input: PutSubscriptionFilterCommandInput) => { +export const putSubscriptionFilter = async ( + client: CloudWatchLogsClient, + input: PutSubscriptionFilterCommandInput +): Promise => { const command = new PutSubscriptionFilterCommand(input) await client.send(command) } @@ -59,7 +69,7 @@ export const calculateLogGroupUpdateRequest = async ( client: CloudWatchLogsClient, logGroupName: string, forwarderARN: string -) => { +): Promise => { const config: LogGroupConfiguration = { logGroupName, putSubscriptionFilterCommandInput: { @@ -99,7 +109,7 @@ export const calculateLogGroupRemoveRequest = async ( client: CloudWatchLogsClient, logGroupName: string, forwarderARN: string -) => { +): Promise => { const config: LogGroupConfiguration = { logGroupName, } @@ -140,7 +150,7 @@ export const getSubscriptionFilterState = async ( client: CloudWatchLogsClient, logGroupName: string, forwarderARN: string -) => { +): Promise => { const subscriptionFilters = await getSubscriptionFilters(client, logGroupName) if (subscriptionFilters === undefined || subscriptionFilters.length === 0) { return SubscriptionState.Empty @@ -162,7 +172,10 @@ export const getSubscriptionFilterState = async ( return SubscriptionState.WrongDestinationUnowned } -export const getSubscriptionFilters = async (client: CloudWatchLogsClient, logGroupName: string) => { +export const getSubscriptionFilters = async ( + client: CloudWatchLogsClient, + logGroupName: string +): Promise => { const input: DescribeSubscriptionFiltersCommandInput = { logGroupName, } diff --git a/src/commands/lambda/prompt.ts b/src/commands/lambda/prompt.ts index 4cc74b7b5..7cf9a5280 100644 --- a/src/commands/lambda/prompt.ts +++ b/src/commands/lambda/prompt.ts @@ -208,7 +208,7 @@ export const functionSelectionQuestion = (functionNames: string[]): typeof check }, }) -export const requestAWSCredentials = async () => { +export const requestAWSCredentials = async (): Promise => { try { const awsCredentialsAnswers = await inquirer.prompt(awsCredentialsQuestions) process.env[AWS_ACCESS_KEY_ID_ENV_VAR] = awsCredentialsAnswers[AWS_ACCESS_KEY_ID_ENV_VAR] @@ -223,7 +223,7 @@ export const requestAWSCredentials = async () => { } } -export const requestAWSRegion = async (defaultRegion?: string) => { +export const requestAWSRegion = async (defaultRegion?: string): Promise => { try { const awsRegionAnswer = await inquirer.prompt(awsRegionQuestion(defaultRegion)) process.env[AWS_DEFAULT_REGION_ENV_VAR] = awsRegionAnswer[AWS_DEFAULT_REGION_ENV_VAR] @@ -234,7 +234,7 @@ export const requestAWSRegion = async (defaultRegion?: string) => { } } -export const requestDatadogEnvVars = async () => { +export const requestDatadogEnvVars = async (): Promise => { try { const envSite = process.env[CI_SITE_ENV_VAR] let selectedDatadogSite = envSite @@ -258,7 +258,7 @@ export const requestDatadogEnvVars = async () => { } } -export const requestEnvServiceVersion = async () => { +export const requestEnvServiceVersion = async (): Promise => { try { const envQuestionAnswer = await inquirer.prompt(envQuestion) const inputedEnvQuestionAnswer = envQuestionAnswer[ENVIRONMENT_ENV_VAR] @@ -278,7 +278,7 @@ export const requestEnvServiceVersion = async () => { } } -export const requestFunctionSelection = async (functionNames: string[]) => { +export const requestFunctionSelection = async (functionNames: string[]): Promise => { try { const selectedFunctionsAnswer: any = await inquirer.prompt(functionSelectionQuestion(functionNames)) diff --git a/src/commands/lambda/tags.ts b/src/commands/lambda/tags.ts index c088c4b26..940131256 100644 --- a/src/commands/lambda/tags.ts +++ b/src/commands/lambda/tags.ts @@ -13,7 +13,7 @@ import {version} from '../../helpers/version' import {TAG_VERSION_NAME} from './constants' import {TagConfiguration} from './interfaces' -export const applyTagConfig = async (lambdaClient: LambdaClient, config: TagConfiguration) => { +export const applyTagConfig = async (lambdaClient: LambdaClient, config: TagConfiguration): Promise => { const {tagResourceCommandInput, untagResourceCommandInput} = config if (tagResourceCommandInput !== undefined) { await tagResource(lambdaClient, tagResourceCommandInput) @@ -23,17 +23,20 @@ export const applyTagConfig = async (lambdaClient: LambdaClient, config: TagConf } } -export const tagResource = async (client: LambdaClient, input: TagResourceCommandInput) => { +export const tagResource = async (client: LambdaClient, input: TagResourceCommandInput): Promise => { const command = new TagResourceCommand(input) await client.send(command) } -export const untagResource = async (client: LambdaClient, input: UntagResourceCommandInput) => { +export const untagResource = async (client: LambdaClient, input: UntagResourceCommandInput): Promise => { const command = new UntagResourceCommand(input) await client.send(command) } -export const calculateTagUpdateRequest = async (lambdaClient: LambdaClient, functionARN: string) => { +export const calculateTagUpdateRequest = async ( + lambdaClient: LambdaClient, + functionARN: string +): Promise => { const config: TagConfiguration = {} const versionTagPresent = await hasVersionTag(lambdaClient, functionARN) @@ -52,7 +55,10 @@ export const calculateTagUpdateRequest = async (lambdaClient: LambdaClient, func return } -export const calculateTagRemoveRequest = async (lambdaClient: LambdaClient, functionARN: string) => { +export const calculateTagRemoveRequest = async ( + lambdaClient: LambdaClient, + functionARN: string +): Promise => { const config: TagConfiguration = {} const versionTagPresent = await hasVersionTag(lambdaClient, functionARN) if (versionTagPresent) { diff --git a/src/commands/lambda/uninstrument.ts b/src/commands/lambda/uninstrument.ts index 05534bd16..39075d44a 100644 --- a/src/commands/lambda/uninstrument.ts +++ b/src/commands/lambda/uninstrument.ts @@ -66,7 +66,7 @@ export class UninstrumentCommand extends Command { private credentials?: AwsCredentialIdentity - public async execute() { + public async execute(): Promise<0 | 1> { this.context.stdout.write(instrumentRenderer.renderLambdaHeader(Object.getPrototypeOf(this), this.dryRun)) const lambdaConfig = {lambda: this.config} @@ -278,7 +278,7 @@ export class UninstrumentCommand extends Command { return 0 } - private printPlannedActions(configs: FunctionConfiguration[]) { + private printPlannedActions(configs: FunctionConfiguration[]): void { const willUpdate = willUpdateFunctionConfigs(configs) if (!willUpdate) { diff --git a/src/commands/stepfunctions/instrument.ts b/src/commands/stepfunctions/instrument.ts index 2884dd4b9..8a46966ef 100644 --- a/src/commands/stepfunctions/instrument.ts +++ b/src/commands/stepfunctions/instrument.ts @@ -62,7 +62,7 @@ export class InstrumentStepFunctionsCommand extends Command { ) private propagateUpstreamTrace = Option.Boolean('--propagate-upstream-trace', false) - public async execute() { + public async execute(): Promise<0 | 1> { let validationError = false if (typeof this.forwarderArn !== 'string') { this.context.stdout.write('[Error] `--forwarder` is required\n') diff --git a/src/commands/stepfunctions/uninstrument.ts b/src/commands/stepfunctions/uninstrument.ts index 5a9352620..b33309101 100644 --- a/src/commands/stepfunctions/uninstrument.ts +++ b/src/commands/stepfunctions/uninstrument.ts @@ -43,7 +43,7 @@ export class UninstrumentStepFunctionsCommand extends Command { {hidden: true} ) - public async execute() { + public async execute(): Promise<0 | 1> { let validationError = false let hasChanges = false