public async Task <IActionResult> ZipPushDeployViaUrl(
            [FromBody] JObject requestJson,
            [FromQuery] bool isAsync       = false,
            [FromQuery] bool syncTriggers  = false,
            [FromQuery] string author      = null,
            [FromQuery] string authorEmail = null,
            [FromQuery] string deployer    = DefaultDeployer,
            [FromQuery] string message     = DefaultMessage)
        {
            using (_tracer.Step("ZipPushDeployViaUrl"))
            {
                string zipUrl = GetZipURLFromJSON(requestJson);

                var deploymentInfo = new ZipDeploymentInfo(_environment, _traceFactory)
                {
                    AllowDeploymentWhileScmDisabled = true,
                    Deployer                = deployer,
                    IsContinuous            = false,
                    AllowDeferredDeployment = false,
                    IsReusable              = false,
                    TargetChangeset         =
                        DeploymentManager.CreateTemporaryChangeSet(message: "Deploying from pushed zip file"),
                    CommitId             = null,
                    RepositoryType       = RepositoryType.None,
                    Fetch                = LocalZipHandler,
                    DoFullBuildByDefault = false,
                    Author               = author,
                    AuthorEmail          = authorEmail,
                    Message              = message,
                    ZipURL               = zipUrl,
                    DoSyncTriggers       = syncTriggers
                };
                return(await PushDeployAsync(deploymentInfo, isAsync, HttpContext));
            }
        }
예제 #2
0
        private void ExtractTriggers(IRepository repository, ZipDeploymentInfo zipDeploymentInfo)
        {
            FileSystemHelpers.EnsureDirectory(zipDeploymentInfo.SyncFunctionsTriggersPath);
            // Loading the zip file depends on how fast the file system is.
            // Tested Azure Files share with a zip containing 120k files (160 MBs)
            // takes 20 seconds to load. On my machine it takes 900 msec.
            using (var zip = ZipFile.OpenRead(Path.Combine(_environment.SitePackagesPath, zipDeploymentInfo.ZipName)))
            {
                var entries = zip.Entries
                              // Only select host.json, proxies.json, or function.json that are from top level directories only
                              // Tested with a zip containing 120k files, and this took 90 msec
                              // on my machine.
                              .Where(e => e.FullName.Equals(Constants.FunctionsHostConfigFile, StringComparison.OrdinalIgnoreCase) ||
                                     e.FullName.Equals(Constants.ProxyConfigFile, StringComparison.OrdinalIgnoreCase) ||
                                     isFunctionJson(e.FullName));

                foreach (var entry in entries)
                {
                    var path = Path.Combine(zipDeploymentInfo.SyncFunctionsTriggersPath, entry.FullName);
                    FileSystemHelpers.EnsureDirectory(Path.GetDirectoryName(path));
                    entry.ExtractToFile(path, overwrite: true);
                }
            }

            CommitRepo(repository, zipDeploymentInfo);

            bool isFunctionJson(string fullName)
            {
                return(fullName.EndsWith(Constants.FunctionsConfigFile) &&
                       fullName.Count(c => c == '/' || c == '\\') == 1);
            }
        }
예제 #3
0
        public static async Task UpdateSiteVersion(ZipDeploymentInfo deploymentInfo, IEnvironment environment, ILogger logger)
        {
            var siteVersionPath = Path.Combine(environment.SitePackagesPath, Constants.SiteVersionTxt);

            logger.Log($"Updating {siteVersionPath} with deployment {deploymentInfo.ZipName}");
            await FileSystemHelpers.WriteAllTextToFileAsync(siteVersionPath, deploymentInfo.ZipName);
        }
예제 #4
0
        public async Task <HttpResponseMessage> WarPushDeploy(
            [FromUri] bool isAsync       = false,
            [FromUri] string author      = null,
            [FromUri] string authorEmail = null,
            [FromUri] string deployer    = DefaultDeployer,
            [FromUri] string message     = DefaultMessage)
        {
            using (_tracer.Step("WarPushDeploy"))
            {
                var deploymentInfo = new ZipDeploymentInfo(_environment, _traceFactory)
                {
                    AllowDeploymentWhileScmDisabled = true,
                    Deployer                = deployer,
                    TargetPath              = Path.Combine("webapps", "ROOT"),
                    WatchedFilePath         = Path.Combine("WEB-INF", "web.xml"),
                    IsContinuous            = false,
                    AllowDeferredDeployment = false,
                    IsReusable              = false,
                    TargetChangeset         = DeploymentManager.CreateTemporaryChangeSet(message: "Deploying from pushed war file"),
                    CommitId                = null,
                    RepositoryType          = RepositoryType.None,
                    Fetch = LocalZipFetch,
                    DoFullBuildByDefault = false,
                    Author      = author,
                    AuthorEmail = authorEmail,
                    Message     = message
                };

                return(await PushDeployAsync(deploymentInfo, isAsync));
            }
        }
        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());
        }
