private void SetupFunctionAppExpressArtifacts(DeploymentContext context) { string sitePackages = "/home/data/SitePackages"; string packageNameFile = Path.Combine(sitePackages, "packagename.txt"); string packagePathFile = Path.Combine(sitePackages, "packagepath.txt"); FileSystemHelpers.EnsureDirectory(sitePackages); string zipAppName = $"{DateTime.UtcNow.ToString("yyyyMMddHHmmss")}.zip"; string createdZip = PackageArtifactFromFolder(context, OryxBuildConstants.FunctionAppBuildSettings.ExpressBuildSetup, OryxBuildConstants.FunctionAppBuildSettings.ExpressBuildSetup, zipAppName, BuildArtifactType.Zip, numBuildArtifacts: -1); var copyExe = ExternalCommandFactory.BuildExternalCommandExecutable(OryxBuildConstants.FunctionAppBuildSettings.ExpressBuildSetup, sitePackages, context.Logger); var copyToPath = Path.Combine(sitePackages, zipAppName); try { copyExe.ExecuteWithProgressWriter(context.Logger, context.Tracer, $"cp {createdZip} {copyToPath}"); } catch (Exception) { context.GlobalLogger.LogError(); throw; } // Gotta remove the old zips DeploymentHelper.PurgeBuildArtifactsIfNecessary(sitePackages, BuildArtifactType.Zip, context.Tracer, totalAllowedFiles: 2); File.WriteAllText(packageNameFile, zipAppName); File.WriteAllText(packagePathFile, sitePackages); }
private void SetupFunctionAppExpressArtifacts(DeploymentContext context) { string sitePackages = "/home/data/SitePackages"; string packageNameFile = Path.Combine(sitePackages, "packagename.txt"); string packagePathFile = Path.Combine(sitePackages, "packagepath.txt"); FileSystemHelpers.EnsureDirectory(sitePackages); string zipAppName = $"{DateTime.UtcNow.ToString("yyyyMMddHHmmss")}.zip"; string zipFile = Path.Combine(sitePackages, zipAppName); context.Logger.Log("Writing the artifacts to a zip file"); var exe = ExternalCommandFactory.BuildExternalCommandExecutable(OryxBuildConstants.FunctionAppBuildSettings.ExpressBuildSetup, sitePackages, context.Logger); try { exe.ExecuteWithProgressWriter(context.Logger, context.Tracer, $"zip -r {zipFile} .", String.Empty); } catch (Exception) { context.GlobalLogger.LogError(); throw; } // Just to be sure that we don't keep adding zip files here DeploymentHelper.PurgeZipsIfNecessary(sitePackages, context.Tracer, totalAllowedZips: 3); File.WriteAllText(packageNameFile, zipAppName); File.WriteAllText(packagePathFile, sitePackages); }
private void SetupAppServiceArtifacts(DeploymentContext context) { string sitePackages = "/home/data/SitePackages"; string deploymentsPath = $"/home/site/deployments/"; string artifactPath = $"/home/site/deployments/{context.CommitId}/artifact"; string packageNameFile = Path.Combine(sitePackages, "packagename.txt"); string packagePathFile = Path.Combine(sitePackages, "packagepath.txt"); FileSystemHelpers.EnsureDirectory(sitePackages); FileSystemHelpers.EnsureDirectory(artifactPath); string zipAppName = $"{DateTime.UtcNow.ToString("yyyyMMddHHmmss")}.zip"; string createdZip = PackageArtifactFromFolder(context, context.BuildTempPath, context.BuildTempPath, zipAppName, BuildArtifactType.Zip, numBuildArtifacts: -1); var copyExe = ExternalCommandFactory.BuildExternalCommandExecutable(context.BuildTempPath, artifactPath, context.Logger); var copyToPath = Path.Combine(artifactPath, zipAppName); try { copyExe.ExecuteWithProgressWriter(context.Logger, context.Tracer, $"cp {createdZip} {copyToPath}"); } catch (Exception) { context.GlobalLogger.LogError(); throw; } // Gotta remove the old zips DeploymentHelper.PurgeOldDeploymentsIfNecessary(deploymentsPath, context.Tracer, totalAllowedDeployments: 10); File.WriteAllText(packageNameFile, zipAppName); File.WriteAllText(packagePathFile, artifactPath); }
public async Task DownloadError_Md5() { // Upload file as a multi-part release, mess with a part's MD5 and // verify that we detect the problem when downloading. var tagName = Guid.NewGuid().ToString("d"); var release = GitHub.Releases.Create(repo, tagName); try { var partCount = 10; var partSize = 1024; var download = PublishMultipartAsset(release, "test.dat", "v1.0", partCount, partSize); Assert.Equal("test.dat", download.Name); Assert.Equal("v1.0", download.Version); Assert.NotNull(download.Md5); Assert.Equal(10, download.Parts.Count); Assert.Equal(partCount * partSize, download.Parts.Sum(part => part.Size)); Assert.Equal(partCount * partSize, download.Size); download.Parts[0].Md5 += "222"; using (var tempFolder = new TempFolder()) { var targetPath = Path.Combine(tempFolder.Path, download.Filename); await Assert.ThrowsAsync <IOException>(async() => await DeploymentHelper.DownloadMultiPartAsync(download, targetPath)); } } finally { GitHub.Releases.Remove(repo, release); } }
private ISiteBuilder DetermineProject(string repositoryRoot, string targetPath, IDeploymentSettingsManager perDeploymentSettings, IFileFinder fileFinder) { if (!DeploymentHelper.IsDeployableProject(targetPath)) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.Error_ProjectNotDeployable, targetPath)); } else if (File.Exists(targetPath)) { var solution = VsHelper.FindContainingSolution(targetPath, fileFinder); string solutionPath = solution != null ? solution.Path : null; return(new WapBuilder(_environment, perDeploymentSettings, _propertyProvider, repositoryRoot, targetPath, solutionPath)); } throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.Error_ProjectDoesNotExist, targetPath)); }
public async Task CreateDeployment_WithInvalidValidParameterFileContents_ReturnsDeploymentFailesMessage() { var template = @"{ ""$schema"": ""https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#"", ""resources"": [ { ""type"": ""Microsoft.Storage/storageAccounts"", ""apiVersion"": ""2021-06-01"", ""name"": ""storageaccount"", ""location"": ""[resourceGroup().location]"", ""properties"": {} } ] }"; var deploymentCollection = CreateDeploymentCollection(LanguageConstants.TargetScopeTypeSubscription); var deploymentCollectionProvider = StrictMock.Of <IDeploymentCollectionProvider>(); deploymentCollectionProvider .Setup(m => m.GetDeploymentCollection(It.IsAny <ArmClient>(), It.IsAny <ResourceIdentifier>(), LanguageConstants.TargetScopeTypeSubscription)) .Returns(deploymentCollection); string parametersFilePath = FileHelper.SaveResultFile(TestContext, "parameters.json", "invalid_parameters_file"); var documentPath = "some_path"; var result = await DeploymentHelper.CreateDeployment( deploymentCollectionProvider.Object, CreateMockArmClient(), documentPath, template, parametersFilePath, "/subscriptions/07268dd7-4c50-434b-b1ff-67b8164edb41/resourceGroups/bhavyatest", LanguageConstants.TargetScopeTypeSubscription, "eastus"); result.Should().Be(string.Format(LangServerResources.InvalidParameterFileDeploymentFailedMessage, documentPath, @"'i' is an invalid start of a value. LineNumber: 0 | BytePositionInLine: 0.")); }
public async Task WaitForDeploymentCompletionAsync_WhenCalled_RemovesDeployIdFromDeploymentOperationsCache() { var responseMessage = "sample response"; var armDeploymentResourceResponse = StrictMock.Of <Response <ArmDeploymentResource> >(); armDeploymentResourceResponse.Setup(m => m.GetRawResponse().Status).Returns(It.IsAny <int>); armDeploymentResourceResponse.Setup(m => m.ToString()).Returns(responseMessage); var armDeploymentResourceOperation = StrictMock.Of <ArmOperation <ArmDeploymentResource> >(); armDeploymentResourceOperation.Setup(m => m.WaitForCompletionAsync(CancellationToken.None)).Returns(ValueTask.FromResult(armDeploymentResourceResponse.Object)); armDeploymentResourceOperation.Setup(m => m.HasValue).Returns(true); var documentPath = "some_path"; var deploymentId1 = "bicep_deployment_1"; var deploymentId2 = "bicep_deployment_2"; var deploymentOperationsCache = new DeploymentOperationsCache(); deploymentOperationsCache.CacheDeploymentOperation(deploymentId1, armDeploymentResourceOperation.Object); deploymentOperationsCache.CacheDeploymentOperation(deploymentId2, armDeploymentResourceOperation.Object); await DeploymentHelper.WaitForDeploymentCompletionAsync( deploymentId1, documentPath, deploymentOperationsCache); deploymentOperationsCache.FindAndRemoveDeploymentOperation(deploymentId1).Should().BeNull(); deploymentOperationsCache.FindAndRemoveDeploymentOperation(deploymentId2).Should().NotBeNull(); }
public async Task StartDeploymentAsync_WithInvalidScope_ReturnsDeploymentFailedMessage(string scope) { var armClient = CreateMockArmClient(); var deploymentCollectionProvider = StrictMock.Of <IDeploymentCollectionProvider>(); deploymentCollectionProvider .Setup(m => m.GetDeploymentCollection(It.IsAny <ArmClient>(), It.IsAny <ResourceIdentifier>(), scope)) .Throws(new Exception(string.Format(LangServerResources.UnsupportedTargetScopeMessage, scope))); var documentPath = "some_path"; var bicepDeployStartResponse = await DeploymentHelper.StartDeploymentAsync( deploymentCollectionProvider.Object, armClient, documentPath, string.Empty, string.Empty, "/subscriptions/07268dd7-4c50-434b-b1ff-67b8164edb41", scope, string.Empty, string.Empty, string.Empty, ParametersFileUpdateOption.None, new List <BicepUpdatedDeploymentParameter>(), "https://portal.azure.com", "bicep_deployment", new DeploymentOperationsCache()); var expectedDeploymentOutputMessage = string.Format(LangServerResources.DeploymentFailedWithExceptionMessage, documentPath, string.Format(LangServerResources.UnsupportedTargetScopeMessage, scope)); bicepDeployStartResponse.isSuccess.Should().BeFalse(); bicepDeployStartResponse.outputMessage.Should().Be(expectedDeploymentOutputMessage); bicepDeployStartResponse.viewDeploymentInPortalMessage.Should().BeNull(); }
private async Task WriteSitePackageZip(ZipDeploymentInfo zipDeploymentInfo, ITracer tracer) { var filePath = Path.Combine(_environment.SitePackagesPath, zipDeploymentInfo.ZipName); // Make sure D:\home\data\SitePackages exists FileSystemHelpers.EnsureDirectory(_environment.SitePackagesPath); using (_tracer.Step("Writing zip file to {0}", filePath)) { if (HttpContext.Request.ContentType.Contains("multipart/form-data", StringComparison.OrdinalIgnoreCase)) { FormValueProvider formModel; using (_tracer.Step("Writing zip file to {0}", filePath)) { using (var file = System.IO.File.Create(filePath)) { formModel = await Request.StreamFile(file); } } } else { using (var file = System.IO.File.Create(filePath)) { await Request.Body.CopyToAsync(file); } } } DeploymentHelper.PurgeBuildArtifactsIfNecessary(_environment.SitePackagesPath, BuildArtifactType.Zip, tracer, _settings.GetMaxZipPackageCount()); }
public async Task WaitForDeploymentCompletionAsync_WithStatusMessage200Or201_ReturnsDeploymentSucceededMessage(int status) { var responseMessage = "sample response"; var armDeploymentResourceResponse = StrictMock.Of <Response <ArmDeploymentResource> >(); armDeploymentResourceResponse.Setup(m => m.GetRawResponse().Status).Returns(status); armDeploymentResourceResponse.Setup(m => m.ToString()).Returns(responseMessage); var armDeploymentResourceOperation = StrictMock.Of <ArmOperation <ArmDeploymentResource> >(); armDeploymentResourceOperation.Setup(m => m.WaitForCompletionAsync(CancellationToken.None)).Returns(ValueTask.FromResult(armDeploymentResourceResponse.Object)); armDeploymentResourceOperation.Setup(m => m.HasValue).Returns(true); var documentPath = "some_path"; var deploymentId = "bicep_deployment"; var deploymentOperationsCache = new DeploymentOperationsCache(); deploymentOperationsCache.CacheDeploymentOperation(deploymentId, armDeploymentResourceOperation.Object); var bicepDeployWaitForCompletionResponse = await DeploymentHelper.WaitForDeploymentCompletionAsync( deploymentId, documentPath, deploymentOperationsCache); var expectedDeploymentOutputMessage = string.Format(LangServerResources.DeploymentSucceededMessage, documentPath); bicepDeployWaitForCompletionResponse.isSuccess.Should().BeTrue(); bicepDeployWaitForCompletionResponse.outputMessage.Should().Be(expectedDeploymentOutputMessage); }
public async Task CreateDeployment_WithInvalidValidParameterFilePath_ReturnsDeploymentFailedMessage() { var template = @"{ ""$schema"": ""https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#"", ""resources"": [ { ""type"": ""Microsoft.Storage/storageAccounts"", ""apiVersion"": ""2021-06-01"", ""name"": ""storageaccount"", ""location"": ""[resourceGroup().location]"", ""properties"": {} } ] }"; var deploymentCollection = CreateDeploymentCollection(LanguageConstants.TargetScopeTypeSubscription); var deploymentCollectionProvider = StrictMock.Of <IDeploymentCollectionProvider>(); deploymentCollectionProvider .Setup(m => m.GetDeploymentCollection(It.IsAny <ArmClient>(), It.IsAny <ResourceIdentifier>(), LanguageConstants.TargetScopeTypeSubscription)) .Returns(deploymentCollection); var result = await DeploymentHelper.CreateDeployment( deploymentCollectionProvider.Object, CreateMockArmClient(), template, @"c:\parameter.json", "/subscriptions/07268dd7-4c50-434b-b1ff-67b8164edb41/resourceGroups/bhavyatest", LanguageConstants.TargetScopeTypeSubscription, "eastus"); result.Should().Contain(string.Format(LangServerResources.InvalidParameterFileDeploymentFailedMessage, @"Could not find file")); }
public void DeleteDeploymentTest() { DeploymentHelper target = new DeploymentHelper(); string subscriptionId = "e57cc5fa-5cf7-41c0-a33c-3adaf2944c4a"; string filePath = @"C:\Development\Certificates\AzureManagementCertificate.cer"; List <Byte> certificateBytes = CertificateUtility.GetCertificateBytes(filePath); string serviceName = "commandlinetest"; string deploymentSlot = "staging"; string expected = string.Empty; string actual; actual = target.DeleteDeployment(subscriptionId, certificateBytes, serviceName, deploymentSlot); string opsStatus = string.Empty; string status = "InProgress"; while (status == "InProgress") { opsStatus = target.GetOperationStatus(subscriptionId, certificateBytes, actual, out status); Trace.WriteLine("Ops Status = " + status); Thread.Sleep(2000); } Assert.AreEqual(expected, actual); }
public async Task CreateDeployment_WithInvalidScope_ReturnsDeploymentFailedMessage(string scope) { var armClient = CreateMockArmClient(); var deploymentCollectionProvider = StrictMock.Of <IDeploymentCollectionProvider>(); deploymentCollectionProvider .Setup(m => m.GetDeploymentCollection(It.IsAny <ArmClient>(), It.IsAny <ResourceIdentifier>(), scope)) .Throws(new Exception(string.Format(LangServerResources.UnsupportedTargetScopeMessage, scope))); var documentPath = "some_path"; var result = await DeploymentHelper.CreateDeployment( deploymentCollectionProvider.Object, armClient, documentPath, string.Empty, string.Empty, "/subscriptions/07268dd7-4c50-434b-b1ff-67b8164edb41", scope, string.Empty); var expectedDeploymentOutputMessage = string.Format(LangServerResources.DeploymentFailedWithExceptionMessage, documentPath, string.Format(LangServerResources.UnsupportedTargetScopeMessage, scope)); result.Should().Be(expectedDeploymentOutputMessage); }
public async Task CreateDeployment_WithExceptionWhileFetchingDeploymentCollection_ReturnsDeploymentFailedMessage() { var template = @"{ ""$schema"": ""https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#"", ""resources"": [ { ""type"": ""Microsoft.Storage/storageAccounts"", ""apiVersion"": ""2021-06-01"", ""name"": ""storageaccount"", ""location"": ""[resourceGroup().location]"", ""properties"": {} } ] }"; var deploymentCollectionProvider = StrictMock.Of <IDeploymentCollectionProvider>(); var errorMessage = "Encountered error while fetching deployments"; deploymentCollectionProvider .Setup(m => m.GetDeploymentCollection(It.IsAny <ArmClient>(), It.IsAny <ResourceIdentifier>(), LanguageConstants.TargetScopeTypeResourceGroup)) .Throws(new Exception(errorMessage)); var documentPath = "some_path"; var result = await DeploymentHelper.CreateDeployment( deploymentCollectionProvider.Object, CreateMockArmClient(), documentPath, template, string.Empty, "/subscriptions/07268dd7-4c50-434b-b1ff-67b8164edb41/resourceGroups/bhavyatest", LanguageConstants.TargetScopeTypeResourceGroup, ""); result.Should().Be(string.Format(LangServerResources.DeploymentFailedWithExceptionMessage, documentPath, errorMessage)); }
public async Task StartDeploymentAsync_WithSubscriptionScopeAndInvalidLocation_ReturnsDeploymentFailedMessage(string location) { var armClient = CreateMockArmClient(); var documentPath = "some_path"; var bicepDeployStartResponse = await DeploymentHelper.StartDeploymentAsync( CreateDeploymentCollectionProvider(), armClient, documentPath, string.Empty, string.Empty, "/subscriptions/07268dd7-4c50-434b-b1ff-67b8164edb41", LanguageConstants.TargetScopeTypeSubscription, location, string.Empty, string.Empty, ParametersFileUpdateOption.None, new List <BicepUpdatedDeploymentParameter>(), "https://portal.azure.com", "bicep_deployment", new DeploymentOperationsCache()); var expectedDeploymentOutputMessage = string.Format(LangServerResources.MissingLocationDeploymentFailedMessage, documentPath); bicepDeployStartResponse.isSuccess.Should().BeFalse(); bicepDeployStartResponse.outputMessage.Should().Be(expectedDeploymentOutputMessage); bicepDeployStartResponse.viewDeploymentInPortalMessage.Should().BeNull(); }
public async Task CreateDeployment_WithValidScopeAndInput_ReturnsDeploymentSucceededMessage(string scope, string location) { var template = @"{ ""$schema"": ""https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#"", ""resources"": [ { ""type"": ""Microsoft.Storage/storageAccounts"", ""apiVersion"": ""2021-06-01"", ""name"": ""storageaccount"", ""location"": ""[resourceGroup().location]"", ""properties"": {} } ] }"; var deploymentCollection = CreateDeploymentCollection(scope); var deploymentCollectionProvider = StrictMock.Of <IDeploymentCollectionProvider>(); deploymentCollectionProvider .Setup(m => m.GetDeploymentCollection(It.IsAny <ArmClient>(), It.IsAny <ResourceIdentifier>(), scope)) .Returns(deploymentCollection); var documentPath = "some_path"; var result = await DeploymentHelper.CreateDeployment( deploymentCollectionProvider.Object, CreateMockArmClient(), documentPath, template, string.Empty, "/subscriptions/07268dd7-4c50-434b-b1ff-67b8164edb41/resourceGroups/bhavyatest", scope, location); result.Should().Be(string.Format(LangServerResources.DeploymentSucceededMessage, documentPath)); }
static OperationStatus GetOperationStatus(OperationStatus operationStatus) { try { DeploymentHelper deploymentHelper = new DeploymentHelper(); string status = string.Empty; string responseString = deploymentHelper.GetOperationStatus(operationStatus.SubscriptionId, operationStatus.CertificateBytes, operationStatus.RequestId, out status); operationStatus.ResponseString = responseString; operationStatus.Status = status; } catch (Exception ex) { Console.WriteLine(string.Format("Error: {0}\n{1}", ex.Message, ex.InnerException != null ? ex.InnerException.Message : string.Empty)); operationStatus = null; } return(operationStatus); }
static string CreateDeployment(string subscriptionId, string serviceName, string label, string deploymentName, string deploymentSlot, string certificateFilePath, int instanceCount) { string responseString = string.Empty; try { DeploymentHelper deploymentHelper = new DeploymentHelper(); List <Byte> certificateBytes = GetCertificateBytes(certificateFilePath); responseString = deploymentHelper.CreateDeployment(subscriptionId, certificateBytes, serviceName, deploymentName, deploymentSlot, label, instanceCount); Console.WriteLine(); Console.WriteLine("Response String: {0}", responseString); Console.WriteLine(); } catch (Exception ex) { Console.WriteLine(string.Format("Error: {0}\n{1}", ex.Message, ex.InnerException != null ? ex.InnerException.Message : string.Empty)); responseString = string.Empty; } return(responseString); }
// POST /api/deployment/subscriptionId/serviceName/deploymentName/deploymentSlot/label/instanceCount // CreateDeployment public string Post(AzureDeployment azureDeployment) { string requestId = string.Empty; try { Logger.Write("In the DeploymentController.Post method..."); DeploymentHelper deploymentHelper = new DeploymentHelper(); Logger.Write(string.Format("SubscriptionId: {0}\tService Name: {1}\tCertificate Byte Length: {2}\tDeployment Name: {3}", azureDeployment.SubscriptionId, azureDeployment.ServiceName, azureDeployment.CertificateBytes.ToArray().Length, azureDeployment.DeploymentName)); requestId = deploymentHelper.CreateDeployment(azureDeployment.SubscriptionId, azureDeployment.CertificateBytes, azureDeployment.ServiceName, azureDeployment.DeploymentName, azureDeployment.DeploymentSlot, azureDeployment.Label, azureDeployment.InstanceCount); Logger.Write("Returned RequestId: " + requestId); } catch (WebException wex) { string responseString = string.Empty; using (StreamReader responseReader = new StreamReader(wex.Response.GetResponseStream())) { responseString = responseReader.ReadToEnd(); if (string.IsNullOrWhiteSpace(responseString) != true) { Logger.Write("DeploymentController.Post() WebException Response: " + responseString); } responseReader.Close(); } Logger.Write(string.Format("Error in DeploymentController.Post() Error: {0}\n{1}", wex.Message, wex.InnerException != null ? wex.InnerException.Message : string.Empty)); requestId = string.Empty; throw new HttpResponseException(HttpStatusCode.BadRequest); } catch (Exception ex) { Logger.Write(string.Format("Error in DeploymentController.Post() Error: {0}\n{1}", ex.Message, ex.InnerException != null ? ex.InnerException.Message : string.Empty)); requestId = string.Empty; throw new HttpResponseException(HttpStatusCode.BadRequest); } return(requestId); }
public void PurgeZipsIfNecessaryTest() { // Setup var tracer = new Mock <ITracer>(); var fileSystem = new Mock <IFileSystem>(); var fileBase = new Mock <FileBase>(); var directoryBase = new Mock <DirectoryBase>(); Dictionary <string, DateTime> testFiles = new Dictionary <string, DateTime>() { { "testFile1.zip", new DateTime(year: 2018, month: 08, day: 21, hour: 12, minute: 31, second: 34) }, { "testFile2.zip", new DateTime(year: 2018, month: 08, day: 21, hour: 12, minute: 31, second: 20) }, { "testFile3.zip", new DateTime(year: 2018, month: 07, day: 30, hour: 7, minute: 21, second: 22) }, { "testFile4.zip", new DateTime(year: 2018, month: 08, day: 25, hour: 0, minute: 0, second: 0) } }; List <string> deletedFiles = new List <string>(); directoryBase .Setup(d => d.GetFiles(It.IsAny <string>(), It.IsAny <string>())) .Returns(testFiles.Keys.ToArray()); fileBase .Setup(f => f.GetLastWriteTimeUtc(It.IsAny <string>())) .Returns((string fileName) => testFiles[fileName]); fileBase .Setup(f => f.Delete(It.IsAny <string>())) .Callback((string path) => deletedFiles.Add(Path.GetFileName(path))); fileSystem.SetupGet(f => f.File).Returns(fileBase.Object); fileSystem.SetupGet(f => f.Directory).Returns(directoryBase.Object); // Act FileSystemHelpers.Instance = fileSystem.Object; DeploymentHelper.PurgeZipsIfNecessary("testLocation", tracer.Object, 2); // Assert Set 1 Assert.Contains("testFile3.zip", deletedFiles); Assert.Contains("testFile2.zip", deletedFiles); Assert.Equal(deletedFiles.Count, 2); // Reset and Act deletedFiles = new List <string>(); DeploymentHelper.PurgeZipsIfNecessary("testLocation", tracer.Object, 5); // Assert Set 2 Assert.Equal(deletedFiles.Count, 0); // Reset and Act deletedFiles = new List <string>(); DeploymentHelper.PurgeZipsIfNecessary("testLocation", tracer.Object, 1); // Assert Set 3 Assert.Contains("testFile3.zip", deletedFiles); Assert.Contains("testFile2.zip", deletedFiles); Assert.Contains("testFile1.zip", deletedFiles); Assert.Equal(deletedFiles.Count, 3); }
/// <summary> /// /// </summary> public void InitialCommitIfNecessary() { var settings = GetInstance <IDeploymentSettingsManager>(); // only support if LocalGit if (settings.GetValue(SettingsKeys.ScmType) != ScmType.LocalGit) { return; } // get repository for the WebRoot var initLock = GetInstance <IDictionary <string, IOperationLock> >(); initLock["deployment"].LockOperation(() => { IRepository repository = _repositoryFactory.GetRepository(); // if repository exists, no need to do anything if (repository != null) { return; } var repositoryPath = settings.GetValue(SettingsKeys.RepositoryPath); // if repository settings is defined, it's already been taken care. if (!String.IsNullOrEmpty(repositoryPath)) { return; } var env = GetInstance <IEnvironment>(); // it is default webroot content, do nothing if (DeploymentHelper.IsDefaultWebRootContent(env.WebRootPath)) { return; } // Set repo path to WebRoot var previous = env.RepositoryPath; env.RepositoryPath = Path.Combine(env.SiteRootPath, Constants.WebRoot); repository = _repositoryFactory.GetRepository(); if (repository != null) { env.RepositoryPath = previous; return; } // do initial commit repository = _repositoryFactory.EnsureRepository(RepositoryType.Git); // Once repo is init, persist the new repo path settings.SetValue(SettingsKeys.RepositoryPath, Constants.WebRoot); repository.Commit("Initial Commit", authorName: null, emailAddress: null); }, "Cloning repository", GitExeServer.InitTimeout); }
public static void AssemblyInitialize(TestContext testContext) { //Todo: This will fail if local cluster is not setup, currently the test code does not automatically //start a local cluster and that's a manual pre-req step. //Todo: Also this will assume that latest SF test application and service code is packaged, if that's not true //the issue might be hard to detect :-( DeploymentHelper.CleanAsync().Wait(); DeploymentHelper.DeployAsync(TestApplicationRootPath).Wait(); }
private ISiteBuilder ResolveProject(string repositoryRoot, string targetPath, IDeploymentSettingsManager perDeploymentSettings, IFileFinder fileFinder, bool tryWebSiteProject, SearchOption searchOption = SearchOption.AllDirectories, bool specificConfiguration = true) { if (DeploymentHelper.IsProject(targetPath)) { return(DetermineProject(repositoryRoot, targetPath, perDeploymentSettings, fileFinder)); } // Check for loose projects var projects = DeploymentHelper.GetProjects(targetPath, fileFinder, searchOption); if (projects.Count > 1) { // Can't determine which project to build throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.Error_AmbiguousProjects, String.Join(", ", projects))); } else if (projects.Count == 1) { return(DetermineProject(repositoryRoot, projects[0], perDeploymentSettings, fileFinder)); } if (tryWebSiteProject) { // Website projects need a solution to build so look for one in the repository path // that has this website in it. var solutions = VsHelper.FindContainingSolutions(targetPath, fileFinder); // More than one solution is ambiguous if (solutions.Count > 1) { ThrowAmbiguousSolutionsError(solutions); } else if (solutions.Count == 1) { // Unambiguously pick the root return(new WebSiteBuilder(_environment, perDeploymentSettings, _propertyProvider, repositoryRoot, targetPath, solutions[0].Path)); } } // This should only ever happen if the user specifies an invalid directory. // The other case where the method is called we always resolve the path so it's a non issue there. if (specificConfiguration && !Directory.Exists(targetPath)) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.Error_ProjectDoesNotExist, targetPath)); } // If there's none then use the basic builder (the site is xcopy deployable) return(ResolveNonAspProject(repositoryRoot, targetPath, perDeploymentSettings)); }
// OneDeploy Fetch handler for non-zip artifacts. // For zip files, OneDeploy uses the LocalZipHandler Fetch handler // NOTE: Do not access the request stream as it may have been closed during asynchronous scenarios private async Task OneDeployFetch(IRepository repository, DeploymentInfoBase deploymentInfo, string targetBranch, ILogger logger, ITracer tracer) { var artifactDeploymentInfo = (ArtifactDeploymentInfo)deploymentInfo; // This is the path where the artifact being deployed is staged, before it is copied to the final target location var artifactDirectoryStagingPath = repository.RepositoryPath; var targetInfo = FileSystemHelpers.DirectoryInfoFromDirectoryName(artifactDirectoryStagingPath); if (targetInfo.Exists) { // If tempDirPath already exists, rename it so we can delete it later var moveTarget = Path.Combine(targetInfo.Parent.FullName, Path.GetRandomFileName()); using (tracer.Step(string.Format("Renaming ({0}) to ({1})", targetInfo.FullName, moveTarget))) { targetInfo.MoveTo(moveTarget); } } // Create artifact staging directory before later use Directory.CreateDirectory(artifactDirectoryStagingPath); var artifactFileStagingPath = Path.Combine(artifactDirectoryStagingPath, deploymentInfo.TargetFileName); // If RemoteUrl is non-null, it means the content needs to be downloaded from the Url source to the staging location // Else, it had been downloaded already so we just move the downloaded file to the staging location if (!string.IsNullOrWhiteSpace(artifactDeploymentInfo.RemoteURL)) { using (tracer.Step("Saving request content to {0}", artifactFileStagingPath)) { var content = await DeploymentHelper.GetArtifactContentFromURL(artifactDeploymentInfo, tracer); var copyTask = content.CopyToAsync(artifactFileStagingPath, tracer); // Deletes all files and directories except for artifactFileStagingPath and artifactDirectoryStagingPath var cleanTask = Task.Run(() => DeleteFilesAndDirsExcept(artifactFileStagingPath, artifactDirectoryStagingPath, tracer)); // Lets the copy and cleanup tasks to run in parallel and wait for them to finish await Task.WhenAll(copyTask, cleanTask); } } else { var srcInfo = FileSystemHelpers.DirectoryInfoFromDirectoryName(deploymentInfo.RepositoryUrl); using (tracer.Step(string.Format("Moving {0} to {1}", targetInfo.FullName, artifactFileStagingPath))) { srcInfo.MoveTo(artifactFileStagingPath); } // Deletes all files and directories except for artifactFileStagingPath and artifactDirectoryStagingPath DeleteFilesAndDirsExcept(artifactFileStagingPath, artifactDirectoryStagingPath, tracer); } // The deployment flow expects at least 1 commit in the IRepository commit, refer to CommitRepo() for more info CommitRepo(repository, artifactDeploymentInfo); }
public void SmartCopyDeletesFilesThatDontExistInSourceIfNoPrevious() { DirectoryWrapper sourceDirectory = GetDirectory(@"a:\test\", filePaths: new[] { @"a.txt", "b.txt" }); DirectoryWrapper destinationDirectory = GetDirectory(@"b:\foo\", filePaths: new[] { "c.txt" }); DeploymentHelper.SmartCopy(@"a:\test\", @"b:\foo\", null, sourceDirectory.Directory, destinationDirectory.Directory, path => GetDirectory(path, exists: false).Directory); sourceDirectory.VerifyCopied("a.txt", @"b:\foo\a.txt"); sourceDirectory.VerifyCopied("b.txt", @"b:\foo\b.txt"); destinationDirectory.VerifyDeleted("c.txt"); }
/// <summary> /// Returns the server link to the deployment. /// </summary> /// <returns>Returns the server link to the deployment.</returns> public string GetDeploymentLink() { if (taskToManage != null) { return(DeploymentHelper.GetDeploymentLinkForWeb(deploymentToManage)); } else { return(string.Empty); } }
public async Task CreateDeployment_WithStatusMessageOtherThan200Or201_ReturnsDeploymentFailedMessage() { var template = @"{ ""$schema"": ""https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#"", ""resources"": [ { ""type"": ""Microsoft.Storage/storageAccounts"", ""apiVersion"": ""2021-06-01"", ""name"": ""storageaccount"", ""location"": ""[resourceGroup().location]"", ""properties"": {} } ] }"; var response = StrictMock.Of <Response>(); response.Setup(m => m.Status).Returns(502); var responseMessage = "sample response"; response.Setup(m => m.ToString()).Returns(responseMessage); var deploymentCreateOrUpdateOperation = StrictMock.Of <DeploymentCreateOrUpdateOperation>(); deploymentCreateOrUpdateOperation.Setup(m => m.HasValue).Returns(true); deploymentCreateOrUpdateOperation.Setup(m => m.GetRawResponse()).Returns(response.Object); var deploymentCollection = StrictMock.Of <DeploymentCollection>(); deploymentCollection .Setup(m => m.CreateOrUpdateAsync( It.IsAny <bool>(), It.IsAny <string>(), It.IsAny <DeploymentInput>(), It.IsAny <CancellationToken>())).Returns(Task.FromResult(deploymentCreateOrUpdateOperation.Object)); var deploymentCollectionProvider = StrictMock.Of <IDeploymentCollectionProvider>(); deploymentCollectionProvider .Setup(m => m.GetDeploymentCollection(It.IsAny <ArmClient>(), It.IsAny <ResourceIdentifier>(), LanguageConstants.TargetScopeTypeResourceGroup)) .Returns(deploymentCollection.Object); var documentPath = "some_path"; var result = await DeploymentHelper.CreateDeployment( deploymentCollectionProvider.Object, CreateMockArmClient(), documentPath, template, string.Empty, "/subscriptions/07268dd7-4c50-434b-b1ff-67b8164edb41/resourceGroups/bhavyatest", LanguageConstants.TargetScopeTypeResourceGroup, ""); result.Should().Be(string.Format(LangServerResources.DeploymentFailedWithExceptionMessage, documentPath, responseMessage)); }
public async Task StartDeploymentAsync_WithExceptionWhileCreatingDeployment_ReturnsDeploymentFailedMessage() { var template = @"{ ""$schema"": ""https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#"", ""resources"": [ { ""type"": ""Microsoft.Storage/storageAccounts"", ""apiVersion"": ""2021-06-01"", ""name"": ""storageaccount"", ""location"": ""[resourceGroup().location]"", ""properties"": {} } ] }"; var deploymentCollection = StrictMock.Of <ArmDeploymentCollection>(); var errorMessage = "Encountered error while creating deployment"; deploymentCollection .Setup(m => m.CreateOrUpdateAsync( It.IsAny <WaitUntil>(), It.IsAny <string>(), It.IsAny <ArmDeploymentContent>(), It.IsAny <CancellationToken>())) .Throws(new Exception(errorMessage)); var deploymentCollectionProvider = StrictMock.Of <IDeploymentCollectionProvider>(); deploymentCollectionProvider .Setup(m => m.GetDeploymentCollection(It.IsAny <ArmClient>(), It.IsAny <ResourceIdentifier>(), LanguageConstants.TargetScopeTypeResourceGroup)) .Returns(deploymentCollection.Object); var documentPath = "some_path"; var bicepDeployStartResponse = await DeploymentHelper.StartDeploymentAsync( deploymentCollectionProvider.Object, CreateMockArmClient(), documentPath, template, string.Empty, "/subscriptions/07268dd7-4c50-434b-b1ff-67b8164edb41/resourceGroups/bhavyatest", LanguageConstants.TargetScopeTypeResourceGroup, "", string.Empty, string.Empty, ParametersFileUpdateOption.None, new List <BicepUpdatedDeploymentParameter>(), "https://portal.azure.com", "bicep_deployment", new DeploymentOperationsCache()); var expectedDeploymentOutputMessage = string.Format(LangServerResources.DeploymentFailedWithExceptionMessage, documentPath, errorMessage); bicepDeployStartResponse.isSuccess.Should().BeFalse(); bicepDeployStartResponse.outputMessage.Should().Be(expectedDeploymentOutputMessage); bicepDeployStartResponse.viewDeploymentInPortalMessage.Should().BeNull(); }
private void EnsureProperties() { if (_initialized) { return; } _projectName = _projectNameProperty.GetValue <string>(_projectInstance); var projectType = _projectTypeProperty.GetValue <SolutionProjectType>(_projectInstance); var relativePath = _relativePathProperty.GetValue <string>(_projectInstance); _isWebSite = projectType == SolutionProjectType.WebProject; // When using websites with IISExpress, the relative path property becomes a URL. // When that happens we're going to grab the path from the Release.AspNetCompiler.PhysicalPath // property in the solution. Uri uri; if (_isWebSite && Uri.TryCreate(relativePath, UriKind.Absolute, out uri)) { var aspNetConfigurations = _aspNetConfigurationsProperty.GetValue <Hashtable>(_projectInstance); // Use the release configuration and debug if it isn't available object configurationObject = aspNetConfigurations["Release"] ?? aspNetConfigurations["Debug"]; // REVIEW: Is there always a configuration object (i.e. can this ever be null?) // The aspNetPhysicalPath contains the relative to the website FieldInfo aspNetPhysicalPathField = configurationObject.GetType().GetField("aspNetPhysicalPath", BindingFlags.NonPublic | BindingFlags.Instance); relativePath = (string)aspNetPhysicalPathField.GetValue(configurationObject); } _absolutePath = Path.Combine(Path.GetDirectoryName(_solutionPath), relativePath); if (FileSystemHelpers.FileExists(_absolutePath) && DeploymentHelper.IsMsBuildProject(_absolutePath)) { // used to determine project type from project file _projectTypeGuids = VsHelper.GetProjectTypeGuids(_absolutePath); _isAspNetCore = AspNetCoreHelper.IsDotnetCoreFromProjectFile(_absolutePath, _projectTypeGuids); _isWap = VsHelper.IsWap(_projectTypeGuids); _isExecutable = VsHelper.IsExecutableProject(_absolutePath); _isFunctionApp = FunctionAppHelper.LooksLikeFunctionApp(); _targetFramework = VsHelper.GetTargetFramework(_absolutePath); } else { _projectTypeGuids = Enumerable.Empty <Guid>(); } _initialized = true; }
public async Task StartDeploymentAsync_WithValidScopeAndInput_ShouldUpdateDeploymentOperationsCache() { var template = @"{ ""$schema"": ""https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#"", ""resources"": [ { ""type"": ""Microsoft.Storage/storageAccounts"", ""apiVersion"": ""2021-06-01"", ""name"": ""storageaccount"", ""location"": ""[resourceGroup().location]"", ""properties"": {} } ] }"; var armDeploymentResourceOperation = StrictMock.Of <ArmOperation <ArmDeploymentResource> >().Object; var deploymentCollection = StrictMock.Of <ArmDeploymentCollection>(); deploymentCollection .Setup(m => m.CreateOrUpdateAsync( It.IsAny <WaitUntil>(), It.IsAny <string>(), It.IsAny <ArmDeploymentContent>(), It.IsAny <CancellationToken>())).Returns(Task.FromResult(armDeploymentResourceOperation)); var deploymentCollectionProvider = StrictMock.Of <IDeploymentCollectionProvider>(); deploymentCollectionProvider .Setup(m => m.GetDeploymentCollection(It.IsAny <ArmClient>(), It.IsAny <ResourceIdentifier>(), LanguageConstants.TargetScopeTypeSubscription)) .Returns(deploymentCollection.Object); var deploymentOperationsCache = new DeploymentOperationsCache(); var deployId = "bicep_deployment1"; var bicepDeployStartResponse = await DeploymentHelper.StartDeploymentAsync( deploymentCollectionProvider.Object, CreateMockArmClient(), "some_path", template, string.Empty, "/subscriptions/07268dd7-4c50-434b-b1ff-67b8164edb41/resourceGroups/bhavyatest", LanguageConstants.TargetScopeTypeSubscription, "eastus", deployId, string.Empty, ParametersFileUpdateOption.None, new List <BicepUpdatedDeploymentParameter>(), "https://portal.azure.com", "deployment_name", deploymentOperationsCache); deploymentOperationsCache.FindAndRemoveDeploymentOperation(deployId).Should().NotBeNull(); }