コード例 #1
0
        public void ApplyConfiguration_Singleton()
        {
            JObject config = new JObject();
            config["id"] = ID;
            JObject singleton = new JObject();
            config["singleton"] = singleton;
            ScriptHostConfiguration scriptConfig = new ScriptHostConfiguration();

            ScriptHost.ApplyConfiguration(config, scriptConfig);

            Assert.Equal(ID, scriptConfig.HostConfig.HostId);
            Assert.Equal(15, scriptConfig.HostConfig.Singleton.LockPeriod.TotalSeconds);
            Assert.Equal(1, scriptConfig.HostConfig.Singleton.ListenerLockPeriod.TotalMinutes);
            Assert.Equal(1, scriptConfig.HostConfig.Singleton.ListenerLockRecoveryPollingInterval.TotalMinutes);
            Assert.Equal(TimeSpan.MaxValue, scriptConfig.HostConfig.Singleton.LockAcquisitionTimeout);
            Assert.Equal(5, scriptConfig.HostConfig.Singleton.LockAcquisitionPollingInterval.TotalSeconds);

            singleton["lockPeriod"] = "00:00:17";
            singleton["listenerLockPeriod"] = "00:00:22";
            singleton["listenerLockRecoveryPollingInterval"] = "00:00:33";
            singleton["lockAcquisitionTimeout"] = "00:05:00";
            singleton["lockAcquisitionPollingInterval"] = "00:00:08";

            ScriptHost.ApplyConfiguration(config, scriptConfig);

            Assert.Equal(17, scriptConfig.HostConfig.Singleton.LockPeriod.TotalSeconds);
            Assert.Equal(22, scriptConfig.HostConfig.Singleton.ListenerLockPeriod.TotalSeconds);
            Assert.Equal(33, scriptConfig.HostConfig.Singleton.ListenerLockRecoveryPollingInterval.TotalSeconds);
            Assert.Equal(5, scriptConfig.HostConfig.Singleton.LockAcquisitionTimeout.TotalMinutes);
            Assert.Equal(8, scriptConfig.HostConfig.Singleton.LockAcquisitionPollingInterval.TotalSeconds);
        }
コード例 #2
0
        public void ApplyConfiguration_Queues()
        {
            JObject config = new JObject();
            config["id"] = ID;
            JObject queuesConfig = new JObject();
            config["queues"] = queuesConfig;
            ScriptHostConfiguration scriptConfig = new ScriptHostConfiguration();

            ScriptHost.ApplyConfiguration(config, scriptConfig);

            Assert.Equal(ID, scriptConfig.HostConfig.HostId);
            Assert.Equal(60 * 1000, scriptConfig.HostConfig.Queues.MaxPollingInterval.TotalMilliseconds);
            Assert.Equal(16, scriptConfig.HostConfig.Queues.BatchSize);
            Assert.Equal(5, scriptConfig.HostConfig.Queues.MaxDequeueCount);
            Assert.Equal(8, scriptConfig.HostConfig.Queues.NewBatchThreshold);

            queuesConfig["maxPollingInterval"] = 5000;
            queuesConfig["batchSize"] = 17;
            queuesConfig["maxDequeueCount"] = 3;
            queuesConfig["newBatchThreshold"] = 123;

            ScriptHost.ApplyConfiguration(config, scriptConfig);

            Assert.Equal(5000, scriptConfig.HostConfig.Queues.MaxPollingInterval.TotalMilliseconds);
            Assert.Equal(17, scriptConfig.HostConfig.Queues.BatchSize);
            Assert.Equal(3, scriptConfig.HostConfig.Queues.MaxDequeueCount);
            Assert.Equal(123, scriptConfig.HostConfig.Queues.NewBatchThreshold);
        }
コード例 #3
0
        protected EndToEndTestFixture(string rootPath)
        {
            string connectionString = AmbientConnectionStringProvider.Instance.GetConnectionString(ConnectionStringNames.Storage);
            CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString);
            _queueClient = storageAccount.CreateCloudQueueClient();
            _blobClient = storageAccount.CreateCloudBlobClient();

            CreateTestStorageEntities();
            TraceWriter = new TestTraceWriter(TraceLevel.Verbose);

            ScriptHostConfiguration config = new ScriptHostConfiguration()
            {
                RootScriptPath = rootPath,
                TraceWriter = TraceWriter,
                FileLoggingEnabled = true
            };

            HostManager = new ScriptHostManager(config);

            Thread t = new Thread(_ =>
            {
                HostManager.RunAndBlock();
            });
            t.Start();

            TestHelpers.Await(() => HostManager.IsRunning).Wait();
        }
コード例 #4
0
 protected ScriptHost(ScriptHostConfiguration scriptConfig)
     : base(scriptConfig.HostConfig)
 {
     ScriptConfig = scriptConfig;
     FunctionErrors = new Dictionary<string, Collection<string>>(StringComparer.OrdinalIgnoreCase);
     NodeFunctionInvoker.UnhandledException += OnUnhandledException;
 }
コード例 #5
0
        public static CSharpScriptHost Create(ScriptHostConfiguration scriptConfig)
        {
            JobHostConfiguration config = new JobHostConfiguration();
            CSharpScriptHost scriptHost = new CSharpScriptHost(config, scriptConfig);
            scriptHost.Initialize();

            return scriptHost;
        }
コード例 #6
0
        protected ScriptHost(ScriptHostConfiguration scriptConfig) 
            : base(scriptConfig.HostConfig)
        {
            ScriptConfig = scriptConfig;

            if (scriptConfig.FileLoggingEnabled)
            {
                string hostLogFilePath = Path.Combine(scriptConfig.RootLogPath, "Host");
                _traceWriter = new FileTraceWriter(hostLogFilePath, TraceLevel.Verbose);
                scriptConfig.HostConfig.Tracing.Tracers.Add(_traceWriter);
            }
            else
            {
                _traceWriter = NullTraceWriter.Instance;
            }

            if (scriptConfig.TraceWriter != null)
            {
                scriptConfig.HostConfig.Tracing.Tracers.Add(scriptConfig.TraceWriter);
            }
            else
            {
                scriptConfig.TraceWriter = NullTraceWriter.Instance;
            }

            if (scriptConfig.FileWatchingEnabled)
            {
                _fileWatcher = new FileSystemWatcher(scriptConfig.RootScriptPath)
                {
                    IncludeSubdirectories = true,
                    EnableRaisingEvents = true
                };
                _fileWatcher.Changed += OnFileChanged;
                _fileWatcher.Created += OnFileChanged;
                _fileWatcher.Deleted += OnFileChanged;
                _fileWatcher.Renamed += OnFileChanged;
            }

            // If a file change should result in a restart, we debounce the event to
            // ensure that only a single restart is triggered within a specific time window.
            // This allows us to deal with a large set of file change events that might
            // result from a bulk copy/unzip operation. In such cases, we only want to
            // restart after ALL the operations are complete and there is a quiet period.
            _restart = (e) =>
            {
                _traceWriter.Verbose(string.Format("File change of type '{0}' detected for '{1}'", e.ChangeType, e.FullPath));
                _traceWriter.Verbose("Host configuration has changed. Signaling restart.");

                // signal host restart
                _restartEvent.Set();
            };
            _restart = _restart.Debounce(500);

            // take a snapshot so we can detect function additions/removals
            _directoryCountSnapshot = Directory.EnumerateDirectories(ScriptConfig.RootScriptPath).Count();
        }
コード例 #7
0
        static void Main(string[] args)
        {
            ScriptHostConfiguration config = new ScriptHostConfiguration()
            {
                RootPath = args[0]
            };

            ScriptHost host = ScriptHost.Create(config);
            host.RunAndBlock();
        }
コード例 #8
0
        public void ApplyConfiguration_TopLevel()
        {
            JObject config = new JObject();
            config["id"] = ID;
            ScriptHostConfiguration scriptConfig = new ScriptHostConfiguration();

            ScriptHost.ApplyConfiguration(config, scriptConfig);

            Assert.Equal(ID, scriptConfig.HostConfig.HostId);
        }
コード例 #9
0
        public static void Main(string[] args)
        {
            ScriptHostConfiguration config = new ScriptHostConfiguration()
            {
                ApplicationRootPath = Directory.GetCurrentDirectory(),
                HostAssembly = Assembly.GetExecutingAssembly()
            };

            ScriptHost host = CSharpScriptHost.Create(config);
            host.RunAndBlock();
        }
コード例 #10
0
        protected virtual void OnInitializeConfig(ScriptHostConfiguration config)
        {
            var loggingConnectionString = config.HostConfig.DashboardConnectionString;

            if (string.IsNullOrEmpty(loggingConnectionString))
            {
                // if no Dashboard connection string is provided, set this to null
                // to prevent host startup failure
                config.HostConfig.DashboardConnectionString = null;
            }
        }