예제 #6
0
 private static void CommitRepo(IRepository repository, ZipDeploymentInfo zipDeploymentInfo)
 {
     // Needed in order for repository.GetChangeSet() to work.
     // Similar to what OneDriveHelper and DropBoxHelper do.
     // We need to make to call respository.Commit() since deployment flow expects at
     // least 1 commit in the IRepository. Even though there is no repo per se in this
     // scenario, deployment pipeline still generates a NullRepository
     repository.Commit(zipDeploymentInfo.Message, zipDeploymentInfo.Author, zipDeploymentInfo.AuthorEmail);
 }
예제 #7
0
        public static async Task UpdateSiteVersion(ZipDeploymentInfo deploymentInfo, IEnvironment environment, ITracer tracer)
        {
            var siteVersionPath = Path.Combine(environment.SitePackagesPath, Constants.PackageNameTxt);

            using (tracer.Step($"Updating {siteVersionPath} with deployment {deploymentInfo.ZipName}"))
            {
                await FileSystemHelpers.WriteAllTextToFileAsync(siteVersionPath, deploymentInfo.ZipName);
            }
        }
예제 #8
0
        private void ExtractTriggers(IRepository repository, ZipDeploymentInfo zipDeploymentInfo)
        {
            FileSystemHelpers.EnsureDirectory(zipDeploymentInfo.SyncFunctionsTriggersPath);
            // Loading the zip file depends on how fast the file system is.
            // Tested Azure Files share with a zip containing 120k files (160 MBs)
            // takes 20 seconds to load. On my machine it takes 900 msec.
            using (var zip = ZipFile.OpenRead(Path.Combine(_environment.SitePackagesPath, zipDeploymentInfo.ZipName)))
            {
                var entries = zip.Entries
                              // Only select host.json, proxies.json, or top level directories.
                              // Tested with a zip containing 120k files, and this took 90 msec
                              // on my machine.
                              .Where(e => e.FullName.Equals(Constants.FunctionsHostConfigFile, StringComparison.OrdinalIgnoreCase) ||
                                     e.FullName.Equals(Constants.ProxyConfigFile, StringComparison.OrdinalIgnoreCase) ||
                                     isTopLevelDirectory(e.FullName))
                              // If entry is a top level dir, select the function.json in it.
                              // otherwise that must be host.json, or proxies.json. Leave it as is.
                              .Select(e => isTopLevelDirectory(e.FullName)
                        ? zip.GetEntry($"{e.FullName}{Constants.FunctionsConfigFile}")
                        : e
                                      )
                              // if a top level folder wasn't a function, it won't contain a function.json
                              // and GetEntry above will return null
                              .Where(e => e != null);

                foreach (var entry in entries)
                {
                    var path = Path.Combine(zipDeploymentInfo.SyncFunctionsTriggersPath, entry.FullName);
                    FileSystemHelpers.EnsureDirectory(Path.GetDirectoryName(path));
                    entry.ExtractToFile(path, overwrite: true);
                }
            }

            CommitRepo(repository, zipDeploymentInfo);

            bool isTopLevelDirectory(string fullName)
            {
                for (var i = 0; i < fullName.Length; i++)
                {
                    // Zip entries use '/' separators.
                    // If the first '/' we find also the last in the string
                    // It's a top level dir, otherwise it's not
                    if (fullName[i] == '/')
                    {
                        return(i + 1 == fullName.Length);
                    }
                }
                // Top level file
                return(false);
            }
        }
