Example #1
0
        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);
        }
Example #2
0
        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);
        }
Example #3
0
        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)));
            }
        }
Example #4
0
        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));
            }
        }