コード例 #11
0
        static void Main(string[] args)
        {
            ScriptHostConfiguration config = new ScriptHostConfiguration()
            {
                ApplicationRootPath = Environment.CurrentDirectory,
                HostAssembly = Assembly.GetExecutingAssembly()
            };

            ScriptHost host = NodeScriptHost.Create(config);
            host.RunAndBlock();
        }
コード例 #12
0
 public ScriptHostManager(ScriptHostConfiguration config, IScriptEventManager eventManager = null, IScriptHostEnvironment environment = null)
     : this(config, ScriptSettingsManager.Instance, new ScriptHostFactory(), eventManager, environment)
 {
     if (config.FileWatchingEnabled)
     {
         // We only setup a subscription here as the actual ScriptHost will create the publisher
         // when initialized.
         _fileEventSubscription = EventManager.OfType <FileEvent>()
                                  .Where(f => string.Equals(f.Source, EventSources.ScriptFiles, StringComparison.Ordinal))
                                  .Subscribe(e => OnScriptFileChanged(null, e.FileChangeArguments));
     }
 }
コード例 #13
0
        public ScriptHostManager(ScriptHostConfiguration config,
                                 ScriptSettingsManager settingsManager,
                                 IScriptHostFactory scriptHostFactory,
                                 IScriptEventManager eventManager   = null,
                                 IScriptHostEnvironment environment = null)
        {
            _environment       = environment ?? this;
            _config            = config;
            _settingsManager   = settingsManager;
            _scriptHostFactory = scriptHostFactory;

            EventManager = eventManager ?? new ScriptEventManager();
        }
コード例 #14
0
        public static Manifest Read(ScriptHostConfiguration config, IEnumerable<FunctionDescriptorProvider> descriptionProviders)
        {
            string manifestFilePath = Path.Combine(config.ApplicationRootPath, @"scripts\manifest.json");
            Console.WriteLine(string.Format("Reading job manifest file '{0}'", manifestFilePath));
            string json = File.ReadAllText(manifestFilePath);

            JObject manifest = JObject.Parse(json);

            return new Manifest
            {
                Functions = ReadFunctions(manifest, descriptionProviders),
                Configuration = (JObject)manifest["config"]
            };
        }
コード例 #15
0
        protected EndToEndTestFixture(string rootPath)
        {
            CreateTestStorageEntities();
            TraceWriter = new TestTraceWriter(TraceLevel.Verbose);

            ScriptHostConfiguration config = new ScriptHostConfiguration()
            {
                RootScriptPath = rootPath,
                TraceWriter = TraceWriter
            };

            Host = ScriptHost.Create(config);
            Host.Start();
        }
コード例 #16
0
        internal static bool ConsoleLoggingEnabled(ScriptHostConfiguration config, ScriptSettingsManager settingsManager)
        {
            // console logging defaults to false, except for self host
            bool enableConsole = config.IsSelfHost;

            string configValue = settingsManager.Configuration.GetSection(ScriptConstants.ConsoleLoggingMode).Value;

            if (!string.IsNullOrEmpty(configValue))
            {
                // if it has been explicitly configured that value overrides default
                enableConsole = string.Compare(configValue, "always", StringComparison.OrdinalIgnoreCase) == 0 ? true : false;
            }

            return(enableConsole);
        }
コード例 #17
0
        public ScriptHostManager(ScriptHostConfiguration config,
                                 ScriptSettingsManager settingsManager,
                                 IScriptHostFactory scriptHostFactory,
                                 IScriptEventManager eventManager   = null,
                                 IScriptHostEnvironment environment = null)
        {
            _environment       = environment ?? this;
            _config            = config;
            _settingsManager   = settingsManager;
            _scriptHostFactory = scriptHostFactory;

            EventManager = eventManager ?? new ScriptEventManager();

            _structuredLogWriter = new StructuredLogWriter(EventManager, config.RootLogPath);
        }
コード例 #18
0
        static void Main(string[] args)
        {
            string rootPath = Environment.CurrentDirectory;
            if (args.Length > 0)
            {
                rootPath = (string)args[0];
            }

            ScriptHostConfiguration config = new ScriptHostConfiguration()
            {
                RootPath = rootPath
            };

            ScriptHost host = ScriptHost.Create(config);
            host.RunAndBlock();
        }
コード例 #19
0
        internal static void Initialize(ContainerBuilder builder, WebHostSettings settings)
        {
            ScriptHostConfiguration scriptHostConfig = new ScriptHostConfiguration()
            {
                RootScriptPath = settings.ScriptPath,
                RootLogPath = settings.LogPath,
                FileLoggingEnabled = true
            };

            // If running on Azure Web App, derive the host ID from the site name
            string hostId = Environment.GetEnvironmentVariable("WEBSITE_SITE_NAME");
            if (!String.IsNullOrEmpty(hostId))
            {
                // Truncate to the max host name length if needed
                const int MaximumHostIdLength = 32;
                if (hostId.Length > MaximumHostIdLength)
                {
                    hostId = hostId.Substring(0, MaximumHostIdLength);
                }

                // Trim any trailing - as they can cause problems with queue names
                hostId = hostId.TrimEnd('-');

                scriptHostConfig.HostConfig.HostId = hostId.ToLowerInvariant();
            }

            WebScriptHostManager scriptHostManager = new WebScriptHostManager(scriptHostConfig);
            builder.RegisterInstance<WebScriptHostManager>(scriptHostManager);

            SecretManager secretManager = new SecretManager(settings.SecretsPath);
            // Make sure that host secrets get created on startup if they don't exist
            secretManager.GetHostSecrets();
            builder.RegisterInstance<SecretManager>(secretManager);

            WebHookReceiverManager webHookReceiverManager = new WebHookReceiverManager(secretManager);
            builder.RegisterInstance<WebHookReceiverManager>(webHookReceiverManager);

            if (!settings.IsSelfHost)
            {
                HostingEnvironment.QueueBackgroundWorkItem((ct) => scriptHostManager.RunAndBlock(ct));
            }
            else
            {
                Task.Run(() => scriptHostManager.RunAndBlock());
            }
        }
コード例 #20
0
        public static ScriptHost Create(ScriptHostConfiguration scriptConfig = null)
        {
            if (scriptConfig == null)
            {
                scriptConfig = new ScriptHostConfiguration();
            }

            if (!Path.IsPathRooted(scriptConfig.RootScriptPath))
            {
                scriptConfig.RootScriptPath = Path.Combine(Environment.CurrentDirectory, scriptConfig.RootScriptPath);
            }

            ScriptHost scriptHost = new ScriptHost(scriptConfig);

            scriptHost.Initialize();

            return(scriptHost);
        }
コード例 #21
0
        public ScriptHostManager(ScriptHostConfiguration config,
                                 ScriptSettingsManager settingsManager,
                                 IScriptHostFactory scriptHostFactory,
                                 IScriptEventManager eventManager              = null,
                                 IScriptHostEnvironment environment            = null,
                                 ILoggerProviderFactory loggerProviderFactory  = null,
                                 HostPerformanceManager hostPerformanceManager = null)
        {
            if (config == null)
            {
                throw new ArgumentNullException(nameof(config));
            }
            if (settingsManager == null)
            {
                throw new ArgumentNullException(nameof(settingsManager));
            }

            scriptHostFactory      = scriptHostFactory ?? new ScriptHostFactory();
            _environment           = environment ?? this;
            _config                = config;
            _settingsManager       = settingsManager;
            _scriptHostFactory     = scriptHostFactory;
            _loggerProviderFactory = loggerProviderFactory;

            EventManager = eventManager ?? new ScriptEventManager();

            _structuredLogWriter = new StructuredLogWriter(EventManager, config.RootLogPath);
            _performanceManager  = hostPerformanceManager ?? new HostPerformanceManager(settingsManager, _config.HostHealthMonitor);

            if (config.FileWatchingEnabled && !settingsManager.FileSystemIsReadOnly)
            {
                // We only setup a subscription here as the actual ScriptHost will create the publisher
                // when initialized.
                _fileEventSubscription = EventManager.OfType <FileEvent>()
                                         .Where(f => string.Equals(f.Source, EventSources.ScriptFiles, StringComparison.Ordinal))
                                         .Subscribe(e => OnScriptFileChanged(null, e.FileChangeArguments));
            }

            if (ShouldMonitorHostHealth)
            {
                _healthCheckWindow    = new SlidingWindow <bool>(_config.HostHealthMonitor.HealthCheckWindow);
                _hostHealthCheckTimer = new Timer(OnHostHealthCheckTimer, null, TimeSpan.Zero, _config.HostHealthMonitor.HealthCheckInterval);
            }
        }
        /// <summary>
        /// Adds additional <see cref="ILoggerProvider"/>s to the <see cref="ILoggerFactory"/>.
        /// </summary>
        /// <param name="factory">The <see cref="ILoggerFactory"/>.</param>
        /// <param name="scriptConfig">The configuration.</param>
        public virtual void AddLoggerProviders(ILoggerFactory factory, ScriptHostConfiguration scriptConfig, ScriptSettingsManager settingsManager)
        {
            IMetricsLogger metricsLogger = scriptConfig.HostConfig.GetService <IMetricsLogger>();

            // Automatically register App Insights if the key is present
            if (!string.IsNullOrEmpty(settingsManager?.ApplicationInsightsInstrumentationKey))
            {
                metricsLogger?.LogEvent(MetricEventNames.ApplicationInsightsEnabled);

                ITelemetryClientFactory clientFactory = scriptConfig.HostConfig.GetService <ITelemetryClientFactory>() ??
                                                        new ScriptTelemetryClientFactory(settingsManager.ApplicationInsightsInstrumentationKey, scriptConfig.ApplicationInsightsSamplingSettings, scriptConfig.LogFilter.Filter);

                scriptConfig.HostConfig.LoggerFactory.AddApplicationInsights(clientFactory);
            }
            else
            {
                metricsLogger?.LogEvent(MetricEventNames.ApplicationInsightsDisabled);
            }
        }