예제 #9
0
        private async Task WriteSitePackageZip(ZipDeploymentInfo zipDeploymentInfo, ITracer tracer, HttpContent content)
        {
            var filePath = Path.Combine(_environment.SitePackagesPath, zipDeploymentInfo.ZipName);

            // Make sure D:\home\data\SitePackages exists
            FileSystemHelpers.EnsureDirectory(_environment.SitePackagesPath);

            using (tracer.Step("Saving request content to {0}", filePath))
            {
                await content.CopyToAsync(filePath, tracer);
            }

            DeploymentHelper.PurgeZipsIfNecessary(_environment.SitePackagesPath, tracer, _settings.GetMaxZipPackageCount());
        }
예제 #10
0
        private async Task <string> DeployZipLocally(ZipDeploymentInfo zipDeploymentInfo, ITracer tracer)
        {
            var content = await DeploymentHelper.GetZipContentFromURL(zipDeploymentInfo, tracer);

            var zipFileName = Path.ChangeExtension(Path.GetRandomFileName(), "zip");
            var zipFilePath = Path.Combine(_environment.ZipTempPath, zipFileName);

            using (_tracer.Step("Downloading content from {0} to {1}", zipDeploymentInfo.ZipURL.Split('?')[0], zipFilePath))
            {
                await content.CopyToAsync(zipFilePath, _tracer);
            }

            zipDeploymentInfo.RepositoryUrl = zipFilePath;
            return(zipFilePath);
        }
        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 content to {0}", filePath))
            {
                using (var file = FileSystemHelpers.CreateFile(filePath))
                {
                    await Request.Content.CopyToAsync(file);
                }
            }
        }
예제 #12
0
        private async Task <string> DeployZipLocally(ZipDeploymentInfo zipDeploymentInfo, ITracer tracer)
        {
            var content = await DeploymentHelper.GetZipContentFromURL(zipDeploymentInfo, tracer);

            var zipFileName = Path.ChangeExtension(Path.GetRandomFileName(), "zip");
            var zipFilePath = Path.Combine(_environment.ZipTempPath, zipFileName);

            using (_tracer.Step("Writing content to {0}", zipFilePath))
            {
                using (var file = FileSystemHelpers.CreateFile(zipFilePath))
                {
                    await content.CopyToAsync(file);
                }
            }
            zipDeploymentInfo.RepositoryUrl = zipFilePath;
            return(zipFilePath);
        }
예제 #13
0
        public async Task <IActionResult> ZipPushDeploy(
            [FromQuery] bool isAsync       = false,
            [FromQuery] bool syncTriggers  = false,
            [FromQuery] string author      = null,
            [FromQuery] string authorEmail = null,
            [FromQuery] string deployer    = DefaultDeployer,
            [FromQuery] string message     = DefaultMessage)
        {
            using (_tracer.Step("ZipPushDeploy"))
            {
                var deploymentInfo = new ZipDeploymentInfo(_environment, _traceFactory)
                {
                    AllowDeploymentWhileScmDisabled = true,
                    Deployer                = deployer,
                    IsContinuous            = false,
                    AllowDeferredDeployment = false,
                    IsReusable              = false,
                    TargetChangeset         =
                        DeploymentManager.CreateTemporaryChangeSet(message: "Deploying from pushed zip file"),
                    CommitId             = null,
                    RepositoryType       = RepositoryType.None,
                    Fetch                = LocalZipHandler,
                    DoFullBuildByDefault = false,
                    Author               = author,
                    AuthorEmail          = authorEmail,
                    Message              = message,
                    ZipURL               = null,
                    DoSyncTriggers       = syncTriggers
                };

                if (_settings.RunFromLocalZip())
                {
                    // This is used if the deployment is Run-From-Zip
                    // the name of the deployed file in D:\home\data\SitePackages\{name}.zip is the
                    // timestamp in the format yyyMMddHHmmss.
                    deploymentInfo.ZipName = $"{DateTime.UtcNow.ToString("yyyyMMddHHmmss")}.zip";
                    // This is also for Run-From-Zip where we need to extract the triggers
                    // for post deployment sync triggers.
                    deploymentInfo.SyncFunctionsTriggersPath =
                        Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
                }
                ;

                return(await PushDeployAsync(deploymentInfo, isAsync, HttpContext));
            }
        }
