示例#1
0
        public async Task <string> ValidateContext(HostAssignmentContext assignmentContext)
        {
            string error = null;
            HttpResponseMessage response = null;

            try
            {
                var zipUrl = assignmentContext.ZipUrl;
                if (!string.IsNullOrEmpty(zipUrl))
                {
                    // make sure the zip uri is valid and accessible
                    await OperationManager.AttemptAsync(async() =>
                    {
                        try
                        {
                            var request = new HttpRequestMessage(HttpMethod.Head, zipUrl);
                            response    = await _client.SendAsync(request);
                            response.EnsureSuccessStatusCode();
                        }
                        catch (Exception)
                        {
                            throw;
                        }
                    }, retries : 2, delayBeforeRetry : 300 /*ms*/);
                }
            }
            catch (Exception)
            {
                error = $"Invalid zip url specified (StatusCode: {response?.StatusCode})";
            }

            return(error);
        }
示例#2
0
        public static async Task RestartMainSiteAsync(string requestId, TraceListener tracer)
        {
            Trace(tracer, TraceEventType.Information, "Requesting site restart");

            VerifyEnvironments();

            int attemptCount = 0;

            try
            {
                await OperationManager.AttemptAsync(async() =>
                {
                    attemptCount++;

                    Trace(tracer, TraceEventType.Information, $"Requesting site restart. Attempt #{attemptCount}");

                    await PostAsync(Constants.RestartApiPath, requestId, null);

                    Trace(tracer, TraceEventType.Information, $"Successfully requested a restart. Attempt #{attemptCount}");
                }, RestartRetryCount, RestartRetryIntervalInMilliSeconds);
            }
            catch
            {
                Trace(tracer, TraceEventType.Information, $"Failed to request a restart. Number of attempts: {attemptCount}");
                throw;
            }
        }
示例#3
0
        public async Task <bool> SendDeployStatusUpdate(DeployStatusApiResult updateStatusObj)
        {
            ITracer tracer       = _traceFactory.GetTracer();
            int     attemptCount = 0;

            try
            {
                await OperationManager.AttemptAsync(async() =>
                {
                    attemptCount++;

                    tracer.Trace($" PostAsync - Trying to send {updateStatusObj.DeploymentStatus} deployment status to {Constants.UpdateDeployStatusPath}. Deployment Id is {updateStatusObj.DeploymentId}");
                    await PostDeploymentHelper.PostAsync(Constants.UpdateDeployStatusPath, _environment.RequestId, content: JsonConvert.SerializeObject(updateStatusObj));
                }, 3, 5 * 1000);

                // If no exception is thrown, the operation was a success
                return(true);
            }
            catch (Exception ex)
            {
                tracer.TraceError($"Failed to request a post deployment status. Number of attempts: {attemptCount}. Exception: {ex}");
                // Do not throw the exception
                // We fail silently so that we do not fail the build altogether if this call fails
                //throw;

                return(false);
            }
        }
        private static async Task RemoveLinuxConsumptionFunctionAppWorkers(DeploymentContext context)
        {
            string webSiteHostName = System.Environment.GetEnvironmentVariable(SettingsKeys.WebsiteHostname);
            string sitename        = ServerConfiguration.GetApplicationName();

            context.Logger.Log($"Resetting all workers for {webSiteHostName}");

            try
            {
                await OperationManager.AttemptAsync(async() =>
                {
                    await PostDeploymentHelper.RemoveAllWorkersAsync(webSiteHostName, sitename);
                }, retries : 3, delayBeforeRetry : 2000);
            }
            catch (ArgumentException ae)
            {
                context.Logger.Log($"Reset all workers has malformed webSiteHostName or sitename {ae.Message}");
                throw new DeploymentFailedException(ae);
            }
            catch (HttpRequestException hre)
            {
                context.Logger.Log($"Reset all workers endpoint responded with {hre.Message}");
                throw new DeploymentFailedException(hre);
            }
        }