コード例 #23
0
        private static Collection <ScriptBindingProvider> LoadBindingProviders(ScriptHostConfiguration config, JObject hostMetadata, TraceWriter traceWriter)
        {
            JobHostConfiguration hostConfig = config.HostConfig;

            // Register our built in extensions
            var bindingProviderTypes = new Collection <Type>()
            {
                // binding providers defined in this assembly
                typeof(WebJobsCoreScriptBindingProvider),
                typeof(ServiceBusScriptBindingProvider),

                // binding providers defined in known extension assemblies
                typeof(CoreExtensionsScriptBindingProvider),
                typeof(ApiHubScriptBindingProvider),
                typeof(DocumentDBScriptBindingProvider),
                typeof(MobileAppsScriptBindingProvider),
                typeof(NotificationHubScriptBindingProvider),
                typeof(SendGridScriptBindingProvider),
                typeof(TwilioScriptBindingProvider),
                typeof(BotFrameworkScriptBindingProvider)
            };

            // Create the binding providers
            var bindingProviders = new Collection <ScriptBindingProvider>();

            foreach (var bindingProviderType in bindingProviderTypes)
            {
                try
                {
                    var provider = (ScriptBindingProvider)Activator.CreateInstance(bindingProviderType, new object[] { hostConfig, hostMetadata, traceWriter });
                    bindingProviders.Add(provider);
                }
                catch (Exception ex)
                {
                    // If we're unable to load create a binding provider for any reason, log
                    // the error and continue
                    traceWriter.Error(string.Format("Unable to create binding provider '{0}'", bindingProviderType.FullName), ex);
                }
            }

            return(bindingProviders);
        }
コード例 #24
0
        public static void Main(string[] args)
        {
            if (args == null)
            {
                throw new ArgumentNullException("args");
            }

            string rootPath = Environment.CurrentDirectory;
            if (args.Length > 0)
            {
                rootPath = (string)args[0];
            }

            ScriptHostConfiguration config = new ScriptHostConfiguration()
            {
                RootScriptPath = rootPath
            };

            ScriptHostManager scriptHostManager = new ScriptHostManager(config);
            scriptHostManager.RunAndBlock();
        }    
コード例 #25
0
        public static ScriptHost Create(ScriptHostConfiguration scriptConfig = null)
        {
            if (scriptConfig == null)
            {
                scriptConfig = new ScriptHostConfiguration()
                {
                    RootPath = Environment.CurrentDirectory
                };
            }

            if (!Path.IsPathRooted(scriptConfig.RootPath))
            {
                scriptConfig.RootPath = Path.Combine(Environment.CurrentDirectory, scriptConfig.RootPath);
            }

            JobHostConfiguration config = new JobHostConfiguration();
            ScriptHost scriptHost = new ScriptHost(config, scriptConfig);
            scriptHost.Initialize();

            return scriptHost;
        }
コード例 #26
0
        internal static void Initialize(ContainerBuilder builder)
        {
            string logFilePath;
            string scriptRootPath;
            string secretsPath;
            string home = Environment.GetEnvironmentVariable("HOME");
            bool isLocal = string.IsNullOrEmpty(home);
            if (isLocal)
            {
                // we're running locally
                scriptRootPath = Path.Combine(HostingEnvironment.ApplicationPhysicalPath, @"..\..\sample");
                logFilePath = Path.Combine(Path.GetTempPath(), @"Functions");
                secretsPath = HttpContext.Current.Server.MapPath("~/App_Data/Secrets");
            }
            else
            {
                // we're running in Azure
                scriptRootPath = Path.Combine(home, @"site\wwwroot");
                logFilePath = Path.Combine(home, @"LogFiles\Application\Functions");
                secretsPath = Path.Combine(home, @"data\Functions\secrets");
            }

            ScriptHostConfiguration scriptHostConfig = new ScriptHostConfiguration()
            {
                RootScriptPath = scriptRootPath,
                RootLogPath = logFilePath,
                FileLoggingEnabled = true
            };
            WebScriptHostManager scriptHostManager = new WebScriptHostManager(scriptHostConfig);
            builder.RegisterInstance<WebScriptHostManager>(scriptHostManager);

            SecretManager secretManager = new SecretManager(secretsPath);
            builder.RegisterInstance<SecretManager>(secretManager);

            WebHookReceiverManager webHookRecieverManager = new WebHookReceiverManager(secretManager);
            builder.RegisterInstance<WebHookReceiverManager>(webHookRecieverManager);

            Task.Run(() => scriptHostManager.RunAndBlock(CancellationToken.None));
        }
コード例 #27
0
        public ScriptHostManager(ScriptHostConfiguration config,
                                 ScriptSettingsManager settingsManager,
                                 IScriptHostFactory scriptHostFactory,
                                 IScriptEventManager eventManager              = null,
                                 IScriptHostEnvironment environment            = null,
                                 ILoggerFactoryBuilder loggerFactoryBuilder    = null,
                                 HostPerformanceManager hostPerformanceManager = null)
        {
            if (config == null)
            {
                throw new ArgumentNullException(nameof(config));
            }
            if (settingsManager == null)
            {
                throw new ArgumentNullException(nameof(settingsManager));
            }

            scriptHostFactory     = scriptHostFactory ?? new ScriptHostFactory();
            _environment          = environment ?? this;
            _config               = config;
            _settingsManager      = settingsManager;
            _scriptHostFactory    = scriptHostFactory;
            _loggerFactoryBuilder = loggerFactoryBuilder;

            EventManager = eventManager ?? new ScriptEventManager();

            _structuredLogWriter = new StructuredLogWriter(EventManager, config.RootLogPath);
            _performanceManager  = hostPerformanceManager ?? new HostPerformanceManager(settingsManager);

            // TEMP : temporarily disabling this until the feature is improved
            bool periodicHealthCheckEnabled = false;

            if (periodicHealthCheckEnabled && config.HostHealthMonitorEnabled && settingsManager.IsAzureEnvironment)
            {
                _hostHealthCheckTimer = new Timer(OnHostHealthCheckTimer, null, TimeSpan.Zero, hostHealthCheckInterval);
            }
        }
コード例 #28
0
        public void RunAndBlock_DisposesOfHost_WhenExceptionIsThrown()
        {
            ScriptHostConfiguration config = new ScriptHostConfiguration()
            {
                RootScriptPath = Environment.CurrentDirectory,
                TraceWriter = NullTraceWriter.Instance
            };

            var hostMock = new Mock<TestScriptHost>(config);
            var factoryMock = new Mock<IScriptHostFactory>();
            factoryMock.Setup(f => f.Create(It.IsAny<ScriptHostConfiguration>()))
                .Returns(hostMock.Object);

            var target = new Mock<ScriptHostManager>(config, factoryMock.Object);
            target.Protected().Setup("OnHostStarted")
                .Throws(new Exception());

            hostMock.Protected().Setup("Dispose", true)
                .Callback(() => target.Object.Stop());

            Task.Run(() => target.Object.RunAndBlock()).Wait(5000);

            hostMock.Protected().Verify("Dispose", Times.Once(), true);
        }
