【问题标题】:CloudFormation large responses with with AwsCustomResource AWS SDK calls (CodeArtifact getPackageVersionAsset)使用 AwsCustomResource AWS 开发工具包调用 (CodeArtifact getPackageVersionAsset) 的 CloudFormation 大型响应
【发布时间】:2020-11-03 13:20:14
【问题描述】:

我发现了一些关于使用 AwsCustomResource 从 AWS CDK 构造中进行 AWS 开发工具包调用的问题和答案,但没有关于响应可能很大的用例,并且 cfn 超过了大约 4KB 的限制回复。

我的目标是能够从我的 CDK 堆栈中获取小型 codeartifact 存储资产。最初我从我的 CDK 构造中调用 AWS 开发工具包开始,但后来意识到我会遇到竞争条件,因为 CDK 构造并不意味着运行异步代码。

然后我考虑使用 AwsCustomResource 为 CodeArtifact 执行 getPackageVersionAsset SDK 调用,但现在我的问题是响应对于 CFN 响应来说太大了。

这是我所拥有的,但它不适用于大于几 KB 的响应。

const namespace = new AwsCustomResource(this, 'custom-resource', {
  onUpdate: {
    physicalResourceId: PhysicalResourceId.of('codeartifact-stored-artifact-namespace'),
    service: 'CodeArtifact',
    action: 'getPackageVersionAsset',
    parameters: {
      repository: codeartifactCoordinates.repository,
      domain: codeartifactCoordinates.domain,
      domainOwner: codeartifactCoordinates.domainOwner,
      format: codeartifactCoordinates.format,
      namespace: codeartifactCoordinates.groupId,
      package: codeartifactCoordinates.artifactId,
      packageVersion: codeartifactCoordinates.version,
      asset: `${codeartifactCoordinates.artifactId}-${codeartifactCoordinates.version}-${codeartifactCoordinates.classifier}.zip`
    }
  },
  policy: AwsCustomResourcePolicy.fromSdkCalls({resources: AwsCustomResourcePolicy.ANY_RESOURCE})
});

const result = namespace.getResponseField('Data');

作为比较,这是我在 Construct 中使用客户端调用 sdk 时开始使用的 AWS 开发工具包代码:

const outputFile = `artifact-${crypto.randomBytes(16).toString("hex")}.yml`;
const file = require('fs').createWriteStream(outputFile);
const params : AWS.CodeArtifact.GetPackageVersionAssetRequest = {
    domain: codeartifactCoordinates.domain,
    domainOwner: codeartifactCoordinates.domainOwner,
    repository: codeartifactCoordinates.repository,
    format: codeartifactCoordinates.format,
    namespace: codeartifactCoordinates.groupId,
    package: codeartifactCoordinates.artifactId,
    packageVersion: codeartifactCoordinates.version,
    asset: `${codeartifactCoordinates.artifactId}-${codeartifactCoordinates.version}-${codeartifactCoordinates.classifier}.yml`
};

return new Promise((resolve, reject) => {
    codeartifact
        .getPackageVersionAsset(params)
        .createReadStream()
        .on('end', () => {
            const data = fs.readFileSync(outputFile, "utf-8");
            const yamlNs = YAML.parse(data);
            return resolve(yamlNs);
        })
        .on('error', (error) => {
            return reject(error);
        })
        .pipe(file)
    
});

有没有更好的模式呢?或者,有没有一种方法可以在我的 Construct 中执行 AWS 开发工具包调用,让我可以等待资产响应调用完成并避免竞争条件?

【问题讨论】:

    标签: aws-cdk


    【解决方案1】:

    所以我最终为此使用了 nodejs child_process spawnSync() 方法。它从运行 CDK 的节点进程生成一个同步子进程。我在此过程中运行 AWS CLI 以与 AWS CodeArtifact(在我的特定情况下)通信并检索大文件资产。

    当然,您可以在此处使用任何 AWS CLI 命令,只需根据需要设置 CLI 参数即可。

    import * as fs from "fs"
    import * as path from "path"
    import * as crypto from "crypto"
    import * as cp from 'child_process';
    
    export interface CodeArtifactCoordinatesType {
    
        readonly repository: string;
    
        readonly domain: string;
    
        readonly domainOwner: string;
    
        readonly format: string;
    
        readonly groupId: string;
    
        readonly artifactId: string;
    
        readonly version: string;
    
        readonly classifier: string;
    }
    
    export class YourClassNameHere {
        static fromCodeArtifactCoordinates(codeartifactCoordinates: CodeArtifactCoordinatesType) : any {
    
            const outputFile = `${codeartifactCoordinates.artifactId}-${codeartifactCoordinates.version}-${codeartifactCoordinates.classifier}.ext`;
            var getPackageVersionAssetProcess = cp.spawnSync('aws', [
                'codeartifact',
                'get-package-version-asset',
                '--domain',
                codeartifactCoordinates.domain,
                '--domain-owner',
                codeartifactCoordinates.domainOwner,
                '--repository',
                codeartifactCoordinates.repository,
                '--format',
                codeartifactCoordinates.format,
                '--namespace',
                codeartifactCoordinates.groupId,
                '--package',
                codeartifactCoordinates.artifactId,
                '--package-version',
                codeartifactCoordinates.version,
                '--asset',
                outputFile,
                outputFile
            ], {stdio: [0, 1, 2]});
    
            if (getPackageVersionAssetProcess.error) {
                console.error(getPackageVersionAssetProcess.error.stack);
                throw "Error executing 'get-package-version-asset' aws cli command."
            } else if (getPackageVersionAssetProcess.stderr) {
                console.error(getPackageVersionAssetProcess.stderr);
                throw "aws codeartifact get-package-version-asset command parameters caused an error."
            } else {
                const data = fs.readFileSync(outputFile, "utf-8");
                return data;
            }
        }
    }
    

    然后您可以将其作为静态方法调用。例如

    const data = YourClassNameHere.fromCodeArtifactCoordinates(codeartifactCoordinates);
    

    codeartifactCoordinates 当然是一个包含来自CodeArtifactCoordinatesType 接口的各种属性的对象。即repositorydomain等...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-29
      • 2020-01-03
      • 2020-03-14
      • 1970-01-01
      • 1970-01-01
      • 2021-02-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多