示例#5
0
        private static async Task <bool> TryFunctionsRuntimeSyncTriggers(string requestId)
        {
            try
            {
                var scmHostName = IsLocalHost ? HttpAuthority : HttpHost;

                var scmSplit = scmHostName.Split('.');

                if (!(scmSplit.Length > 1 && scmSplit[1].Equals("scm", StringComparison.OrdinalIgnoreCase)))
                {
                    return(false);
                }

                var functionsSiteHostName = string.Join(".", scmSplit.Where((el, idx) => idx != 1));

                await OperationManager.AttemptAsync(async() => await PostAsync(Constants.FunctionsSyncTriggersApiPath, requestId,
                                                                               hostName: functionsSiteHostName), retries : 3, delayBeforeRetry : 1000);

                return(true);
            }
            catch (Exception)
            {
                Trace(TraceEventType.Information, "Syncing function triggers by calling the functions runtime site failed.");
                return(false);
            }
        }
示例#6
0
        public static async Task UpdateSiteVersion(ArtifactDeploymentInfo deploymentInfo, IEnvironment environment, ITracer tracer)
        {
            var siteVersionPath = Path.Combine(environment.SitePackagesPath, Constants.PackageNameTxt);

            using (tracer.Step($"Updating {siteVersionPath} with deployment {deploymentInfo.ArtifactFileName}"))
            {
                await OperationManager.AttemptAsync(() => FileSystemHelpers.WriteAllTextToFileAsync(siteVersionPath, deploymentInfo.ArtifactFileName));
            }
        }
示例#7
0
 public async Task Delete()
 {
     await OperationManager.AttemptAsync(async() =>
     {
         using (var response = await Client.DeleteAsync(
                    $"/subscriptions/{_config.Subscription}/resourceGroups/{_config.ResourceGroup}/providers/Microsoft.Web/sites/{AppName}?api-version=2016-03-01"))
         {
             response.EnsureSuccessStatusCode();
         }
     }, 5, 2000);
 }
        private static async Task FunctionHostSyncTriggersAsync(DeploymentContext context)
        {
            string webSiteHostName = System.Environment.GetEnvironmentVariable(SettingsKeys.WebsiteHostname);

            context.Logger.Log($"Synchronizing function triggers for your function app {webSiteHostName}");

            try
            {
                await OperationManager.AttemptAsync(async() =>
                {
                    await PostDeploymentHelper.PerformFunctionHostSyncTriggersAsync(webSiteHostName);
                }, retries : 3, delayBeforeRetry : 2000);
            } catch (HttpRequestException hre)
            {
                context.Logger.Log($"Function triggers synchronization failed due to {hre.Message}");
            }
        }
        public async Task SiteExtensionShouldDeployWebJobs()
        {
            const string appName = "SiteExtensionShouldDeployWebJobs";

            await ApplicationManager.RunAsync(appName, async appManager =>
            {
                var manager = appManager.SiteExtensionManager;
                await CleanSiteExtensions(manager);

                TestTracer.Trace("Install site extension with jobs");
                await manager.InstallExtension("filecounterwithwebjobs", null, "https://www.myget.org/F/amitaptest/");

                TestTracer.Trace("Verify jobs were deployed");
                await OperationManager.AttemptAsync(async() =>
                {
                    var continuousJobs = (await appManager.JobsManager.ListContinuousJobsAsync()).ToArray();
                    Assert.Equal(1, continuousJobs.Length);
                    Assert.Equal("filecounterwithwebjobs(cjoba)", continuousJobs[0].Name);
                    TestTracer.Trace("Job status - {0}", continuousJobs[0].Status);
                    Assert.Equal("PendingRestart", continuousJobs[0].Status);
                }, 100, 500);

                TriggeredJob[] triggeredJobs;
                await OperationManager.AttemptAsync(async() =>
                {
                    triggeredJobs = (await appManager.JobsManager.ListTriggeredJobsAsync()).ToArray();
                    Assert.Equal(2, triggeredJobs.Length);
                    Assert.Equal("filecounterwithwebjobs(tjoba)", triggeredJobs[0].Name);
                    Assert.Equal("filecounterwithwebjobs(tjobb)", triggeredJobs[1].Name);
                }, 100, 500);

                TestTracer.Trace("Uninstall site extension with jobs");
                await manager.UninstallExtension("filecounterwithwebjobs");

                TestTracer.Trace("Verify jobs removed");
                await OperationManager.AttemptAsync(async() =>
                {
                    var continuousJobs2 = (await appManager.JobsManager.ListContinuousJobsAsync()).ToArray();
                    Assert.Equal(0, continuousJobs2.Length);

                    triggeredJobs = (await appManager.JobsManager.ListTriggeredJobsAsync()).ToArray();
                    Assert.Equal(0, triggeredJobs.Length);
                }, 100, 500);
            });
        }