コード例 #29
0
        internal static Collection<FunctionDescriptor> ReadFunctions(ScriptHostConfiguration config, IEnumerable<FunctionDescriptorProvider> descriptionProviders)
        {
            string scriptRootPath = config.RootPath;
            List<FunctionFolderInfo> functionFolderInfos = new List<FunctionFolderInfo>();
            foreach (var scriptDir in Directory.EnumerateDirectories(scriptRootPath))
            {
                FunctionFolderInfo functionInfo = new FunctionFolderInfo();

                // read the function config
                string functionConfigPath = Path.Combine(scriptDir, "function.json");
                if (!File.Exists(functionConfigPath))
                {
                    // not a function directory
                    continue;
                }
                string json = File.ReadAllText(functionConfigPath);
                functionInfo.Configuration = JObject.Parse(json);

                // unless the name is explicitly set in the config,
                // default it to the function folder name
                string name = (string)functionInfo.Configuration["name"];
                if (string.IsNullOrEmpty(name))
                {
                    functionInfo.Name = Path.GetFileNameWithoutExtension(scriptDir);
                }

                // determine the primary script
                string[] functionFiles = Directory.EnumerateFiles(scriptDir).Where(p => Path.GetFileName(p).ToLowerInvariant() != "function.json").ToArray();
                if (functionFiles.Length == 0)
                {
                    continue;
                }
                else if (functionFiles.Length == 1)
                {
                    // if there is only a single file, that file is primary
                    functionInfo.Source = functionFiles[0];
                }
                else
                {
                    // if there is a "run" file, that file is primary
                    string functionPrimary = null;
                    functionPrimary = functionFiles.FirstOrDefault(p => Path.GetFileNameWithoutExtension(p).ToLowerInvariant() == "run");
                    if (string.IsNullOrEmpty(functionPrimary))
                    {
                        // for Node, any index.js file is primary
                        functionPrimary = functionFiles.FirstOrDefault(p => Path.GetFileName(p).ToLowerInvariant() == "index.js");
                        if (string.IsNullOrEmpty(functionPrimary))
                        {
                            // finally, if there is an explicit primary file indicated
                            // in config, use it
                            JToken token = functionInfo.Configuration["source"];
                            if (token != null)
                            {
                                string sourceFileName = (string)token;
                                functionPrimary = Path.Combine(scriptDir, sourceFileName);
                            }
                        }
                    }

                    if (string.IsNullOrEmpty(functionPrimary))
                    {
                        // TODO: should this be an error?
                        continue;
                    }
                    functionInfo.Source = functionPrimary;
                }

                functionFolderInfos.Add(functionInfo);
            }

            var functions = ReadFunctions(functionFolderInfos, descriptionProviders);
            return functions;
        }
コード例 #30
0
        internal static void ApplyConfiguration(JObject config, ScriptHostConfiguration scriptConfig)
        {
            JobHostConfiguration hostConfig = scriptConfig.HostConfig;

            JArray functions = (JArray)config["functions"];
            if (functions != null && functions.Count > 0)
            {
                scriptConfig.Functions = new Collection<string>();
                foreach (var function in functions)
                {
                    scriptConfig.Functions.Add((string)function);
                }
            }

            // We may already have a host id, but the one from the JSON takes precedence
            JToken hostId = (JToken)config["id"];
            if (hostId != null)
            {
                hostConfig.HostId = (string)hostId;
            }
            else if (hostConfig.HostId == null)
            {
                throw new InvalidOperationException("An 'id' must be specified in the host configuration.");
            }

            JToken watchFiles = (JToken)config["watchFiles"];
            if (watchFiles != null && watchFiles.Type == JTokenType.Boolean)
            {
                scriptConfig.FileWatchingEnabled = (bool)watchFiles;
            }

            // Apply Queues configuration
            JObject configSection = (JObject)config["queues"];
            JToken value = null;
            if (configSection != null)
            {
                if (configSection.TryGetValue("maxPollingInterval", out value))
                {
                    hostConfig.Queues.MaxPollingInterval = TimeSpan.FromMilliseconds((int)value);
                }
                if (configSection.TryGetValue("batchSize", out value))
                {
                    hostConfig.Queues.BatchSize = (int)value;
                }
                if (configSection.TryGetValue("maxDequeueCount", out value))
                {
                    hostConfig.Queues.MaxDequeueCount = (int)value;
                }
                if (configSection.TryGetValue("newBatchThreshold", out value))
                {
                    hostConfig.Queues.NewBatchThreshold = (int)value;
                }
            }

            // Apply Singleton configuration
            configSection = (JObject)config["singleton"];
            value = null;
            if (configSection != null)
            {
                if (configSection.TryGetValue("lockPeriod", out value))
                {
                    hostConfig.Singleton.LockPeriod = TimeSpan.Parse((string)value, CultureInfo.InvariantCulture);
                }
                if (configSection.TryGetValue("listenerLockPeriod", out value))
                {
                    hostConfig.Singleton.ListenerLockPeriod = TimeSpan.Parse((string)value, CultureInfo.InvariantCulture);
                }
                if (configSection.TryGetValue("listenerLockRecoveryPollingInterval", out value))
                {
                    hostConfig.Singleton.ListenerLockRecoveryPollingInterval = TimeSpan.Parse((string)value, CultureInfo.InvariantCulture);
                }
                if (configSection.TryGetValue("lockAcquisitionTimeout", out value))
                {
                    hostConfig.Singleton.LockAcquisitionTimeout = TimeSpan.Parse((string)value, CultureInfo.InvariantCulture);
                }
                if (configSection.TryGetValue("lockAcquisitionPollingInterval", out value))
                {
                    hostConfig.Singleton.LockAcquisitionPollingInterval = TimeSpan.Parse((string)value, CultureInfo.InvariantCulture);
                }
            }

            // Apply ServiceBus configuration
            ServiceBusConfiguration serviceBusConfig = new ServiceBusConfiguration();
            configSection = (JObject)config["serviceBus"];
            value = null;
            if (configSection != null)
            {
                if (configSection.TryGetValue("maxConcurrentCalls", out value))
                {
                    serviceBusConfig.MessageOptions.MaxConcurrentCalls = (int)value;
                }
            }
            hostConfig.UseServiceBus(serviceBusConfig);

            // Apply Tracing/Logging configuration
            configSection = (JObject)config["tracing"];
            if (configSection != null)
            {
                if (configSection.TryGetValue("consoleLevel", out value))
                {
                    TraceLevel consoleLevel;
                    if (Enum.TryParse<TraceLevel>((string)value, true, out consoleLevel))
                    {
                        hostConfig.Tracing.ConsoleLevel = consoleLevel;
                    }
                }

                if (configSection.TryGetValue("fileLoggingEnabled", out value))
                {
                    scriptConfig.FileLoggingEnabled = (bool)value;
                }
            }

            hostConfig.UseTimers();
            hostConfig.UseCore();
        }
コード例 #31
0
        internal static Collection <FunctionDescriptor> ReadFunctions(ScriptHostConfiguration config, IEnumerable <FunctionDescriptorProvider> descriptionProviders)
        {
            string scriptRootPath             = config.RootScriptPath;
            List <FunctionMetadata> metadatas = new List <FunctionMetadata>();

            foreach (var scriptDir in Directory.EnumerateDirectories(scriptRootPath))
            {
                // read the function config
                string functionConfigPath = Path.Combine(scriptDir, "function.json");
                if (!File.Exists(functionConfigPath))
                {
                    // not a function directory
                    continue;
                }

                string           json     = File.ReadAllText(functionConfigPath);
                JObject          jObject  = JObject.Parse(json);
                FunctionMetadata metadata = null;

                // unless the name is explicitly set in the config,
                // default it to the function folder name
                string name = (string)jObject["name"];
                if (string.IsNullOrEmpty(name))
                {
                    name = Path.GetFileNameWithoutExtension(scriptDir);
                }

                if (!TryParseFunctionMetadata(name, jObject, out metadata))
                {
                    // TODO: Handle error
                    continue;
                }

                // determine the primary script
                string[] functionFiles = Directory.EnumerateFiles(scriptDir).Where(p => Path.GetFileName(p).ToLowerInvariant() != "function.json").ToArray();
                if (functionFiles.Length == 0)
                {
                    continue;
                }
                else if (functionFiles.Length == 1)
                {
                    // if there is only a single file, that file is primary
                    metadata.Source = functionFiles[0];
                }
                else
                {
                    // if there is a "run" file, that file is primary
                    string functionPrimary = null;
                    functionPrimary = functionFiles.FirstOrDefault(p => Path.GetFileNameWithoutExtension(p).ToLowerInvariant() == "run");
                    if (string.IsNullOrEmpty(functionPrimary))
                    {
                        // for Node, any index.js file is primary
                        functionPrimary = functionFiles.FirstOrDefault(p => Path.GetFileName(p).ToLowerInvariant() == "index.js");
                        if (string.IsNullOrEmpty(functionPrimary))
                        {
                            // finally, if there is an explicit primary file indicated
                            // in config, use it
                            JToken token = jObject["source"];
                            if (token != null)
                            {
                                string sourceFileName = (string)token;
                                functionPrimary = Path.Combine(scriptDir, sourceFileName);
                            }
                        }
                    }

                    if (string.IsNullOrEmpty(functionPrimary))
                    {
                        // TODO: should this be an error?
                        continue;
                    }
                    metadata.Source = functionPrimary;
                }

                metadatas.Add(metadata);
            }

            var functions = ReadFunctions(metadatas, descriptionProviders);

            return(functions);
        }
