Open1

C#でCDKするときのTips

kenfdevkenfdev

CDKデプロイ時にLambdaをビルドしたい

単純に cdk deploy しても、ビルドしていないと最新のコードはデプロイされない。

いろいろなデプロイ方法があるので、↓を参考にすると良い。

4 ways to deploy a .NET Core Lambda using AWS CDK :: my tech ramblings — A blog for writing about my techie ramblings

その中でも、deploy時にビルドするように、以下のような書き方をすることがある。

      IEnumerable<string> commands = new[]
            {
                "cd /asset-input",
                "dotnet lambda package -o output.zip",
                "unzip -o -d /asset-output output.zip"
            };
      new Function(this, "MyFunction", new FunctionProps
      {
        Runtime = Runtime.DOTNET_6,
        Code = Code.FromAsset("./src/MyFunction/src/MyFunction", new Amazon.CDK.AWS.S3.Assets.AssetOptions
        {
          Bundling = new BundlingOptions
          {
            Image = Runtime.DOTNET_6.BundlingImage,
            Command = new[] { "bash", "-c", string.Join(" && ", commands) }
          },
        }),
        Handler = "MyFunction::MyFunction.Function::FunctionHandler"
      });

この状態で cdk synth やdeployすると、パーミッションエラーになることがある。

'/.dotnet' is denied. がポイント。

Bundling asset CdkDotnetStack/MyFunction/Code/Stage...
System.UnauthorizedAccessException: Access to the path '/.dotnet' is denied.
 ---> System.IO.IOException: Permission denied
   --- End of inner exception stack trace ---
   at System.IO.FileSystem.CreateDirectory(String fullPath)
   at System.IO.Directory.CreateDirectory(String path)
   at Microsoft.Extensions.EnvironmentAbstractions.DirectoryWrapper.CreateDirectory(String path)
   at Microsoft.DotNet.Configurer.FileSystemExtensions.<>c__DisplayClass0_0.<CreateIfNotExists>b__0()
   at Microsoft.DotNet.Cli.Utils.FileAccessRetrier.RetryOnIOException(Action action)
   at Microsoft.DotNet.Configurer.FileSystemExtensions.CreateIfNotExists(IFileSystem fileSystem, String filePath)
   at Microsoft.DotNet.Configurer.FileSentinel.Create()
   at Microsoft.DotNet.Configurer.DotnetFirstTimeUseConfigurer.Configure()
   at Microsoft.DotNet.Cli.Program.ConfigureDotNetForFirstTimeUse(IFirstTimeUseNoticeSentinel firstTimeUseNoticeSentinel, IAspNetCertificateSentinel aspNetCertificateSentinel, IFileSentinel toolPathSentinel, Boolean isDotnetBeingInvokedFromNativeInstaller, DotnetFirstRunConfiguration dotnetFirstRunConfiguration, IEnvironmentProvider environmentProvider, Dictionary`2 performanceMeasurements)
   at Microsoft.DotNet.Cli.Program.ProcessArgs(String[] args, TimeSpan startupTime, ITelemetry telemetryClient)
   at Microsoft.DotNet.Cli.Program.Main(String[] args)
Unhandled exception. Amazon.JSII.Runtime.JsiiException: Failed to bundle asset CdkDotnetStack/MyFunction/Code/Stage, bundle output is located at /workspaces/cdk-dotnet/cdk.out/asset.f5ca12e0d3262419e2ec977cb22870b89af995ff3a243d6f283df982a1e1e0fe-error: Error: docker exited with status 1
   at Amazon.JSII.Runtime.Services.Client.TryDeserialize[TResponse](String responseJson)
   at Amazon.JSII.Runtime.Services.Client.ReceiveResponse[TResponse]()
   at Amazon.JSII.Runtime.Services.Client.Send[TRequest,TResponse](TRequest requestObject)
   at Amazon.JSII.Runtime.Services.Client.Create(CreateRequest request)
   at Amazon.JSII.Runtime.Services.Client.Create(String fullyQualifiedName, Object[] arguments, Override[] overrides, String[] interfaces)
   at Amazon.JSII.Runtime.Deputy.DeputyBase..ctor(DeputyProps props)
   at Constructs.Construct..ctor(DeputyProps props)
   at Amazon.CDK.Resource..ctor(DeputyProps props)
   at Amazon.CDK.AWS.Lambda.FunctionBase..ctor(DeputyProps props)
   at Amazon.CDK.AWS.Lambda.Function..ctor(Construct scope, String id, IFunctionProps props)
   at CdkDotnet.CdkDotnetStack..ctor(Construct scope, String id, IStackProps props) in /workspaces/cdk-dotnet/src/CdkDotnet/CdkDotnetStack.cs:line 22
   at CdkDotnet.Program.Main(String[] args) in /workspaces/cdk-dotnet/src/CdkDotnet/Program.cs:line 13

どうやらBundling用のコンテナのパーミッションがうまい具合に機能していない予感(詳しくはみていない)。

応急処置で、以下のように /tmpHOME に切り替えちゃうという荒業を使うと回避できる。

      IEnumerable<string> commands = new[]
            {
                "cd /asset-input",
                "export HOME=\"/tmp\"",
                "dotnet lambda package -o output.zip",
                "unzip -o -d /asset-output output.zip"
            };