/// <summary> /// Determine the action to be done for the local path, like building a .NET Core package, then uploading the /// package to S3. The S3 key is returned to be updated in the template. /// </summary> /// <param name="templateDirectory"></param> /// <param name="field"></param> /// <returns></returns> /// <exception cref="LambdaToolsException"></exception> private async Task <UpdateResourceResults> ProcessUpdatableResourceAsync(string templateDirectory, IUpdateResourceField field, string[] args) { UpdateResourceResults results; var localPath = field.GetLocalPath(); if (!Path.IsPathRooted(localPath)) { localPath = Path.Combine(templateDirectory, localPath); } bool deleteArchiveAfterUploaded = false; // Uploading a single file as the code for the resource. If the single file is not a zip file then zip the file first. if (File.Exists(localPath)) { if (field.IsCode && !string.Equals(Path.GetExtension(localPath), ".zip", StringComparison.OrdinalIgnoreCase)) { this.Logger.WriteLine($"Creating zip archive for {localPath} file"); results = new UpdateResourceResults { ZipArchivePath = GenerateOutputZipFilename(field) }; LambdaPackager.BundleFiles(results.ZipArchivePath, Path.GetDirectoryName(localPath), new string[] { localPath }, this.Logger); } else { results = new UpdateResourceResults { ZipArchivePath = localPath }; } } // If IsCode is false then the local path needs to point to a file and not a directory. When IsCode is true // it can point either to a file or a directory. else if (!field.IsCode && !File.Exists(localPath)) { throw new LambdaToolsException($"File that the field {field.Resource.Name}/{field.Name} is pointing to doesn't exist", LambdaToolsException.LambdaErrorCode.ServerlessTemplateMissingLocalPath); } else if (!Directory.Exists(localPath)) { throw new LambdaToolsException($"Directory that the field {field.Resource.Name}/{field.Name} is pointing doesn't exist", LambdaToolsException.LambdaErrorCode.ServerlessTemplateMissingLocalPath); } // To maintain compatibility if the field is point to current directory or not set at all but a prepackaged zip archive is given // then use it as the package source. else if (IsCurrentDirectory(field.GetLocalPath()) && !string.IsNullOrEmpty(this.DefaultOptions.Package)) { results = new UpdateResourceResults { ZipArchivePath = this.DefaultOptions.Package }; } else if (field.IsCode) { // If the function is image upload then run the .NET tools to handle running // docker build even if the current folder is not a .NET project. The .NET // could be in a sub folder or be a self contained Docker build. if (IsDotnetProjectDirectory(localPath) || field.Resource.UploadType == CodeUploadType.Image) { results = await PackageDotnetProjectAsync(field, localPath, args); } else { results = new UpdateResourceResults { ZipArchivePath = GenerateOutputZipFilename(field) }; LambdaPackager.BundleDirectory(results.ZipArchivePath, localPath, false, this.Logger); } deleteArchiveAfterUploaded = true; } else { throw new LambdaToolsException($"Unable to determine package action for the field {field.Resource.Name}/{field.Name}", LambdaToolsException.LambdaErrorCode.ServerlessTemplateUnknownActionForLocalPath); } if (!string.IsNullOrEmpty(results.ZipArchivePath)) { string s3Key; using (var stream = File.OpenRead(results.ZipArchivePath)) { s3Key = await Utilities.UploadToS3Async(this.Logger, this.S3Client, this.S3Bucket, this.S3Prefix, Path.GetFileName(results.ZipArchivePath), stream); results.S3Key = s3Key; } // Now that the temp zip file is uploaded to S3 clean up by deleting the temp file. if (deleteArchiveAfterUploaded) { try { File.Delete(results.ZipArchivePath); } catch (Exception e) { this.Logger?.WriteLine($"Warning: Unable to delete temporary archive, {results.ZipArchivePath}, after uploading to S3: {e.Message}"); } } } return(results); }
/// <summary> /// Determine the action to be done for the local path, like building a .NET Core package, then uploading the /// package to S3. The S3 key is returned to be updated in the template. /// </summary> /// <param name="templateDirectory"></param> /// <param name="field"></param> /// <returns></returns> /// <exception cref="LambdaToolsException"></exception> private async Task <string> ProcessUpdatableResourceAsync(string templateDirectory, IUpdateResourceField field) { var localPath = field.GetLocalPath(); if (!Path.IsPathRooted(localPath)) { localPath = Path.Combine(templateDirectory, localPath); } bool deleteArchiveAfterUploaded = false; string zipArchivePath; if (File.Exists(localPath)) { if (field.IsCode && !string.Equals(Path.GetExtension(localPath), ".zip", StringComparison.OrdinalIgnoreCase)) { this.Logger.WriteLine($"Creating zip archive for {localPath} file"); zipArchivePath = GenerateOutputZipFilename(field); LambdaPackager.BundleFiles(zipArchivePath, Path.GetDirectoryName(localPath), new string[] { localPath }, this.Logger); } else { zipArchivePath = localPath; } } // If IsCode is false then the local path needs to point to a file and not a directory. When IsCode is true // it can point either to a file or a directory. else if (!field.IsCode && !File.Exists(localPath)) { throw new LambdaToolsException($"File that the field {field.Resource.Name}/{field.Name} is pointing to doesn't exist", LambdaToolsException.LambdaErrorCode.ServerlessTemplateMissingLocalPath); } else if (!Directory.Exists(localPath)) { throw new LambdaToolsException($"Directory that the field {field.Resource.Name}/{field.Name} is pointing doesn't exist", LambdaToolsException.LambdaErrorCode.ServerlessTemplateMissingLocalPath); } // To maintain compatibility if the field is point to current directory or not set at all but a prepackaged zip archive is given // then use it as the package source. else if (IsCurrentDirectory(field.GetLocalPath()) && !string.IsNullOrEmpty(this.DefaultOptions.Package)) { zipArchivePath = this.DefaultOptions.Package; } else if (field.IsCode) { if (IsDotnetProjectDirectory(localPath)) { zipArchivePath = await PackageDotnetProjectAsync(field, localPath); } else { zipArchivePath = GenerateOutputZipFilename(field); LambdaPackager.BundleDirectory(zipArchivePath, localPath, false, this.Logger); } deleteArchiveAfterUploaded = true; } else { throw new LambdaToolsException($"Unable to determine package action for the field {field.Resource.Name}/{field.Name}", LambdaToolsException.LambdaErrorCode.ServerlessTemplateUnknownActionForLocalPath); } string s3Key; using (var stream = File.OpenRead(zipArchivePath)) { s3Key = await Utilities.UploadToS3Async(this.Logger, this.S3Client, this.S3Bucket, this.S3Prefix, Path.GetFileName(zipArchivePath), stream); } // Now that the temp zip file is uploaded to S3 clean up by deleting the temp file. if (deleteArchiveAfterUploaded) { try { File.Delete(zipArchivePath); } catch (Exception e) { this.Logger?.WriteLine($"Warning: Unable to delete temporary archive, {zipArchivePath}, after uploading to S3: {e.Message}"); } } return(s3Key); }