コード例 #32
0
 public ScriptHostManager(ScriptHostConfiguration config, ScriptSettingsManager settingsManager, IScriptHostFactory scriptHostFactory)
 {
     _config = config;
     _settingsManager = settingsManager;
     _scriptHostFactory = scriptHostFactory;
 }
コード例 #33
0
 protected virtual void OnInitializeConfig(ScriptHostConfiguration config)
 {
 }
コード例 #34
0
 protected virtual void OnInitializeConfig(ScriptHostConfiguration config)
 {
 }
コード例 #35
0
 public ScriptHostManager(ScriptHostConfiguration config)
 {
     _config = config;
 }
コード例 #36
0
 public ScriptHostManager(ScriptHostConfiguration config, ScriptSettingsManager settingsManager, IScriptHostFactory scriptHostFactory)
 {
     _config            = config;
     _settingsManager   = settingsManager;
     _scriptHostFactory = scriptHostFactory;
 }
コード例 #37
0
 public ScriptHostManager(ScriptHostConfiguration config)
 {
     _config = config;
 }
コード例 #38
0
 public ScriptHostManager(ScriptHostConfiguration config, IScriptHostFactory scriptHostFactory)
 {
     _config            = config;
     _scriptHostFactory = scriptHostFactory;
 }
コード例 #39
0
 public ScriptHostManager(ScriptHostConfiguration config)
     : this(config, new ScriptHostFactory())
 {
 }
コード例 #40
0
 protected ScriptHost(JobHostConfiguration config, ScriptHostConfiguration scriptConfig)
     : base(config)
 {
     _jobHostConfig = config;
     _scriptHostConfig = scriptConfig;
 }
コード例 #41
0
 public ScriptHost Create(ScriptSettingsManager settingsManager, ScriptHostConfiguration config)
 {
     return ScriptHost.Create(settingsManager, config);
 }
コード例 #42
0
        public virtual IEnumerable <ILoggerProvider> CreateLoggerProviders(string hostInstanceId, ScriptHostConfiguration scriptConfig, ScriptSettingsManager settingsManager,
                                                                           Func <bool> isFileLoggingEnabled, Func <bool> isPrimary)
        {
            IList <ILoggerProvider> providers = new List <ILoggerProvider>();

            IMetricsLogger metricsLogger = scriptConfig.HostConfig.GetService <IMetricsLogger>();

            // Automatically register App Insights if the key is present
            if (!string.IsNullOrEmpty(settingsManager?.ApplicationInsightsInstrumentationKey))
            {
                metricsLogger?.LogEvent(MetricEventNames.ApplicationInsightsEnabled);

                ITelemetryClientFactory clientFactory = scriptConfig.HostConfig.GetService <ITelemetryClientFactory>() ??
                                                        new ScriptTelemetryClientFactory(settingsManager.ApplicationInsightsInstrumentationKey, scriptConfig.ApplicationInsightsSamplingSettings, scriptConfig.LogFilter.Filter);

                providers.Add(new ApplicationInsightsLoggerProvider(clientFactory));
            }
            else
            {
                metricsLogger?.LogEvent(MetricEventNames.ApplicationInsightsDisabled);
            }

            providers.Add(new FunctionFileLoggerProvider(hostInstanceId, scriptConfig.RootLogPath, isFileLoggingEnabled, isPrimary));
            providers.Add(new HostFileLoggerProvider(hostInstanceId, scriptConfig.RootLogPath, isFileLoggingEnabled));

            if (settingsManager.Configuration.GetSection("host:logger:consoleLoggingMode").Value == "always")
            {
                providers.Add(new ConsoleLoggerProvider(scriptConfig.LogFilter.Filter, includeScopes: true));
            }

            return(providers);
        }
コード例 #43
0
 public ScriptHostManager(ScriptHostConfiguration config)
     : this(config, ScriptSettingsManager.Instance, new ScriptHostFactory())
 {
 }
コード例 #44
0
 public ScriptHost Create(ScriptSettingsManager settingsManager, ScriptHostConfiguration config)
 {
     return(ScriptHost.Create(settingsManager, config));
 }
コード例 #45
0
        public static ScriptHost Create(ScriptHostConfiguration scriptConfig = null)
        {
            if (scriptConfig == null)
            {
                scriptConfig = new ScriptHostConfiguration();
            }

            if (!Path.IsPathRooted(scriptConfig.RootScriptPath))
            {
                scriptConfig.RootScriptPath = Path.Combine(Environment.CurrentDirectory, scriptConfig.RootScriptPath);
            }

            ScriptHost scriptHost = new ScriptHost(scriptConfig);
            try
            {
                scriptHost.Initialize();
            }
            catch (Exception ex)
            {
                if (scriptHost.TraceWriter != null)
                {
                    scriptHost.TraceWriter.Error("ScriptHost initialization failed", ex);
                }
                throw;
            }

            return scriptHost;
        }
コード例 #46
0
 protected ScriptHost(ScriptHostConfiguration scriptConfig)
     : base(scriptConfig.HostConfig)
 {
     ScriptConfig   = scriptConfig;
     FunctionErrors = new Dictionary <string, Collection <string> >(StringComparer.OrdinalIgnoreCase);
 }
コード例 #47
0
        private Collection<FunctionDescriptor> ReadFunctions(ScriptHostConfiguration config, IEnumerable<FunctionDescriptorProvider> descriptorProviders)
        {
            string scriptRootPath = config.RootScriptPath;
            List<FunctionMetadata> metadatas = new List<FunctionMetadata>();

            foreach (var scriptDir in Directory.EnumerateDirectories(scriptRootPath))
            {
                string functionName = null;

                try
                {
                    // read the function config
                    string functionConfigPath = Path.Combine(scriptDir, ScriptConstants.FunctionConfigFileName);
                    if (!File.Exists(functionConfigPath))
                    {
                        // not a function directory
                        continue;
                    }

                    functionName = Path.GetFileNameWithoutExtension(scriptDir);

                    if (ScriptConfig.Functions != null &&
                        !ScriptConfig.Functions.Contains(functionName, StringComparer.OrdinalIgnoreCase))
                    {
                        // a functions filter has been specified and the current function is
                        // not in the filter list
                        continue;
                    }

                    // TODO: we need to define a json schema document and do
                    // schema validation
                    string json = File.ReadAllText(functionConfigPath);
                    JObject configMetadata = JObject.Parse(json);
                    FunctionMetadata metadata = ParseFunctionMetadata(functionName, config.HostConfig.NameResolver, configMetadata);

                    // determine the primary script
                    string[] functionFiles = Directory.EnumerateFiles(scriptDir).Where(p => Path.GetFileName(p).ToLowerInvariant() != ScriptConstants.FunctionConfigFileName).ToArray();
                    if (functionFiles.Length == 0)
                    {
                        AddFunctionError(functionName, "No function script files present.");
                        continue;
                    }
                    else if (functionFiles.Length == 1)
                    {
                        // if there is only a single file, that file is primary
                        metadata.Source = functionFiles[0];
                    }
                    else
                    {
                        // if there is a "run" file, that file is primary
                        string functionPrimary = null;
                        functionPrimary = functionFiles.FirstOrDefault(p => Path.GetFileNameWithoutExtension(p).ToLowerInvariant() == "run");
                        if (string.IsNullOrEmpty(functionPrimary))
                        {
                            // for Node, any index.js file is primary
                            functionPrimary = functionFiles.FirstOrDefault(p => Path.GetFileName(p).ToLowerInvariant() == "index.js");
                            if (string.IsNullOrEmpty(functionPrimary))
                            {
                                // finally, if there is an explicit primary file indicated
                                // in config, use it
                                JToken token = configMetadata["source"];
                                if (token != null)
                                {
                                    string sourceFileName = (string)token;
                                    functionPrimary = Path.Combine(scriptDir, sourceFileName);
                                }
                            }
                        }

                        if (string.IsNullOrEmpty(functionPrimary))
                        {
                            AddFunctionError(functionName, "Unable to determine primary function script.");
                            continue;
                        }
                        metadata.Source = functionPrimary;
                    }

                    metadata.ScriptType = ParseScriptType(metadata.Source);

                    metadatas.Add(metadata);
                }
                catch (Exception ex)
                {
                    // log any unhandled exceptions and continue
                    AddFunctionError(functionName, ex.Message);
                }
            }

            return ReadFunctions(metadatas, descriptorProviders);
        }