예제 #14
0
 private async Task LocalZipHandler(IRepository repository, DeploymentInfoBase deploymentInfo, string targetBranch, ILogger logger, ITracer tracer)
 {
     if (_settings.RunFromLocalZip() && deploymentInfo is ZipDeploymentInfo)
     {
         ZipDeploymentInfo zipDeploymentInfo = (ZipDeploymentInfo)deploymentInfo;
         // If this was a request with a Zip URL in the JSON, we first need to get the zip content and write it to the site.
         if (!string.IsNullOrEmpty(zipDeploymentInfo.ZipURL))
         {
             await WriteSitePackageZip(zipDeploymentInfo, tracer, await DeploymentHelper.GetZipContentFromURL(zipDeploymentInfo, tracer));
         }
         // If this is a Run-From-Zip deployment, then we need to extract function.json
         // from the zip file into path zipDeploymentInfo.SyncFunctionsTrigersPath
         ExtractTriggers(repository, zipDeploymentInfo);
     }
     else
     {
         await LocalZipFetch(repository, deploymentInfo, targetBranch, logger, tracer);
     }
 }
예제 #15
0
        public async Task <IActionResult> WarPushDeploy(
            [FromQuery] bool isAsync       = false,
            [FromQuery] string author      = null,
            [FromQuery] string authorEmail = null,
            [FromQuery] string deployer    = DefaultDeployer,
            [FromQuery] string message     = DefaultMessage)
        {
            using (_tracer.Step("WarPushDeploy"))
            {
                var appName = HttpContext.Request.Query["name"].ToString();
                if (string.IsNullOrWhiteSpace(appName))
                {
                    appName = "ROOT";
                }

                var deploymentInfo = new ZipDeploymentInfo(_environment, _traceFactory)
                {
                    AllowDeploymentWhileScmDisabled = true,
                    Deployer                = deployer,
                    TargetPath              = Path.Combine("webapps", appName),
                    WatchedFilePath         = Path.Combine("WEB-INF", "web.xml"),
                    IsContinuous            = false,
                    AllowDeferredDeployment = false,
                    IsReusable              = false,
                    CleanupTargetDirectory  =
                        true, // For now, always cleanup the target directory. If needed, make it configurable
                    TargetChangeset =
                        DeploymentManager.CreateTemporaryChangeSet(message: "Deploying from pushed war file"),
                    CommitId             = null,
                    RepositoryType       = RepositoryType.None,
                    Fetch                = LocalZipFetch,
                    DoFullBuildByDefault = false,
                    Author               = author,
                    AuthorEmail          = authorEmail,
                    Message              = message,
                    ZipURL               = null
                };
                return(await PushDeployAsync(deploymentInfo, isAsync, HttpContext));
            }
        }
