private bool IsLatestPendingDeployment(HttpRequestMessage request, string id, out DeployResult pending, out DeployResult latest) { latest = null; if (string.Equals(Constants.LatestDeployment, id)) { if (ScmHostingConfigurations.GetLatestDeploymentOptimized && (ArmUtils.IsAzureResourceManagerUserAgent(request) || ArmUtils.IsVSTSDevOpsUserAgent(request)) && _deploymentLock.IsHeld) { pending = DeployResult.PendingResult; return(true); } using (_tracer.Step("DeploymentService.GetLatestDeployment")) { var results = _deploymentManager.GetResults(); pending = results.Where(r => r.Status != DeployStatus.Success && r.Status != DeployStatus.Failed).FirstOrDefault(); if (pending != null) { _tracer.Trace("Deployment {0} is {1}", pending.Id, pending.Status); return(true); } latest = results.Where(r => r.EndTime != null).OrderBy(r => r.EndTime.Value).LastOrDefault(); if (latest != null) { _tracer.Trace("Deployment {0} is {1} at {2}", latest.Id, latest.Status, latest.EndTime.Value.ToString("o")); } else { _tracer.Trace("Could not find latest deployment!"); } } } pending = null; return(false); }
private bool TryGetCachedLatestDeployment(EntityTagHeaderValue latestEtag, out HttpResponseMessage cachedResponse) { cachedResponse = null; var cachedLatestDeployment = _cachedLatestDeployment; if (latestEtag != null && cachedLatestDeployment != null && !cachedLatestDeployment.Expired && latestEtag.Equals(cachedLatestDeployment.Etag) && (ArmUtils.IsAzureResourceManagerUserAgent(Request) || ArmUtils.IsVSTSDevOpsUserAgent(Request))) { var result = cachedLatestDeployment.Result; switch (result.Status) { case DeployStatus.Building: case DeployStatus.Deploying: case DeployStatus.Pending: cachedResponse = Request.CreateResponse(HttpStatusCode.Accepted, ArmUtils.AddEnvelopeOnArmRequest(result, Request)); cachedResponse.Headers.Location = GetResponseLocation(Request); cachedResponse.Headers.RetryAfter = new RetryConditionHeaderValue(TimeSpan.FromSeconds(ScmHostingConfigurations.ArmRetryAfterSeconds)); break; case DeployStatus.Failed: case DeployStatus.Success: cachedResponse = Request.CreateResponse(HttpStatusCode.OK, ArmUtils.AddEnvelopeOnArmRequest(result, Request)); break; default: cachedResponse = null; break; } } return(cachedResponse != null); }
public HttpResponseMessage GetResult(string id) { using (_tracer.Step("DeploymentService.GetResult")) { var latestEtag = (ScmHostingConfigurations.GetLatestDeploymentOptimized && string.Equals(Constants.LatestDeployment, id)) ? GetCurrentEtag(Request) : null; if (TryGetCachedLatestDeployment(latestEtag, out HttpResponseMessage cachedResponse)) { return(cachedResponse); } if (IsLatestPendingDeployment(Request, id, out DeployResult pending, out DeployResult latest)) { _cachedLatestDeployment = (latestEtag != null && pending != null) ? new DeploymentCacheItem { Etag = latestEtag, Result = pending } : null; var response = Request.CreateResponse(HttpStatusCode.Accepted, ArmUtils.AddEnvelopeOnArmRequest(pending, Request)); response.Headers.Location = GetResponseLocation(Request); response.Headers.RetryAfter = new RetryConditionHeaderValue(TimeSpan.FromSeconds(ScmHostingConfigurations.ArmRetryAfterSeconds)); return(response); } _cachedLatestDeployment = (latestEtag != null && latest != null) ? new DeploymentCacheItem { Etag = latestEtag, Result = latest } : null; var result = latest ?? _deploymentManager.GetResult(id); if (result == null) { var response = Request.CreateErrorResponse(HttpStatusCode.NotFound, String.Format(CultureInfo.CurrentCulture, Resources.Error_DeploymentNotFound, id)); throw new HttpResponseException(response); } Uri baseUri = UriHelper.MakeRelative(Request.GetBaseUri(), Request.RequestUri.AbsolutePath); result.Url = baseUri; result.LogUrl = UriHelper.MakeRelative(baseUri, "log"); if (ScmHostingConfigurations.GetLatestDeploymentOptimized && (result.Status == DeployStatus.Building || result.Status == DeployStatus.Deploying || result.Status == DeployStatus.Pending) && (ArmUtils.IsAzureResourceManagerUserAgent(Request) || ArmUtils.IsVSTSDevOpsUserAgent(Request))) { var responseMessage = Request.CreateResponse(HttpStatusCode.Accepted, ArmUtils.AddEnvelopeOnArmRequest(result, Request)); responseMessage.Headers.Location = GetResponseLocation(Request); responseMessage.Headers.RetryAfter = new RetryConditionHeaderValue(TimeSpan.FromSeconds(ScmHostingConfigurations.ArmRetryAfterSeconds)); return(responseMessage); } if (ArmUtils.IsArmRequest(Request)) { switch (result.Status) { case DeployStatus.Building: case DeployStatus.Deploying: case DeployStatus.Pending: var responseMessage = Request.CreateResponse(HttpStatusCode.OK, ArmUtils.AddEnvelopeOnArmRequest(result, Request)); responseMessage.Headers.Location = GetResponseLocation(Request); responseMessage.Headers.RetryAfter = new RetryConditionHeaderValue(TimeSpan.FromSeconds(ScmHostingConfigurations.ArmRetryAfterSeconds)); return(responseMessage); case DeployStatus.Failed: case DeployStatus.Success: break; default: return(Request.CreateResponse(HttpStatusCode.BadRequest, ArmUtils.AddEnvelopeOnArmRequest(result, Request))); } } return(Request.CreateResponse(HttpStatusCode.OK, ArmUtils.AddEnvelopeOnArmRequest(result, Request))); } }
protected override async Task <HttpResponseMessage> CreateDirectoryPutResponse(DirectoryInfoBase info, string localFilePath) { try { var isRequestJSON = Request.Content.Headers?.ContentType?.MediaType?.Equals("application/json", StringComparison.OrdinalIgnoreCase); var targetPath = localFilePath; var isArmTemplate = false; JObject requestContent = null; Uri packageUri = null; if (isRequestJSON == true) { requestContent = await Request.Content.ReadAsAsync <JObject>(); var payload = requestContent; if (ArmUtils.IsArmRequest(Request)) { payload = payload.Value <JObject>("properties"); isArmTemplate = ArmUtils.IsAzureResourceManagerUserAgent(Request); } var uri = payload?.Value <string>("packageUri"); if (!Uri.TryCreate(uri, UriKind.Absolute, out packageUri)) { throw new InvalidOperationException($"Payload contains invalid '{uri}' packageUri property"); } var path = payload?.Value <string>("path"); if (!string.IsNullOrEmpty(path)) { targetPath = Path.Combine(targetPath, path); FileSystemHelpers.CreateDirectory(targetPath); } } using (packageUri == null ? Tracer.Step($"Extracting content to {targetPath}") : Tracer.Step("Extracting content from {0} to {1}", StringUtils.ObfuscatePath(packageUri.AbsoluteUri), targetPath)) { var content = packageUri == null ? Request.Content : await DeploymentHelper.GetArtifactContentFromURL(new ArtifactDeploymentInfo(null, null) { RemoteURL = packageUri.AbsoluteUri }, Tracer); using (var stream = await content.ReadAsStreamAsync()) { // The unzipping is done over the existing folder, without first removing existing files. // Hence it's more of a PATCH than a PUT. We should consider supporting both with the right semantic. // Though a true PUT at the root would be scary as it would wipe all existing files! var zipArchive = new ZipArchive(stream, ZipArchiveMode.Read); zipArchive.Extract(targetPath, Tracer); } } if (isArmTemplate && requestContent != null) { requestContent.Value <JObject>("properties").Add("provisioningState", "Succeeded"); return(Request.CreateResponse(HttpStatusCode.OK, requestContent)); } return(Request.CreateResponse(HttpStatusCode.OK)); } catch (Exception ex) { return(ArmUtils.CreateErrorResponse(Request, HttpStatusCode.BadRequest, ex)); } }