コード例 #48
0
        internal static void ApplyConfiguration(JObject config, ScriptHostConfiguration scriptConfig)
        {
            JobHostConfiguration hostConfig = scriptConfig.HostConfig;

            JArray functions = (JArray)config["functions"];

            if (functions != null && functions.Count > 0)
            {
                scriptConfig.Functions = new Collection <string>();
                foreach (var function in functions)
                {
                    scriptConfig.Functions.Add((string)function);
                }
            }

            // We may already have a host id, but the one from the JSON takes precedence
            JToken hostId = (JToken)config["id"];

            if (hostId != null)
            {
                hostConfig.HostId = (string)hostId;
            }
            else if (hostConfig.HostId == null)
            {
                throw new InvalidOperationException("An 'id' must be specified in the host configuration.");
            }

            JToken watchFiles = (JToken)config["watchFiles"];

            if (watchFiles != null && watchFiles.Type == JTokenType.Boolean)
            {
                scriptConfig.FileWatchingEnabled = (bool)watchFiles;
            }

            // Apply Queues configuration
            JObject configSection = (JObject)config["queues"];
            JToken  value         = null;

            if (configSection != null)
            {
                if (configSection.TryGetValue("maxPollingInterval", out value))
                {
                    hostConfig.Queues.MaxPollingInterval = TimeSpan.FromMilliseconds((int)value);
                }
                if (configSection.TryGetValue("batchSize", out value))
                {
                    hostConfig.Queues.BatchSize = (int)value;
                }
                if (configSection.TryGetValue("maxDequeueCount", out value))
                {
                    hostConfig.Queues.MaxDequeueCount = (int)value;
                }
                if (configSection.TryGetValue("newBatchThreshold", out value))
                {
                    hostConfig.Queues.NewBatchThreshold = (int)value;
                }
            }

            // Apply Singleton configuration
            configSection = (JObject)config["singleton"];
            value         = null;
            if (configSection != null)
            {
                if (configSection.TryGetValue("lockPeriod", out value))
                {
                    hostConfig.Singleton.LockPeriod = TimeSpan.Parse((string)value, CultureInfo.InvariantCulture);
                }
                if (configSection.TryGetValue("listenerLockPeriod", out value))
                {
                    hostConfig.Singleton.ListenerLockPeriod = TimeSpan.Parse((string)value, CultureInfo.InvariantCulture);
                }
                if (configSection.TryGetValue("listenerLockRecoveryPollingInterval", out value))
                {
                    hostConfig.Singleton.ListenerLockRecoveryPollingInterval = TimeSpan.Parse((string)value, CultureInfo.InvariantCulture);
                }
                if (configSection.TryGetValue("lockAcquisitionTimeout", out value))
                {
                    hostConfig.Singleton.LockAcquisitionTimeout = TimeSpan.Parse((string)value, CultureInfo.InvariantCulture);
                }
                if (configSection.TryGetValue("lockAcquisitionPollingInterval", out value))
                {
                    hostConfig.Singleton.LockAcquisitionPollingInterval = TimeSpan.Parse((string)value, CultureInfo.InvariantCulture);
                }
            }

            // Apply ServiceBus configuration
            ServiceBusConfiguration serviceBusConfig = new ServiceBusConfiguration();

            configSection = (JObject)config["serviceBus"];
            value         = null;
            if (configSection != null)
            {
                if (configSection.TryGetValue("maxConcurrentCalls", out value))
                {
                    serviceBusConfig.MessageOptions.MaxConcurrentCalls = (int)value;
                }
            }
            hostConfig.UseServiceBus(serviceBusConfig);

            // Apply Tracing/Logging configuration
            configSection = (JObject)config["tracing"];
            if (configSection != null)
            {
                if (configSection.TryGetValue("consoleLevel", out value))
                {
                    TraceLevel consoleLevel;
                    if (Enum.TryParse <TraceLevel>((string)value, true, out consoleLevel))
                    {
                        hostConfig.Tracing.ConsoleLevel = consoleLevel;
                    }
                }

                if (configSection.TryGetValue("fileLoggingEnabled", out value))
                {
                    scriptConfig.FileLoggingEnabled = (bool)value;
                }
            }

            hostConfig.UseTimers();
            hostConfig.UseCore();
        }
コード例 #49
0
 public FunctionTraceWriterFactory(string functionName, ScriptHostConfiguration scriptHostConfig)
 {
     _functionName     = functionName;
     _scriptHostConfig = scriptHostConfig;
 }
コード例 #50
0
 public ScriptHost Create(IScriptHostEnvironment environment, ScriptSettingsManager settingsManager, ScriptHostConfiguration config)
 {
     return(ScriptHost.Create(environment, config, settingsManager));
 }
コード例 #51
0
        private Collection <FunctionDescriptor> ReadFunctions(ScriptHostConfiguration config, IEnumerable <FunctionDescriptorProvider> descriptorProviders)
        {
            string scriptRootPath             = config.RootScriptPath;
            List <FunctionMetadata> metadatas = new List <FunctionMetadata>();

            foreach (var scriptDir in Directory.EnumerateDirectories(scriptRootPath))
            {
                string functionName = null;

                try
                {
                    // read the function config
                    string functionConfigPath = Path.Combine(scriptDir, ScriptConstants.FunctionMetadataFileName);
                    if (!File.Exists(functionConfigPath))
                    {
                        // not a function directory
                        continue;
                    }

                    functionName = Path.GetFileNameWithoutExtension(scriptDir);

                    if (ScriptConfig.Functions != null &&
                        !ScriptConfig.Functions.Contains(functionName, StringComparer.OrdinalIgnoreCase))
                    {
                        // a functions filter has been specified and the current function is
                        // not in the filter list
                        continue;
                    }

                    ValidateFunctionName(functionName);

                    // TODO: we need to define a json schema document and do
                    // schema validation and give more informative responses
                    string           json           = File.ReadAllText(functionConfigPath);
                    JObject          functionConfig = JObject.Parse(json);
                    FunctionMetadata metadata       = ParseFunctionMetadata(functionName, functionConfig);

                    if (metadata.IsExcluded)
                    {
                        TraceWriter.Info(string.Format("Function '{0}' is marked as excluded", functionName));
                        continue;
                    }

                    if (metadata.IsDisabled)
                    {
                        TraceWriter.Info(string.Format("Function '{0}' is disabled", functionName));
                    }

                    // determine the primary script
                    string[] functionFiles = Directory.EnumerateFiles(scriptDir).Where(p => Path.GetFileName(p).ToLowerInvariant() != ScriptConstants.FunctionMetadataFileName).ToArray();
                    if (functionFiles.Length == 0)
                    {
                        AddFunctionError(functionName, "No function script files present.");
                        continue;
                    }
                    string scriptFile = DeterminePrimaryScriptFile(functionConfig, functionFiles);
                    if (string.IsNullOrEmpty(scriptFile))
                    {
                        AddFunctionError(functionName,
                                         "Unable to determine the primary function script. Try renaming your entry point script to 'run' (or 'index' in the case of Node), " +
                                         "or alternatively you can specify the name of the entry point script explicitly by adding a 'scriptFile' property to your function metadata.");
                        continue;
                    }
                    metadata.ScriptFile = scriptFile;

                    // determine the script type based on the primary script file extension
                    metadata.ScriptType = ParseScriptType(metadata.ScriptFile);

                    metadata.EntryPoint = (string)functionConfig["entryPoint"];

                    metadatas.Add(metadata);
                }
                catch (Exception ex)
                {
                    // log any unhandled exceptions and continue
                    AddFunctionError(functionName, ex.Message);
                }
            }

            return(ReadFunctions(metadatas, descriptorProviders));
        }