示例#10
0
        /// <summary>
        /// This method tries to send the deployment status update through frontend to be saved to db
        /// Since frontend throttling is in place, we retry 3 times with 5 sec gaps in between
        /// </summary>
        /// <param name="updateStatusObj">Obj containing status to save to DB</param>
        /// <returns></returns>
        private async Task SendDeployStatusUpdate(DeployStatusApiResult updateStatusObj)
        {
            int attemptCount = 0;

            try
            {
                await OperationManager.AttemptAsync(async() =>
                {
                    attemptCount++;

                    _tracer.Trace($" PostAsync - Trying to send {updateStatusObj.DeploymentStatus} deployment status to {Constants.UpdateDeployStatusPath}");
                    await PostDeploymentHelper.PostAsync(Constants.UpdateDeployStatusPath, _environment.RequestId, JsonConvert.SerializeObject(updateStatusObj));
                }, 3, 5 *1000);
            }
            catch (Exception ex)
            {
                _tracer.TraceError($"Failed to request a post deployment status. Number of attempts: {attemptCount}. Exception: {ex}");
                throw;
            }
        }
示例#11
0
        private static Task DeleteSiteAsync(ServerManager iis, string siteName, bool deletePhysicalFiles = true)
        {
            var site = iis.Sites[siteName];

            if (site != null)
            {
                return(OperationManager.AttemptAsync(async() =>
                {
                    await Task.Run(() =>
                    {
                        if (deletePhysicalFiles)
                        {
                            string physicalPath = site.Applications[0].VirtualDirectories[0].PhysicalPath;
                            DeleteSafe(physicalPath);
                        }
                        iis.Sites.Remove(site);
                    });
                }));
            }

            return(Task.FromResult(0));
        }
示例#12
0
        public static async Task <BaseApp> CreateApp(HttpClient client, MyConfig config, ILogger <AppManager> logger, string appName)
        {
            return(await OperationManager.AttemptAsync(async() =>
            {
                using (var response = await client.PutAsJsonAsync(
                           $"/subscriptions/{config.Subscription}/resourceGroups/{config.ResourceGroup}/providers/Microsoft.Web/sites/{appName}?api-version=2016-03-01",
                           new
                {
                    location = config.Region,
                    kind = "functionapp",
                    properties = new
                    {
                        siteConfig = new
                        {
                            appSettings = new[]
                            {
                                new
                                {
                                    name = "FUNCFILE",
                                    value = "D:/local/funclite/index.js"
                                }
                            }
                        }
                    }
                }))
                {
                    response.EnsureSuccessStatusCode();

                    logger.LogInformation($"App {appName} was created successfully");

                    var json = await response.Content.ReadAsAsync <dynamic>();
                    var app = new WindowsApp(client, config, logger, json.properties);

                    await app.CompleteCreation();

                    return app;
                }
            }, 5, 2000));
        }
        private static async Task UpdateWebsiteRunFromPackageAppSetting(DeploymentContext context, CloudBlockBlob blob)
        {
            context.Logger.Log($"Updating WEBSITE_RUN_FROM_PACKAGE app setting for linux consumption app...");

            SharedAccessBlobPolicy sasConstraints = new SharedAccessBlobPolicy();

            sasConstraints.SharedAccessStartTime  = DateTimeOffset.UtcNow.AddMinutes(-5);
            sasConstraints.SharedAccessExpiryTime = DateTimeOffset.UtcNow.AddYears(10);
            sasConstraints.Permissions            = SharedAccessBlobPermissions.Read;
            string token = blob.GetSharedAccessSignature(sasConstraints);
            string sas   = blob.Uri + token;

            try
            {
                await OperationManager.AttemptAsync(async() =>
                {
                    await PostDeploymentHelper.UpdateWebsiteRunFromPackage(sas, context);
                }, retries : 3, delayBeforeRetry : 2000);
            }
            catch (ArgumentException ae)
            {
                context.Logger.Log($"Set run from package has malformed blob sas {ae.Message}");
                throw new DeploymentFailedException(ae);
            }
            catch (HttpRequestException hre)
            {
                context.Logger.Log($"Set run from package endpoint responded with {hre.Message}");
                Exception innerException = hre.InnerException;
                while (innerException != null)
                {
                    context.Logger.Log($"Inner Exception = {innerException.Message}");
                    innerException = innerException.InnerException;
                }
                throw new DeploymentFailedException(hre);
            }
        }
 public static async Task <HttpContent> GetZipContentFromURL(ZipDeploymentInfo zipDeploymentInfo, ITracer tracer)
 {
     using (var client = new HttpClient(new HttpClientHandler()))
     {
         Uri uri = new Uri(zipDeploymentInfo.ZipURL);
         using (tracer.Step("Trying to make a GET request to {0}", uri.AbsoluteUri))
         {
             try
             {
                 return(await OperationManager.AttemptAsync <HttpContent>(async() =>
                 {
                     HttpResponseMessage response = await client.GetAsync(uri);
                     response.EnsureSuccessStatusCode();
                     return response.Content;
                 }));
             }
             catch (Exception ex)
             {
                 tracer.TraceError(ex, "Could not make a successful GET request to {0}", uri.AbsoluteUri);
                 throw;
             }
         }
     }
 }