예제 #16
0
        private async Task <HttpResponseMessage> PushDeployAsync(ZipDeploymentInfo deploymentInfo, bool isAsync)
        {
            var content       = Request.Content;
            var isRequestJSON = content.Headers?.ContentType?.MediaType?.Equals("application/json", StringComparison.OrdinalIgnoreCase);

            if (isRequestJSON == true)
            {
                try
                {
                    var requestObject = await Request.Content.ReadAsAsync <JObject>();

                    deploymentInfo.ZipURL = ArmUtils.IsArmRequest(Request) ? GetZipURLFromARMJSON(requestObject) : GetZipURLFromJSON(requestObject);
                }
                catch (Exception ex)
                {
                    return(ArmUtils.CreateErrorResponse(Request, HttpStatusCode.BadRequest, ex));
                }
            }
            else
            {
                if (_settings.RunFromLocalZip())
                {
                    await WriteSitePackageZip(deploymentInfo, _tracer, Request.Content);
                }
                else
                {
                    var zipFileName = Path.ChangeExtension(Path.GetRandomFileName(), "zip");
                    var zipFilePath = Path.Combine(_environment.ZipTempPath, zipFileName);

                    using (_tracer.Step("Saving request content to {0}", zipFilePath))
                    {
                        await content.CopyToAsync(zipFilePath, _tracer);
                    }

                    deploymentInfo.RepositoryUrl = zipFilePath;
                }
            }

            isAsync = ArmUtils.IsArmRequest(Request) ? true : isAsync;

            var result = await _deploymentManager.FetchDeploy(deploymentInfo, isAsync, UriHelper.GetRequestUri(Request), "HEAD");

            var response = Request.CreateResponse();

            switch (result)
            {
            case FetchDeploymentRequestResult.RunningAynschronously:
                if (ArmUtils.IsArmRequest(Request))
                {
                    DeployResult deployResult = new DeployResult();
                    response = Request.CreateResponse(HttpStatusCode.Accepted, ArmUtils.AddEnvelopeOnArmRequest(deployResult, Request));
                    string statusURL = GetStatusUrl();
                    // Should not happen: If we couldn't make the URL, there must have been an error in the request
                    if (string.IsNullOrEmpty(statusURL))
                    {
                        var badResponse = Request.CreateResponse();
                        badResponse.StatusCode = HttpStatusCode.BadRequest;
                        return(badResponse);
                    }
                    // latest deployment keyword reserved to poll till deployment done
                    response.Headers.Location = new Uri(statusURL +
                                                        String.Format("/deployments/{0}?api-version=2018-02-01&deployer={1}&time={2}", Constants.LatestDeployment, deploymentInfo.Deployer, DateTime.UtcNow.ToString("yyy-MM-dd_HH-mm-ssZ")));
                }
                else if (isAsync)
                {
                    // latest deployment keyword reserved to poll till deployment done
                    response.Headers.Location = new Uri(UriHelper.GetRequestUri(Request),
                                                        String.Format("/api/deployments/{0}?deployer={1}&time={2}", Constants.LatestDeployment, deploymentInfo.Deployer, DateTime.UtcNow.ToString("yyy-MM-dd_HH-mm-ssZ")));
                }
                response.StatusCode = HttpStatusCode.Accepted;
                break;

            case FetchDeploymentRequestResult.ForbiddenScmDisabled:
                // Should never hit this for zip push deploy
                response.StatusCode = HttpStatusCode.Forbidden;
                _tracer.Trace("Scm is not enabled, reject all requests.");
                break;

            case FetchDeploymentRequestResult.ConflictAutoSwapOngoing:
                response.StatusCode = HttpStatusCode.Conflict;
                response.Content    = new StringContent(Resources.Error_AutoSwapDeploymentOngoing);
                break;

            case FetchDeploymentRequestResult.Pending:
                // Shouldn't happen here, as we disallow deferral for this use case
                response.StatusCode = HttpStatusCode.Accepted;
                break;

            case FetchDeploymentRequestResult.RanSynchronously:
                response.StatusCode = HttpStatusCode.OK;
                break;

            case FetchDeploymentRequestResult.ConflictDeploymentInProgress:
                response.StatusCode = HttpStatusCode.Conflict;
                response.Content    = new StringContent(Resources.Error_DeploymentInProgress);
                break;

            case FetchDeploymentRequestResult.ConflictRunFromRemoteZipConfigured:
                response.StatusCode = HttpStatusCode.Conflict;
                response.Content    = new StringContent(Resources.Error_RunFromRemoteZipConfigured);
                break;

            default:
                response.StatusCode = HttpStatusCode.BadRequest;
                break;
            }

            return(response);
        }
