public async Task ShouldCorrectlyPackageNodeDirectoryLambdaWithDependency() { var templateDir = Path.Combine(this.LambdaDependencies.FullPath, "NodeLambda1"); var template = Path.Combine(templateDir, "template-complex.yaml"); var modulesDirectory = Path.Combine(templateDir, "Lambda", "node_modules"); this.SetupMocks(template); using var workingDirectory = new TempDirectory(); var packager = new PackagerUtils( new TestPathResolver(), this.Logger, new S3Util(this.ClientFactory, this.Context, template, "test-bucket", null, null), new OSInfo()); await packager.ProcessTemplate(template, workingDirectory); // Verify by checking messages output by the zip library this.Logger.VerboseMessages.Should().Contain( new[] { "Adding my_lambda.js", "Adding other.js", "Adding node_modules/mylibrary/libfile.js" }, "the function itself and its dependency should be in right places in zip"); // Check vendor directory does not exist (was temporarily created to make the package) Directory.Exists(modulesDirectory).Should().BeFalse("node_modules directory transient to create package"); }
public async Task ShouldCorrectlyPackageRubySingleFileLambdaWithLocalAndExternalDependencies() { var templateDir = Path.Combine(this.LambdaDependencies.FullPath, "RubyLambda2"); var template = Path.Combine(templateDir, "template.yaml"); var vendorDirectory = Path.Combine(templateDir, "Lambda", "vendor"); this.SetupMocks(template); using var workingDirectory = new TempDirectory(); var packager = new PackagerUtils( new TestPathResolver(), this.Logger, new S3Util(this.ClientFactory, this.Context, template, "test-bucket", null, null), new OSInfo()); await packager.ProcessTemplate(template, workingDirectory); // Verify by checking messages output by the zip library this.Logger.VerboseMessages.Should().Contain( new[] { "Adding my_lambda.rb", "Adding vendor/bundle/ruby/2.7.0/cache/mylibrary/libfile.rb", "Adding vendor/bundle/ruby/2.7.0/cache/local_lib/local_lib.rb" }, "the function itself and its dependency should be in right places in zip"); // Check vendor directory does not exist (was temporarily created to make the package) Directory.Exists(vendorDirectory).Should().BeTrue("vendor directory existed prior to packaging"); }
public async Task ShouldNotUploadNewVersionOfDirectoryArtifactWhenHashesMatch() { using var templateDir = this.deepNestedStack; // Hash of lambda directory content before zipping // Zips are not idempotent - fields e.g. timestamps in central directory change with successive zips of the same content. var directoryHash = new DirectoryInfo(Path.Combine(templateDir, "lambdacomplex")).MD5(); var template = Path.Combine(templateDir, "base-stack.json"); var projectId = S3Util.GenerateProjectId(template); var logger = new TestLogger(this.output); var mockSts = TestHelpers.GetSTSMock(); var mockS3 = TestHelpers.GetS3ClientWithBucketMock(); var mockContext = new Mock <IPSCloudFormationContext>(); mockContext.Setup(c => c.Logger).Returns(logger); mockContext.Setup(c => c.Region).Returns(RegionEndpoint.EUWest1); mockS3.SetupSequence(s3 => s3.ListObjectsV2Async(It.IsAny <ListObjectsV2Request>(), default)).ReturnsAsync( new ListObjectsV2Response { S3Objects = new List <S3Object> { new S3Object { BucketName = "test-bucket", Key = $"lambdacomplex-{projectId}-0000.zip" } } }).ReturnsAsync(this.fileNotFound).ReturnsAsync(this.fileNotFound); mockS3.Setup(s3 => s3.GetObjectMetadataAsync(It.IsAny <GetObjectMetadataRequest>(), default)).ReturnsAsync( () => { var resp = new GetObjectMetadataResponse(); resp.Metadata.Add(S3Util.PackagerHashKey, directoryHash); return(resp); }); var mockClientFactory = new Mock <IPSAwsClientFactory>(); mockClientFactory.Setup(f => f.CreateS3Client()).Returns(mockS3.Object); mockClientFactory.Setup(f => f.CreateSTSClient()).Returns(mockSts.Object); using var workingDirectory = new TempDirectory(); var packager = new PackagerUtils( new TestPathResolver(), logger, new S3Util(mockClientFactory.Object, mockContext.Object, template, "test-bucket", null, null), new OSInfo()); var outputTemplatePath = await packager.ProcessTemplate(template, workingDirectory); this.output.WriteLine(string.Empty); this.output.WriteLine(await File.ReadAllTextAsync(outputTemplatePath)); // Three objects should have been uploaded to S3 mockS3.Verify(m => m.PutObjectAsync(It.IsAny <PutObjectRequest>(), default), Times.Exactly(2)); }
public async Task ShouldCorrectlyPackagePythonSingleFileLambdaWithRequirementsTxt(string platform) { var templateDir = Path.Combine( this.LambdaDependencies.FullPath, platform == "Windows" ? "PythonLambda" : "PythonLambdaLinux"); var template = Path.Combine(templateDir, "template.yaml"); this.SetupMocks(template); var mockOSInfo = new Mock <IOSInfo>(); mockOSInfo.Setup(i => i.OSPlatform).Returns(platform == "Windows" ? OSPlatform.Windows : OSPlatform.Linux); // Mock the virtualenv Environment.SetEnvironmentVariable("VIRTUAL_ENV", Path.Combine(templateDir, "venv")); var moduleMetadata = new string[] { "METADATA.txt", "RECORD.txt" }; // Fix the fact we have to put a ".txt" extension on these files to get round namespace rules in the embedded resources. foreach (var file in Directory.EnumerateFiles(templateDir, "*.txt", SearchOption.AllDirectories).Where(f => moduleMetadata.Contains(Path.GetFileName(f)))) { File.Move(file, Path.Combine(Path.GetDirectoryName(file), Path.GetFileNameWithoutExtension(file))); } // Place a requriements.txt File.WriteAllText(Path.Combine(templateDir, "Lambda", "requirements.txt"), "mylibrary\nboto3"); using var workingDirectory = new TempDirectory(); var packager = new PackagerUtils( new TestPathResolver(), this.Logger, new S3Util(this.ClientFactory, this.Context, template, "test-bucket", null, null), mockOSInfo.Object); await packager.ProcessTemplate(template, workingDirectory); this.Logger.VerboseMessages.Should().Contain( new[] { "Adding mylibrary/", "Adding my_lambda.py", "Adding standalone_module.py", "Adding mylibrary/__init__.py", "Package 'boto3' will not be included because it exists by default in the AWS execution environment." }, "the function itself and its dependency should be in right places in zip"); }
public async Task ShouldCorrectlyPackagePythonSingleFileLambdaWithoutDependency() { var templateDir = Path.Combine(this.LambdaDependencies.FullPath, "PythonLambda"); var template = Path.Combine(templateDir, "template.yaml"); this.SetupMocks(template); // Mock the virtualenv Environment.SetEnvironmentVariable("VIRTUAL_ENV", Path.Combine(templateDir, "venv")); // Remove the materialized lambda_dependencies so this is seen as a single file lambda foreach (var dep in Directory.EnumerateFiles( templateDir, "lambda-dependencies.*", SearchOption.AllDirectories)) { File.Delete(dep); } using var workingDirectory = new TempDirectory(); var packager = new PackagerUtils( new TestPathResolver(), this.Logger, new S3Util(this.ClientFactory, this.Context, template, "test-bucket", null, null), new OSInfo()); await packager.ProcessTemplate(template, workingDirectory); // Verify by checking messages output by the zip library this.Logger.VerboseMessages.Should().Contain( "Adding my_lambda.py", "the function itself and its dependency should be in right places in zip"); this.Logger.VerboseMessages.Should().NotContain( new[] { "Adding other.py", "Adding mylibrary/__init__.py" }, "lambda is a single script"); this.Logger.VerboseMessages.Should().NotContain( "*__pycache__*", "__pycache__ should not be included in lambda packages"); }
public async Task ShouldCorrectlyPackagePythonDirectoryLambdaWithDependency(string platform) { var templateDir = Path.Combine( this.LambdaDependencies.FullPath, platform == "Windows" ? "PythonLambda" : "PythonLambdaLinux"); var template = Path.Combine(templateDir, "template-complex.yaml"); this.SetupMocks(template); var mockOSInfo = new Mock <IOSInfo>(); mockOSInfo.Setup(i => i.OSPlatform).Returns(platform == "Windows" ? OSPlatform.Windows : OSPlatform.OSX); // Mock the virtualenv Environment.SetEnvironmentVariable("VIRTUAL_ENV", Path.Combine(templateDir, "venv")); using var workingDirectory = new TempDirectory(); var packager = new PackagerUtils( new TestPathResolver(), this.Logger, new S3Util(this.ClientFactory, this.Context, template, "test-bucket", null, null), mockOSInfo.Object); await packager.ProcessTemplate(template, workingDirectory); // Verify by checking messages output by the zip library this.Logger.VerboseMessages.Should().Contain( new[] { "Adding my_lambda.py", "Adding other.py", "Adding mylibrary/__init__.py", "Adding standalone_module.py" }, "the function itself and its dependency should be in right places in zip"); this.Logger.VerboseMessages.Should().NotContain( "*__pycache__*", "__pycache__ should not be included in lambda packages"); }
public async Task ShouldUploadAllArtifactsWhenNoneExistInS3() { var logger = new TestLogger(this.output); var mockSts = TestHelpers.GetSTSMock(); var mockS3 = TestHelpers.GetS3ClientWithBucketMock(); mockS3.Setup(s3 => s3.ListObjectsV2Async(It.IsAny <ListObjectsV2Request>(), default)) .ReturnsAsync(this.fileNotFound); var mockClientFactory = new Mock <IPSAwsClientFactory>(); mockClientFactory.Setup(f => f.CreateS3Client()).Returns(mockS3.Object); mockClientFactory.Setup(f => f.CreateSTSClient()).Returns(mockSts.Object); var mockContext = new Mock <IPSCloudFormationContext>(); mockContext.Setup(c => c.Logger).Returns(logger); mockContext.Setup(c => c.Region).Returns(RegionEndpoint.EUWest1); using var workingDirectory = new TempDirectory(); var template = Path.Combine(this.deepNestedStack, "base-stack.json"); var packager = new PackagerUtils( new TestPathResolver(), logger, new S3Util(mockClientFactory.Object, mockContext.Object, template, "test-bucket", null, null), new OSInfo()); var outputTemplatePath = await packager.ProcessTemplate(template, workingDirectory); this.output.WriteLine(string.Empty); this.output.WriteLine(await File.ReadAllTextAsync(outputTemplatePath)); // Three objects should have been uploaded to S3 mockS3.Verify(m => m.PutObjectAsync(It.IsAny <PutObjectRequest>(), default), Times.Exactly(3)); }
/// <summary> /// Determines whether the specified property name contains a file system reference, and sets properties if it has. /// </summary> /// <param name="propertyName">Name of the property.</param> /// <returns> /// <c>true</c> if [has file system reference] [the specified property name]; otherwise, <c>false</c>. /// </returns> private bool HasFileSystemReference(string propertyName) { var fsi = PackagerUtils.ResolveFileSystemResource( this.pathResolver, this.templatePath, this.GetScalarResourcePropertyValue(propertyName)); if (fsi == null) { return(false); } // File or directory this.Path = fsi.FullName; this.ArtifactType = fsi is FileInfo fi ? System.IO.Path.GetExtension(fi.Name).ToLowerInvariant() == ".zip" ? LambdaArtifactType.ZipFile : LambdaArtifactType.CodeFile : LambdaArtifactType.Directory; return(true); }
public async Task ShouldNotUploadNewVersionOfTemplateArtifactWhenHashesMatch() { var templateDir = this.deepNestedStack; var template = Path.Combine(templateDir, "base-stack.json"); var projectId = S3Util.GenerateProjectId(template); var logger = new TestLogger(this.output); var mockSts = TestHelpers.GetSTSMock(); var mockS3 = TestHelpers.GetS3ClientWithBucketMock(); var mockContext = new Mock <IPSCloudFormationContext>(); mockContext.Setup(c => c.Logger).Returns(logger); mockContext.Setup(c => c.Region).Returns(RegionEndpoint.EUWest1); mockS3.SetupSequence(s3 => s3.ListObjectsV2Async(It.IsAny <ListObjectsV2Request>(), default)) .ReturnsAsync(this.fileNotFound) .ReturnsAsync( new ListObjectsV2Response { S3Objects = new List <S3Object> { new S3Object { BucketName = "test-bucket", Key = $"sub-nested-2-{projectId}-0000.json" } } }).ReturnsAsync(this.fileNotFound); mockS3.Setup(s3 => s3.GetObjectMetadataAsync(It.IsAny <GetObjectMetadataRequest>(), default)).ReturnsAsync( () => { var resp = new GetObjectMetadataResponse(); resp.Metadata.Add(S3Util.PackagerHashKey, GetModifiedTemplateHash()); return(resp); }); var mockClientFactory = new Mock <IPSAwsClientFactory>(); mockClientFactory.Setup(f => f.CreateS3Client()).Returns(mockS3.Object); mockClientFactory.Setup(f => f.CreateSTSClient()).Returns(mockSts.Object); using var workingDirectory = new TempDirectory(); var packager = new PackagerUtils( new TestPathResolver(), logger, new S3Util(mockClientFactory.Object, mockContext.Object, template, "test-bucket", null, null), new OSInfo()); var outputTemplatePath = await packager.ProcessTemplate(template, workingDirectory); this.output.WriteLine(string.Empty); this.output.WriteLine(await File.ReadAllTextAsync(outputTemplatePath)); // Three objects should have been uploaded to S3 mockS3.Verify(m => m.PutObjectAsync(It.IsAny <PutObjectRequest>(), default), Times.Exactly(2)); // Bit hacky, but we need to know the hash of the template after modification. // Different on Windows and Linux due to line endings. string GetModifiedTemplateHash() { var re = new Regex(@"sub-nested-2\.json.*Hash: (?<hash>[0-9a-f]+)"); var logLine = logger.DebugMessages.FirstOrDefault(line => re.IsMatch(line)); if (logLine == null) { return("0"); } var mc = re.Match(logLine); return(mc.Groups["hash"].Value); } }
void OnGUI() { EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("添加一项")) { AddItem(); } if (GUILayout.Button("清除所有项")) { Clear(); } EditorGUILayout.LabelField("Variant(非贴图类资源请设none):", GUILayout.Width(175)); variant = (VariantEnum)EditorGUILayout.EnumPopup(variant, GUILayout.Width(100)); if (GUILayout.Button("读取(csv)")) { Clear(); string path = Application.dataPath + "/Files/BuildMap_cvs/AssetBundleInfo.csv"; string content = File.ReadAllText(path); string[] contents = content.Split(new string[] { "\r\n" }, System.StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < contents.Length; i++) { string[] a = contents[i].Split(','); AddItem(a[0], StringToSuffixEnum(a[1]), a[2]); } variant = StringToVariantEnum(contents[0].Split(',')[3]); } /*if (GUILayout.Button("写入保存")) * { * string path = Application.dataPath + "/BuildMap_cvs/AssetBundleInfo.csv"; * * StringBuilder sb = new StringBuilder(); * for (int i = 0; i < count; i++) * { * if (string.IsNullOrEmpty(bundleNameList[i])) break; * sb.Append(bundleNameList[i] + ","); * sb.Append(SuffixEnumToString(suffixList[i]) + ","); * sb.Append(pathList[i] + ","); * sb.Append(VariantEnumToString(variant) + "\r\n"); * } * File.AppendAllText(path, sb.ToString()); * AssetDatabase.Refresh(); * Clear(); * }*/ if (GUILayout.Button("保存")) { Save(); } if (GUILayout.Button("自动填写(所有选中的)")) { int startIndex = count; for (int i = 0; i < Selection.objects.Length; i++) { AddItem(); AutoFill(startIndex, Selection.objects[i]); startIndex++; } } EditorGUILayout.EndHorizontal(); EditorGUILayout.LabelField("注意:lua文件请以文件夹为单位进行选择!文件夹名即为包名!lua文件请不要混同其他类型文件存放!打包lua文件请点击Build Lua按钮,Build Lua Selected打包选中的文件夹下的lua文件;"); EditorGUILayout.LabelField("Build Lua All打包所有同级目录中的lua文件,打包其他文件请点击Build Asset按钮。按分辨率打包纹理时遇到报“Variant folder path cannot be empty”错误时请忽略,此为 U3D 5.3.X 版本的 bug,经实测不影响使用."); scrollValue = EditorGUILayout.BeginScrollView(scrollValue); for (int i = 0; i < count; i++) { EditorGUILayout.BeginVertical(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField(i.ToString() + ".AB包名:", GUILayout.Width(70)); bundleNameList[i] = EditorGUILayout.TextField("", bundleNameList[i], GUILayout.Width(100)); EditorGUILayout.LabelField(" 类型:", GUILayout.Width(40)); suffixList[i] = (SuffixEnum)EditorGUILayout.EnumPopup(suffixList[i]); EditorGUILayout.LabelField(" 路径:", GUILayout.Width(40)); pathList[i] = EditorGUILayout.TextField(pathList[i]); if (GUILayout.Button("自动填写(单个)")) { AutoFill(i, Selection.objects[0]); } if (GUILayout.Button("log路径")) { Debug.Log(pathList[i]); } if (GUILayout.Button("删除该项")) { RemoveItem(i); } EditorGUILayout.EndHorizontal(); EditorGUILayout.EndVertical(); } EditorGUILayout.EndScrollView(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField(" 是否删除已存在的其他文件:", GUILayout.Width(140)); deleteExists = (YN)EditorGUILayout.EnumPopup(deleteExists, GUILayout.Width(50)); EditorGUILayout.LabelField(" 平台:", GUILayout.Width(40)); target = (BuildTarget)EditorGUILayout.EnumPopup(target, GUILayout.Width(130)); if (GUILayout.Button("Build Lua Selected")) { Save(); if (deleteExists == YN._false) { PackagerUtils.BuildLuaResource(false, false, target); } else { PackagerUtils.BuildLuaResource(false, true, target); } } if (GUILayout.Button("Build Lua All")) { Save(); if (deleteExists == YN._false) { PackagerUtils.BuildLuaResource(true, false, target); } else { PackagerUtils.BuildLuaResource(true, true, target); } } if (GUILayout.Button("Build Asset")) { Save(); if (deleteExists == YN._false) { PackagerUtils.BuildAssetResource(false, target); } else { PackagerUtils.BuildAssetResource(true, target); } } EditorGUILayout.EndHorizontal(); }