コード例 #52
0
        internal static void ApplyConfiguration(JObject config, ScriptHostConfiguration scriptConfig)
        {
            JobHostConfiguration hostConfig = scriptConfig.HostConfig;

            JToken hostId = (JToken)config["id"];

            if (hostId == null)
            {
                throw new InvalidOperationException("An 'id' must be specified in the host configuration.");
            }
            hostConfig.HostId = (string)hostId;

            JToken watchFiles = (JToken)config["watchFiles"];

            if (watchFiles != null && watchFiles.Type == JTokenType.Boolean)
            {
                scriptConfig.FileWatchingEnabled = (bool)watchFiles;
            }

            // Apply Queues configuration
            JObject configSection = (JObject)config["queues"];
            JToken  value         = null;

            if (configSection != null)
            {
                if (configSection.TryGetValue("maxPollingInterval", out value))
                {
                    hostConfig.Queues.MaxPollingInterval = TimeSpan.FromMilliseconds((int)value);
                }
                if (configSection.TryGetValue("batchSize", out value))
                {
                    hostConfig.Queues.BatchSize = (int)value;
                }
                if (configSection.TryGetValue("maxDequeueCount", out value))
                {
                    hostConfig.Queues.MaxDequeueCount = (int)value;
                }
                if (configSection.TryGetValue("newBatchThreshold", out value))
                {
                    hostConfig.Queues.NewBatchThreshold = (int)value;
                }
            }

            // Apply Singleton configuration
            configSection = (JObject)config["singleton"];
            value         = null;
            if (configSection != null)
            {
                if (configSection.TryGetValue("lockPeriod", out value))
                {
                    hostConfig.Singleton.LockPeriod = TimeSpan.Parse((string)value);
                }
                if (configSection.TryGetValue("listenerLockPeriod", out value))
                {
                    hostConfig.Singleton.ListenerLockPeriod = TimeSpan.Parse((string)value);
                }
                if (configSection.TryGetValue("listenerLockRecoveryPollingInterval", out value))
                {
                    hostConfig.Singleton.ListenerLockRecoveryPollingInterval = TimeSpan.Parse((string)value);
                }
                if (configSection.TryGetValue("lockAcquisitionTimeout", out value))
                {
                    hostConfig.Singleton.LockAcquisitionTimeout = TimeSpan.Parse((string)value);
                }
                if (configSection.TryGetValue("lockAcquisitionPollingInterval", out value))
                {
                    hostConfig.Singleton.LockAcquisitionPollingInterval = TimeSpan.Parse((string)value);
                }
            }

            // Apply ServiceBus configuration
            ServiceBusConfiguration sbConfig = new ServiceBusConfiguration();

            configSection = (JObject)config["serviceBus"];
            value         = null;
            if (configSection != null)
            {
                if (configSection.TryGetValue("maxConcurrentCalls", out value))
                {
                    sbConfig.MessageOptions.MaxConcurrentCalls = (int)value;
                }
            }
            hostConfig.UseServiceBus(sbConfig);

            // Apply Tracing configuration
            configSection = (JObject)config["tracing"];
            if (configSection != null && configSection.TryGetValue("consoleLevel", out value))
            {
                TraceLevel consoleLevel;
                if (Enum.TryParse <TraceLevel>((string)value, true, out consoleLevel))
                {
                    hostConfig.Tracing.ConsoleLevel = consoleLevel;
                }
            }

            hostConfig.UseTimers();
            hostConfig.UseCore();
        }
コード例 #53
0
        private Collection <FunctionDescriptor> ReadFunctions(ScriptHostConfiguration config, IEnumerable <FunctionDescriptorProvider> descriptorProviders)
        {
            string scriptRootPath             = config.RootScriptPath;
            List <FunctionMetadata> metadatas = new List <FunctionMetadata>();

            foreach (var scriptDir in Directory.EnumerateDirectories(scriptRootPath))
            {
                string functionName = null;

                try
                {
                    // read the function config
                    string functionConfigPath = Path.Combine(scriptDir, FunctionConfigFileName);
                    if (!File.Exists(functionConfigPath))
                    {
                        // not a function directory
                        continue;
                    }

                    functionName = Path.GetFileNameWithoutExtension(scriptDir);

                    if (ScriptConfig.Functions != null &&
                        !ScriptConfig.Functions.Contains(functionName, StringComparer.OrdinalIgnoreCase))
                    {
                        // a functions filter has been specified and the current function is
                        // not in the filter list
                        continue;
                    }

                    // TODO: we need to define a json schema document and do
                    // schema validation
                    string           json           = File.ReadAllText(functionConfigPath);
                    JObject          configMetadata = JObject.Parse(json);
                    FunctionMetadata metadata       = ParseFunctionMetadata(functionName, config.HostConfig.NameResolver, configMetadata);

                    // determine the primary script
                    string[] functionFiles = Directory.EnumerateFiles(scriptDir).Where(p => Path.GetFileName(p).ToLowerInvariant() != FunctionConfigFileName).ToArray();
                    if (functionFiles.Length == 0)
                    {
                        AddFunctionError(functionName, "No function script files present.");
                        continue;
                    }
                    else if (functionFiles.Length == 1)
                    {
                        // if there is only a single file, that file is primary
                        metadata.Source = functionFiles[0];
                    }
                    else
                    {
                        // if there is a "run" file, that file is primary
                        string functionPrimary = null;
                        functionPrimary = functionFiles.FirstOrDefault(p => Path.GetFileNameWithoutExtension(p).ToLowerInvariant() == "run");
                        if (string.IsNullOrEmpty(functionPrimary))
                        {
                            // for Node, any index.js file is primary
                            functionPrimary = functionFiles.FirstOrDefault(p => Path.GetFileName(p).ToLowerInvariant() == "index.js");
                            if (string.IsNullOrEmpty(functionPrimary))
                            {
                                // finally, if there is an explicit primary file indicated
                                // in config, use it
                                JToken token = configMetadata["source"];
                                if (token != null)
                                {
                                    string sourceFileName = (string)token;
                                    functionPrimary = Path.Combine(scriptDir, sourceFileName);
                                }
                            }
                        }

                        if (string.IsNullOrEmpty(functionPrimary))
                        {
                            AddFunctionError(functionName, "Unable to determine primary function script.");
                            continue;
                        }
                        metadata.Source = functionPrimary;
                    }

                    metadata.ScriptType = ParseScriptType(metadata.Source);

                    metadatas.Add(metadata);
                }
                catch (Exception ex)
                {
                    // log any unhandled exceptions and continue
                    AddFunctionError(functionName, ex.Message);
                }
            }

            return(ReadFunctions(metadatas, descriptorProviders));
        }
コード例 #54
0
 public ScriptHostManager(ScriptHostConfiguration config)
     : this(config, ScriptSettingsManager.Instance, new ScriptHostFactory())
 {
 }
コード例 #55
0
        internal static void ApplyConfiguration(JObject config, ScriptHostConfiguration scriptConfig)
        {
            JobHostConfiguration hostConfig = scriptConfig.HostConfig;

            JToken hostId = (JToken)config["id"];
            if (hostId == null)
            {
                throw new InvalidOperationException("An 'id' must be specified in the host configuration.");
            }
            hostConfig.HostId = (string)hostId;

            JToken watchFiles = (JToken)config["watchFiles"];
            if (watchFiles != null && watchFiles.Type == JTokenType.Boolean)
            {
                scriptConfig.FileWatchingEnabled = (bool)watchFiles;
            }

            // Apply Queues configuration
            JObject configSection = (JObject)config["queues"];
            JToken value = null;
            if (configSection != null)
            {
                if (configSection.TryGetValue("maxPollingInterval", out value))
                {
                    hostConfig.Queues.MaxPollingInterval = TimeSpan.FromMilliseconds((int)value);
                }
                if (configSection.TryGetValue("batchSize", out value))
                {
                    hostConfig.Queues.BatchSize = (int)value;
                }
                if (configSection.TryGetValue("maxDequeueCount", out value))
                {
                    hostConfig.Queues.MaxDequeueCount = (int)value;
                }
                if (configSection.TryGetValue("newBatchThreshold", out value))
                {
                    hostConfig.Queues.NewBatchThreshold = (int)value;
                }
            }

            // Apply Singleton configuration
            configSection = (JObject)config["singleton"];
            value = null;
            if (configSection != null)
            {
                if (configSection.TryGetValue("lockPeriod", out value))
                {
                    hostConfig.Singleton.LockPeriod = TimeSpan.Parse((string)value);
                }
                if (configSection.TryGetValue("listenerLockPeriod", out value))
                {
                    hostConfig.Singleton.ListenerLockPeriod = TimeSpan.Parse((string)value);
                }
                if (configSection.TryGetValue("listenerLockRecoveryPollingInterval", out value))
                {
                    hostConfig.Singleton.ListenerLockRecoveryPollingInterval = TimeSpan.Parse((string)value);
                }
                if (configSection.TryGetValue("lockAcquisitionTimeout", out value))
                {
                    hostConfig.Singleton.LockAcquisitionTimeout = TimeSpan.Parse((string)value);
                }
                if (configSection.TryGetValue("lockAcquisitionPollingInterval", out value))
                {
                    hostConfig.Singleton.LockAcquisitionPollingInterval = TimeSpan.Parse((string)value);
                }
            }

            // Apply ServiceBus configuration
            ServiceBusConfiguration sbConfig = new ServiceBusConfiguration();
            configSection = (JObject)config["serviceBus"];
            value = null;
            if (configSection != null)
            {
                if (configSection.TryGetValue("maxConcurrentCalls", out value))
                {
                    sbConfig.MessageOptions.MaxConcurrentCalls = (int)value;
                }
            }
            hostConfig.UseServiceBus(sbConfig);

            // Apply Tracing configuration
            configSection = (JObject)config["tracing"];
            if (configSection != null && configSection.TryGetValue("consoleLevel", out value))
            {
                TraceLevel consoleLevel;
                if (Enum.TryParse<TraceLevel>((string)value, true, out consoleLevel))
                {
                    hostConfig.Tracing.ConsoleLevel = consoleLevel;
                }
            }

            hostConfig.UseTimers();
            hostConfig.UseCore();
        }