예제 #17
0
        public async Task <HttpResponseMessage> ZipPushDeploy(
            HttpRequestMessage request,
            [FromUri] bool isAsync       = false,
            [FromUri] string author      = null,
            [FromUri] string authorEmail = null,
            [FromUri] string deployer    = DefaultDeployer,
            [FromUri] string message     = DefaultMessage)
        {
            using (_tracer.Step("ZipPushDeploy"))
            {
                var zipFileName = Path.ChangeExtension(Path.GetRandomFileName(), "zip");
                var zipFilePath = Path.Combine(_environment.ZipTempPath, zipFileName);

                using (_tracer.Step("Writing zip file to {0}", zipFilePath))
                {
                    using (var file = FileSystemHelpers.CreateFile(zipFilePath))
                    {
                        await request.Content.CopyToAsync(file);
                    }
                }

                var deploymentInfo = new ZipDeploymentInfo(_environment, _traceFactory)
                {
                    AllowDeploymentWhileScmDisabled = true,
                    Deployer                = deployer,
                    IsContinuous            = false,
                    AllowDeferredDeployment = false,
                    IsReusable              = false,
                    RepositoryUrl           = zipFilePath,
                    TargetChangeset         = DeploymentManager.CreateTemporaryChangeSet(message: "Deploying from pushed zip file"),
                    CommitId                = null,
                    RepositoryType          = RepositoryType.None,
                    Fetch = LocalZipFetch,
                    DoFullBuildByDefault = false,
                    Author      = author,
                    AuthorEmail = authorEmail,
                    Message     = message
                };

                var result = await _deploymentManager.FetchDeploy(deploymentInfo, isAsync, UriHelper.GetRequestUri(Request), "HEAD");

                var response = request.CreateResponse();

                switch (result)
                {
                case FetchDeploymentRequestResult.RunningAynschronously:
                    if (isAsync)
                    {
                        // latest deployment keyword reserved to poll till deployment done
                        response.Headers.Location = new Uri(UriHelper.GetRequestUri(Request),
                                                            String.Format("/api/deployments/{0}?deployer={1}&time={2}", Constants.LatestDeployment, deploymentInfo.Deployer, DateTime.UtcNow.ToString("yyy-MM-dd_HH-mm-ssZ")));
                    }
                    response.StatusCode = HttpStatusCode.Accepted;
                    break;

                case FetchDeploymentRequestResult.ForbiddenScmDisabled:
                    // Should never hit this for zip push deploy
                    response.StatusCode = HttpStatusCode.Forbidden;
                    _tracer.Trace("Scm is not enabled, reject all requests.");
                    break;

                case FetchDeploymentRequestResult.ConflictAutoSwapOngoing:
                    response.StatusCode = HttpStatusCode.Conflict;
                    response.Content    = new StringContent(Resources.Error_AutoSwapDeploymentOngoing);
                    break;

                case FetchDeploymentRequestResult.Pending:
                    // Shouldn't happen here, as we disallow deferral for this use case
                    response.StatusCode = HttpStatusCode.Accepted;
                    break;

                case FetchDeploymentRequestResult.RanSynchronously:
                    response.StatusCode = HttpStatusCode.OK;
                    break;

                case FetchDeploymentRequestResult.ConflictDeploymentInProgress:
                    response.StatusCode = HttpStatusCode.Conflict;
                    response.Content    = new StringContent(Resources.Error_DeploymentInProgress);
                    break;

                default:
                    response.StatusCode = HttpStatusCode.BadRequest;
                    break;
                }

                return(response);
            }
        }
예제 #18
0
        private async Task <HttpResponseMessage> PushDeployAsync(
            ZipDeploymentInfo deploymentInfo,
            bool isAsync)
        {
            var zipFileName = Path.ChangeExtension(Path.GetRandomFileName(), "zip");
            var zipFilePath = Path.Combine(_environment.ZipTempPath, zipFileName);

            using (_tracer.Step("Writing content to {0}", zipFilePath))
            {
                using (var file = FileSystemHelpers.CreateFile(zipFilePath))
                {
                    await Request.Content.CopyToAsync(file);
                }
            }

            deploymentInfo.RepositoryUrl = zipFilePath;

            var result = await _deploymentManager.FetchDeploy(deploymentInfo, isAsync, UriHelper.GetRequestUri(Request), "HEAD");

            var response = Request.CreateResponse();

            switch (result)
            {
            case FetchDeploymentRequestResult.RunningAynschronously:
                if (isAsync)
                {
                    // latest deployment keyword reserved to poll till deployment done
                    response.Headers.Location = new Uri(UriHelper.GetRequestUri(Request),
                                                        String.Format("/api/deployments/{0}?deployer={1}&time={2}", Constants.LatestDeployment, deploymentInfo.Deployer, DateTime.UtcNow.ToString("yyy-MM-dd_HH-mm-ssZ")));
                }
                response.StatusCode = HttpStatusCode.Accepted;
                break;

            case FetchDeploymentRequestResult.ForbiddenScmDisabled:
                // Should never hit this for zip push deploy
                response.StatusCode = HttpStatusCode.Forbidden;
                _tracer.Trace("Scm is not enabled, reject all requests.");
                break;

            case FetchDeploymentRequestResult.ConflictAutoSwapOngoing:
                response.StatusCode = HttpStatusCode.Conflict;
                response.Content    = new StringContent(Resources.Error_AutoSwapDeploymentOngoing);
                break;

            case FetchDeploymentRequestResult.Pending:
                // Shouldn't happen here, as we disallow deferral for this use case
                response.StatusCode = HttpStatusCode.Accepted;
                break;

            case FetchDeploymentRequestResult.RanSynchronously:
                response.StatusCode = HttpStatusCode.OK;
                break;

            case FetchDeploymentRequestResult.ConflictDeploymentInProgress:
                response.StatusCode = HttpStatusCode.Conflict;
                response.Content    = new StringContent(Resources.Error_DeploymentInProgress);
                break;

            default:
                response.StatusCode = HttpStatusCode.BadRequest;
                break;
            }

            return(response);
        }