示例#15
0
        public async Task <Site> CreateSiteAsync(string applicationName)
        {
            using (ServerManager iis = GetServerManager())
            {
                try
                {
                    var siteBindingCongfigs    = new List <IBindingConfiguration>();
                    var svcSiteBindingCongfigs = new List <IBindingConfiguration>();
                    if (_context.Configuration != null && _context.Configuration.Bindings != null)
                    {
                        siteBindingCongfigs    = _context.Configuration.Bindings.Where(b => b.SiteType == SiteType.Live).ToList();
                        svcSiteBindingCongfigs = _context.Configuration.Bindings.Where(b => b.SiteType == SiteType.Service).ToList();
                    }

                    // Determine the host header values
                    List <BindingInformation> siteBindings        = BuildDefaultBindings(applicationName, siteBindingCongfigs).ToList();
                    List <BindingInformation> serviceSiteBindings = BuildDefaultBindings(applicationName, svcSiteBindingCongfigs).ToList();

                    // Create the service site for this site
                    var serviceSite = CreateSiteAsync(iis, applicationName, GetServiceSite(applicationName), _context.Configuration.ServiceSitePath, serviceSiteBindings);

                    // Create the main site
                    string siteName = GetLiveSite(applicationName);
                    string root     = _context.Paths.GetApplicationPath(applicationName);
                    string siteRoot = _context.Paths.GetLiveSitePath(applicationName);
                    string webRoot  = Path.Combine(siteRoot, Constants.WebRoot);

                    FileSystemHelpers.EnsureDirectory(webRoot);
                    File.WriteAllText(Path.Combine(webRoot, HostingStartHtml), HostingStartHtmlContents);

                    var site = CreateSiteAsync(iis, applicationName, siteName, webRoot, siteBindings);

                    // Map a path called _app to the site root under the service site
                    MapServiceSitePath(iis, applicationName, Constants.MappedSite, root);

                    // Commit the changes to iis
                    iis.CommitChanges();

                    var serviceUrls = serviceSite.Bindings
                                      .Select(url => String.Format("{0}://{1}:{2}/", url.Protocol, String.IsNullOrEmpty(url.Host) ? "localhost" : url.Host, url.EndPoint.Port))
                                      .ToList();

                    // Wait for the site to start
                    await OperationManager.AttemptAsync(() => WaitForSiteAsync(serviceUrls.First()));

                    // Set initial ScmType state to LocalGit
                    var settings = new RemoteDeploymentSettingsManager(serviceUrls.First() + "api/settings");
                    await settings.SetValue(SettingsKeys.ScmType, ScmType.LocalGit);

                    var siteUrls = site.Bindings
                                   .Select(url => String.Format("{0}://{1}:{2}/", url.Protocol, String.IsNullOrEmpty(url.Host) ? "localhost" : url.Host, url.EndPoint.Port))
                                   .ToList();

                    return(new Site
                    {
                        ServiceUrls = serviceUrls,
                        SiteUrls = siteUrls
                    });
                }
                catch
                {
                    try
                    {
                        DeleteSiteAsync(applicationName).Wait();
                    }
                    catch
                    {
                        // Don't let it throw if we're unable to delete a failed creation.
                    }
                    throw;
                }
            }
        }
