将 SSM 值转换为数字
Converting SSM Value To Number
我正在尝试使用范围过滤策略通过无服务器框架将 SNS 订阅部署到 AWS。我的资源定义如下所示:
MySusbscription:
Type: AWS::SNS::Subscription
Properties:
TopicArn:
Ref: MyTopic
Endpoint: !GetAtt MyQueue.Arn
Protocol: sqs
RawMessageDelivery: true
FilterPolicy:
percentage:
- numeric:
- '>='
- ${ssm:/path/to/ssm/key}
RedrivePolicy:
deadLetterTargetArn: !GetAtt MyQueueDlq.Arn
问题在于 Serverless 将所有 SSM 值作为字符串提取,因此部署配置的编译版本将为:
- numeric:
- '>='
- '0.25'
这将无法部署,因为 SNS 要求 0.25
是数字而不是字符串。 Serverless 有一个 strToBool
函数,但我没有看到文档表明有一个等效函数可以转换为 number/float.
我确定我可以通过使用 env 变量来解决这个问题,但是我们将所有配置存储在 SSM 中,我希望不必一次性解决这个问题。
第一个解决方案不是最干净的,但肯定会奏效。
在目录中使用以下脚本定义您的自定义 JS 文件 ssmToNumber.js
:
const AWS = require('aws-sdk');
module.exports = async (serverless) => {
# Setup AWS SDK with region and profile
const { region } = serverless.processedInput.options;
AWS.config.update({ region });
if (serverless.processedInput.options['aws-profile']) {
process.env.AWS_PROFILE = serverless.processedInput.options['aws-profile'];
}
const ssm = new AWS.SSM({ apiVersion: '2014-11-06' });
# Get SSM params details from serverless.yml
const ssmKey = serverless.service.custom.ssmKeys.percentageNumericThreshold.path;
const decryption = serverless.service.custom.ssmKeys.percentageNumericThreshold.decryption;
# Get SSM parameter value and convert it to int
const result = await ssm.getParameter({
Name: ssmKey,
WithDecryption: decryption,
}).promise();
if (result.Parameter) {
return parseInt(result.Parameter.Value, 10);
}
throw new Error(`Failed to read SSM parameter for key ${ssmKey}`);
};
现在在 serverless.yml
中定义以下值:
custom:
ssmKeys:
percentageNumericThreshold:
path: '/path/to/ssm/key'
decryption: false
在您想从 SSM 获取数值的地方,只需这样调用它:
FilterPolicy:
percentage:
- numeric:
- '>='
- ${file(./ssmToNumber.js)}
它是如何工作的?
Serverless Framework 可以在构建期间启动任何 JavaScript/TypeScript 文件并将其输出到 serverless.yml
文件中。
这正是我们在这里所做的。我们定义 ssmToNumber.js
脚本,它只是从 SSM 读取 SSM 参数,然后将其转换为整数和 returns 值。
由于 serverless.yml
文件中的 custom.ssmKeys
部分,它知道要使用哪个 SSM 路径。
当然如果你想定制ssmToNumber.js
文件,让它更详细和容错,那么你只需要编辑JavaScript文件。
另一种更优雅的方式
它需要更多的工作。查看 Serverless with Typescript.
的官方示例
如您所见,可以使用 serverless.ts
或 serverless.js
代替 YAML 文件。
这需要你做一些关于重构现有 YML 文件的工作,但是编写辅助函数,将其转换为数字,是实现你的用例的非常简单和优雅的方法。
它有一些缺点,比如直接包含其他 YAML 模板的问题,但您仍然可以在单独的文件中定义您的 CloudFormation YAML 模板,然后使用 import
从 TS/JS 代码调用简单地导入这些模板.
我正在尝试使用范围过滤策略通过无服务器框架将 SNS 订阅部署到 AWS。我的资源定义如下所示:
MySusbscription:
Type: AWS::SNS::Subscription
Properties:
TopicArn:
Ref: MyTopic
Endpoint: !GetAtt MyQueue.Arn
Protocol: sqs
RawMessageDelivery: true
FilterPolicy:
percentage:
- numeric:
- '>='
- ${ssm:/path/to/ssm/key}
RedrivePolicy:
deadLetterTargetArn: !GetAtt MyQueueDlq.Arn
问题在于 Serverless 将所有 SSM 值作为字符串提取,因此部署配置的编译版本将为:
- numeric:
- '>='
- '0.25'
这将无法部署,因为 SNS 要求 0.25
是数字而不是字符串。 Serverless 有一个 strToBool
函数,但我没有看到文档表明有一个等效函数可以转换为 number/float.
我确定我可以通过使用 env 变量来解决这个问题,但是我们将所有配置存储在 SSM 中,我希望不必一次性解决这个问题。
第一个解决方案不是最干净的,但肯定会奏效。
在目录中使用以下脚本定义您的自定义 JS 文件 ssmToNumber.js
:
const AWS = require('aws-sdk');
module.exports = async (serverless) => {
# Setup AWS SDK with region and profile
const { region } = serverless.processedInput.options;
AWS.config.update({ region });
if (serverless.processedInput.options['aws-profile']) {
process.env.AWS_PROFILE = serverless.processedInput.options['aws-profile'];
}
const ssm = new AWS.SSM({ apiVersion: '2014-11-06' });
# Get SSM params details from serverless.yml
const ssmKey = serverless.service.custom.ssmKeys.percentageNumericThreshold.path;
const decryption = serverless.service.custom.ssmKeys.percentageNumericThreshold.decryption;
# Get SSM parameter value and convert it to int
const result = await ssm.getParameter({
Name: ssmKey,
WithDecryption: decryption,
}).promise();
if (result.Parameter) {
return parseInt(result.Parameter.Value, 10);
}
throw new Error(`Failed to read SSM parameter for key ${ssmKey}`);
};
现在在 serverless.yml
中定义以下值:
custom:
ssmKeys:
percentageNumericThreshold:
path: '/path/to/ssm/key'
decryption: false
在您想从 SSM 获取数值的地方,只需这样调用它:
FilterPolicy:
percentage:
- numeric:
- '>='
- ${file(./ssmToNumber.js)}
它是如何工作的?
Serverless Framework 可以在构建期间启动任何 JavaScript/TypeScript 文件并将其输出到 serverless.yml
文件中。
这正是我们在这里所做的。我们定义 ssmToNumber.js
脚本,它只是从 SSM 读取 SSM 参数,然后将其转换为整数和 returns 值。
由于 serverless.yml
文件中的 custom.ssmKeys
部分,它知道要使用哪个 SSM 路径。
当然如果你想定制ssmToNumber.js
文件,让它更详细和容错,那么你只需要编辑JavaScript文件。
另一种更优雅的方式
它需要更多的工作。查看 Serverless with Typescript.
的官方示例如您所见,可以使用 serverless.ts
或 serverless.js
代替 YAML 文件。
这需要你做一些关于重构现有 YML 文件的工作,但是编写辅助函数,将其转换为数字,是实现你的用例的非常简单和优雅的方法。
它有一些缺点,比如直接包含其他 YAML 模板的问题,但您仍然可以在单独的文件中定义您的 CloudFormation YAML 模板,然后使用 import
从 TS/JS 代码调用简单地导入这些模板.