예제 #19
0
        private async Task <IActionResult> PushDeployAsync(ZipDeploymentInfo deploymentInfo, bool isAsync)
        {
            var zipFilePath = Path.Combine(_environment.ZipTempPath, Guid.NewGuid() + ".zip");

            if (_settings.RunFromLocalZip())
            {
                await WriteSitePackageZip(deploymentInfo, _tracer);
            }
            else
            {
                using (_tracer.Step("Writing zip file to {0}", zipFilePath))
                {
                    if (HttpContext.Request.ContentType.Contains("multipart/form-data",
                                                                 StringComparison.OrdinalIgnoreCase))
                    {
                        FormValueProvider formModel;
                        using (_tracer.Step("Writing zip file to {0}", zipFilePath))
                        {
                            using (var file = System.IO.File.Create(zipFilePath))
                            {
                                formModel = await Request.StreamFile(file);
                            }
                        }
                    }
                    else
                    {
                        using (var file = System.IO.File.Create(zipFilePath))
                        {
                            await Request.Body.CopyToAsync(file);
                        }
                    }
                }
                deploymentInfo.RepositoryUrl = zipFilePath;
            }

            var result = await _deploymentManager.FetchDeploy(deploymentInfo, isAsync, UriHelper.GetRequestUri(Request), "HEAD");

            switch (result)
            {
            case FetchDeploymentRequestResult.RunningAynschronously:
                if (isAsync)
                {
                    // latest deployment keyword reserved to poll till deployment done
                    Response.GetTypedHeaders().Location =
                        new Uri(UriHelper.GetRequestUri(Request),
                                String.Format("/api/deployments/{0}?deployer={1}&time={2}", Constants.LatestDeployment, deploymentInfo.Deployer, DateTime.UtcNow.ToString("yyy-MM-dd_HH-mm-ssZ")));
                }
                return(Accepted());

            case FetchDeploymentRequestResult.ForbiddenScmDisabled:
                // Should never hit this for zip push deploy
                _tracer.Trace("Scm is not enabled, reject all requests.");
                return(Forbid());

            case FetchDeploymentRequestResult.ConflictAutoSwapOngoing:
                return(StatusCode(StatusCodes.Status409Conflict, Resources.Error_AutoSwapDeploymentOngoing));

            case FetchDeploymentRequestResult.Pending:
                // Shouldn't happen here, as we disallow deferral for this use case
                return(Accepted());

            case FetchDeploymentRequestResult.RanSynchronously:
                return(Ok());

            case FetchDeploymentRequestResult.ConflictDeploymentInProgress:
                return(StatusCode(StatusCodes.Status409Conflict, Resources.Error_DeploymentInProgress));

            case FetchDeploymentRequestResult.ConflictRunFromRemoteZipConfigured:
                return(StatusCode(StatusCodes.Status409Conflict, Resources.Error_AutoSwapDeploymentOngoing));

            default:
                return(BadRequest());
            }
        }