コード例 #56
0
        internal static string GetDefaultHostId(ScriptSettingsManager settingsManager, ScriptHostConfiguration scriptConfig)
        {
            // We're setting the default here on the newly created configuration
            // If the user has explicitly set the HostID via host.json, it will overwrite
            // what we set here
            string hostId = null;

            if (scriptConfig.IsSelfHost)
            {
                // When running locally, derive a stable host ID from machine name
                // and root path. We use a hash rather than the path itself to ensure
                // IDs differ (due to truncation) between folders that may share the same
                // root path prefix.
                // Note that such an ID won't work in distributed scenarios, so should
                // only be used for local/CLI scenarios.
                string sanitizedMachineName = Environment.MachineName
                                              .Where(char.IsLetterOrDigit)
                                              .Aggregate(new StringBuilder(), (b, c) => b.Append(c)).ToString();
                hostId = $"{sanitizedMachineName}-{Math.Abs(GetStableHash(scriptConfig.RootScriptPath))}";
            }
            else if (!string.IsNullOrEmpty(settingsManager?.AzureWebsiteUniqueSlotName))
            {
                // If running on Azure Web App, derive the host ID from unique site slot name
                hostId = settingsManager.AzureWebsiteUniqueSlotName;
            }

            if (!string.IsNullOrEmpty(hostId))
            {
                if (hostId.Length > ScriptConstants.MaximumHostIdLength)
                {
                    // Truncate to the max host name length if needed
                    hostId = hostId.Substring(0, ScriptConstants.MaximumHostIdLength);
                }
            }

            // Lowercase and trim any trailing '-' as they can cause problems with queue names
            return(hostId?.ToLowerInvariant().TrimEnd('-'));
        }
コード例 #57
0
        public static ScriptHost Create(ScriptSettingsManager settingsManager = null, ScriptHostConfiguration scriptConfig = null)
        {
            if (scriptConfig == null)
            {
                scriptConfig = new ScriptHostConfiguration();
            }

            _settingsManager = settingsManager;
            if (settingsManager == null)
            {
                _settingsManager = ScriptSettingsManager.Instance;
            }

            if (!Path.IsPathRooted(scriptConfig.RootScriptPath))
            {
                scriptConfig.RootScriptPath = Path.Combine(Environment.CurrentDirectory, scriptConfig.RootScriptPath);
            }

            ScriptHost scriptHost = new ScriptHost(scriptConfig);

            try
            {
                scriptHost.Initialize();
            }
            catch (Exception ex)
            {
                if (scriptHost.TraceWriter != null)
                {
                    scriptHost.TraceWriter.Error("ScriptHost initialization failed", ex);
                }
                throw;
            }

            return(scriptHost);
        }
コード例 #58
0
 public FunctionTraceWriterFactory(ScriptHostConfiguration scriptHostConfig)
 {
     _scriptHostConfig = scriptHostConfig;
 }
コード例 #59
0
        internal static void ApplyConfiguration(JObject config, ScriptHostConfiguration scriptConfig)
        {
            JobHostConfiguration hostConfig = scriptConfig.HostConfig;

            JArray functions = (JArray)config["functions"];

            if (functions != null && functions.Count > 0)
            {
                scriptConfig.Functions = new Collection <string>();
                foreach (var function in functions)
                {
                    scriptConfig.Functions.Add((string)function);
                }
            }

            // We may already have a host id, but the one from the JSON takes precedence
            JToken hostId = (JToken)config["id"];

            if (hostId != null)
            {
                hostConfig.HostId = (string)hostId;
            }
            else if (hostConfig.HostId == null)
            {
                throw new InvalidOperationException("An 'id' must be specified in the host configuration.");
            }

            JToken fileWatchingEnabled = (JToken)config["fileWatchingEnabled"];

            if (fileWatchingEnabled != null && fileWatchingEnabled.Type == JTokenType.Boolean)
            {
                scriptConfig.FileWatchingEnabled = (bool)fileWatchingEnabled;
            }

            // Configure the set of watched directories, adding the standard built in
            // set to any the user may have specified
            if (scriptConfig.WatchDirectories == null)
            {
                scriptConfig.WatchDirectories = new HashSet <string>(StringComparer.OrdinalIgnoreCase);
            }
            scriptConfig.WatchDirectories.Add("node_modules");
            JToken watchDirectories = config["watchDirectories"];

            if (watchDirectories != null && watchDirectories.Type == JTokenType.Array)
            {
                foreach (JToken directory in watchDirectories.Where(p => p.Type == JTokenType.String))
                {
                    scriptConfig.WatchDirectories.Add((string)directory);
                }
            }

            // Apply Singleton configuration
            JObject configSection = (JObject)config["singleton"];
            JToken  value         = null;

            if (configSection != null)
            {
                if (configSection.TryGetValue("lockPeriod", out value))
                {
                    hostConfig.Singleton.LockPeriod = TimeSpan.Parse((string)value, CultureInfo.InvariantCulture);
                }
                if (configSection.TryGetValue("listenerLockPeriod", out value))
                {
                    hostConfig.Singleton.ListenerLockPeriod = TimeSpan.Parse((string)value, CultureInfo.InvariantCulture);
                }
                if (configSection.TryGetValue("listenerLockRecoveryPollingInterval", out value))
                {
                    hostConfig.Singleton.ListenerLockRecoveryPollingInterval = TimeSpan.Parse((string)value, CultureInfo.InvariantCulture);
                }
                if (configSection.TryGetValue("lockAcquisitionTimeout", out value))
                {
                    hostConfig.Singleton.LockAcquisitionTimeout = TimeSpan.Parse((string)value, CultureInfo.InvariantCulture);
                }
                if (configSection.TryGetValue("lockAcquisitionPollingInterval", out value))
                {
                    hostConfig.Singleton.LockAcquisitionPollingInterval = TimeSpan.Parse((string)value, CultureInfo.InvariantCulture);
                }
            }

            // Apply Tracing/Logging configuration
            configSection = (JObject)config["tracing"];
            if (configSection != null)
            {
                if (configSection.TryGetValue("consoleLevel", out value))
                {
                    TraceLevel consoleLevel;
                    if (Enum.TryParse <TraceLevel>((string)value, true, out consoleLevel))
                    {
                        hostConfig.Tracing.ConsoleLevel = consoleLevel;
                    }
                }

                if (configSection.TryGetValue("fileLoggingMode", out value))
                {
                    FileLoggingMode fileLoggingMode;
                    if (Enum.TryParse <FileLoggingMode>((string)value, true, out fileLoggingMode))
                    {
                        scriptConfig.FileLoggingMode = fileLoggingMode;
                    }
                }
            }

            // apply http configuration configuration
            configSection = (JObject)config["http"];
            string routePrefix = ScriptConstants.DefaultHttpRoutePrefix;

            if (configSection != null)
            {
                if (configSection.TryGetValue("routePrefix", out value))
                {
                    routePrefix = (string)value;
                }
            }
            scriptConfig.HttpRoutePrefix = routePrefix;

            if (config.TryGetValue("functionTimeout", out value))
            {
                TimeSpan requestedTimeout = TimeSpan.Parse((string)value, CultureInfo.InvariantCulture);

                // Only apply limits if this is Dynamic.
                if (IsDynamicSku() && (requestedTimeout < MinTimeout || requestedTimeout > MaxTimeout))
                {
                    string message = $"{nameof(scriptConfig.FunctionTimeout)} must be between {MinTimeout} and {MaxTimeout}.";
                    throw new ArgumentException(message);
                }

                scriptConfig.FunctionTimeout = requestedTimeout;
            }
            else if (IsDynamicSku())
            {
                // Apply a default if this is running on Dynamic.
                scriptConfig.FunctionTimeout = MaxTimeout;
            }
        }
コード例 #60
0
 public ScriptHostManager(ScriptHostConfiguration config, IScriptHostFactory scriptHostFactory)
 {
     _config = config;
     _scriptHostFactory = scriptHostFactory;
 }