将 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.tsserverless.js 代替 YAML 文件。

这需要你做一些关于重构现有 YML 文件的工作,但是编写辅助函数,将其转换为数字,是实现你的用例的非常简单和优雅的方法。

它有一些缺点,比如直接包含其他 YAML 模板的问题,但您仍然可以在单独的文件中定义您的 CloudFormation YAML 模板,然后使用 import 从 TS/JS 代码调用简单地导入这些模板.