예제 #20
0
        private async Task <IActionResult> PushDeployAsync(ZipDeploymentInfo deploymentInfo, bool isAsync,
                                                           HttpContext context)
        {
            var zipFilePath = Path.Combine(_environment.ZipTempPath, Guid.NewGuid() + ".zip");

            if (_settings.RunFromLocalZip())
            {
                await WriteSitePackageZip(deploymentInfo, _tracer);
            }
            else
            {
                var oryxManifestFile = Path.Combine(_environment.WebRootPath, "oryx-manifest.toml");
                if (FileSystemHelpers.FileExists(oryxManifestFile))
                {
                    _tracer.Step("Removing previous build artifact's manifest file");
                    FileSystemHelpers.DeleteFileSafe(oryxManifestFile);
                }

                try
                {
                    var nodeModulesSymlinkFile       = Path.Combine(_environment.WebRootPath, "node_modules");
                    Mono.Unix.UnixSymbolicLinkInfo i = new Mono.Unix.UnixSymbolicLinkInfo(nodeModulesSymlinkFile);
                    if (i.FileType == Mono.Unix.FileTypes.SymbolicLink)
                    {
                        _tracer.Step("Removing node_modules symlink");
                        // TODO: Add support to remove Unix Symlink File in DeleteFileSafe
                        // FileSystemHelpers.DeleteFileSafe(nodeModulesSymlinkFile);
                        FileSystemHelpers.RemoveUnixSymlink(nodeModulesSymlinkFile, TimeSpan.FromSeconds(5));
                    }
                }
                catch (Exception)
                {
                    // best effort
                }

                using (_tracer.Step("Writing zip file to {0}", zipFilePath))
                {
                    if (!string.IsNullOrEmpty(context.Request.ContentType) &&
                        context.Request.ContentType.Contains("multipart/form-data", StringComparison.OrdinalIgnoreCase))
                    {
                        FormValueProvider formModel;
                        using (_tracer.Step("Writing zip file to {0}", zipFilePath))
                        {
                            using (var file = System.IO.File.Create(zipFilePath))
                            {
                                formModel = await Request.StreamFile(file);
                            }
                        }
                    }
                    else if (deploymentInfo.ZipURL != null)
                    {
                        using (_tracer.Step("Writing zip file from packageUri to {0}", zipFilePath))
                        {
                            using (var httpClient = new HttpClient())
                                using (var fileStream = new FileStream(zipFilePath,
                                                                       FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true))
                                {
                                    var zipUrlRequest  = new HttpRequestMessage(HttpMethod.Get, deploymentInfo.ZipURL);
                                    var zipUrlResponse = await httpClient.SendAsync(zipUrlRequest);

                                    try
                                    {
                                        zipUrlResponse.EnsureSuccessStatusCode();
                                    }
                                    catch (HttpRequestException hre)
                                    {
                                        _tracer.TraceError(hre, "Failed to get file from packageUri {0}", deploymentInfo.ZipURL);
                                        throw;
                                    }

                                    using (var content = await zipUrlResponse.Content.ReadAsStreamAsync())
                                    {
                                        await content.CopyToAsync(fileStream);
                                    }
                                }
                        }
                    }
                    else
                    {
                        using (var file = System.IO.File.Create(zipFilePath))
                        {
                            await Request.Body.CopyToAsync(file);
                        }
                    }
                }

                deploymentInfo.RepositoryUrl = zipFilePath;
            }

            var result =
                await _deploymentManager.FetchDeploy(deploymentInfo, isAsync, UriHelper.GetRequestUri(Request), "HEAD");

            switch (result)
            {
            case FetchDeploymentRequestResult.RunningAynschronously:
                if (isAsync)
                {
                    // latest deployment keyword reserved to poll till deployment done
                    Response.GetTypedHeaders().Location =
                        new Uri(UriHelper.GetRequestUri(Request),
                                String.Format("/api/deployments/{0}?deployer={1}&time={2}", Constants.LatestDeployment,
                                              deploymentInfo.Deployer, DateTime.UtcNow.ToString("yyy-MM-dd_HH-mm-ssZ")));
                }

                return(Accepted());

            case FetchDeploymentRequestResult.ForbiddenScmDisabled:
                // Should never hit this for zip push deploy
                _tracer.Trace("Scm is not enabled, reject all requests.");
                return(Forbid());

            case FetchDeploymentRequestResult.ConflictAutoSwapOngoing:
                return(StatusCode(StatusCodes.Status409Conflict, Resources.Error_AutoSwapDeploymentOngoing));

            case FetchDeploymentRequestResult.Pending:
                // Shouldn't happen here, as we disallow deferral for this use case
                return(Accepted());

            case FetchDeploymentRequestResult.RanSynchronously:
                return(Ok());

            case FetchDeploymentRequestResult.ConflictDeploymentInProgress:
                return(StatusCode(StatusCodes.Status409Conflict, Resources.Error_DeploymentInProgress));

            case FetchDeploymentRequestResult.ConflictRunFromRemoteZipConfigured:
                return(StatusCode(StatusCodes.Status409Conflict, Resources.Error_RunFromRemoteZipConfigured));

            default:
                return(BadRequest());
            }
        }