示例#16
0
        public async Task <Site> CreateSiteAsync(string applicationName, ICredentials credentials = null)
        {
            using (var iis = GetServerManager())
            {
                try
                {
                    // Determine the host header values
                    List <string> siteBindings        = GetDefaultBindings(applicationName, _settingsResolver.SitesBaseUrl);
                    List <string> serviceSiteBindings = GetDefaultBindings(applicationName, _settingsResolver.ServiceSitesBaseUrl);

                    // Create the service site for this site
                    string serviceSiteName = GetServiceSite(applicationName);
                    var    serviceSite     = CreateSiteAsync(iis, applicationName, serviceSiteName, _pathResolver.ServiceSitePath, serviceSiteBindings, _settingsResolver.ServiceSiteBasicAuth, "kudu_service");

                    // Create the main site
                    string siteName = GetLiveSite(applicationName);
                    string root     = _pathResolver.GetApplicationPath(applicationName);
                    string siteRoot = _pathResolver.GetLiveSitePath(applicationName);
                    string webRoot  = Path.Combine(siteRoot, Constants.WebRoot);

                    FileSystemHelpers.EnsureDirectory(webRoot);
                    File.WriteAllText(Path.Combine(webRoot, HostingStartHtml), @"<html> 
<head>
<title>This web site has been successfully created</title>
<style type=""text/css"">
 BODY { color: #444444; background-color: #E5F2FF; font-family: verdana; margin: 0px; text-align: center; margin-top: 100px; }
 H1 { font-size: 16pt; margin-bottom: 4px; }
</style>
</head>
<body>
<h1>This web site has been successfully created</h1><br/>
</body> 
</html>");

                    var site = CreateSiteAsync(iis, applicationName, siteName, webRoot, siteBindings);

                    // Map a path called _app to the site root under the service site
                    MapServiceSitePath(iis, applicationName, Constants.MappedSite, root);

                    // Commit the changes to iis
                    iis.CommitChanges();

                    var serviceUrls = new List <Uri>();
                    foreach (var url in serviceSite.Bindings)
                    {
                        var builder = new UriBuilder
                        {
                            Host   = String.IsNullOrEmpty(url.Host) ? "localhost" : url.Host,
                            Scheme = url.Protocol,
                            Port   = url.EndPoint.Port == 80 ? -1 : url.EndPoint.Port
                        };

                        serviceUrls.Add(builder.Uri);
                    }

                    // Wait for the site to start
                    await OperationManager.AttemptAsync(() => WaitForSiteAsync(serviceUrls[0].ToString(), credentials));

                    // Set initial ScmType state to LocalGit
                    var settings = new RemoteDeploymentSettingsManager(serviceUrls.First() + "api/settings", credentials: credentials);
                    await settings.SetValue(SettingsKeys.ScmType, ScmType.LocalGit);

                    var siteUrls = new List <Uri>();
                    foreach (var url in site.Bindings)
                    {
                        var builder = new UriBuilder
                        {
                            Host   = String.IsNullOrEmpty(url.Host) ? "localhost" : url.Host,
                            Scheme = url.Protocol,
                            Port   = url.EndPoint.Port == 80 ? -1 : url.EndPoint.Port
                        };

                        siteUrls.Add(builder.Uri);
                    }

                    return(new Site
                    {
                        ServiceUrls = serviceUrls,
                        SiteUrls = siteUrls
                    });
                }
                catch
                {
                    try
                    {
                        DeleteSiteAsync(applicationName).Wait();
                    }
                    catch
                    {
                        // Don't let it throw if we're unable to delete a failed creation.
                    }
                    throw;
                }
            }
        }