private static bool TryParseFunctionBinding(ScriptHostConfiguration config, Newtonsoft.Json.Linq.JObject metadata, out FunctionBinding functionBinding) { functionBinding = null; ScriptBindingContext bindingContext = new ScriptBindingContext(metadata); ScriptBinding scriptBinding = null; foreach (var provider in config.BindingProviders) { if (provider.TryCreate(bindingContext, out scriptBinding)) { break; } } if (scriptBinding == null) { return(false); } BindingMetadata bindingMetadata = BindingMetadata.Create(metadata); functionBinding = new ExtensionBinding(config, scriptBinding, bindingMetadata); return(true); }
public static FunctionMetadata GetSampleMetadata(string functionName) { Func <HttpRequest, ILogger, Task <IActionResult> > invokeFunction = MyFunction; string endToendAssemblySuffix = "WebHostEndToEnd"; var functionMetadata = new FunctionMetadata { Name = functionName, FunctionDirectory = null, ScriptFile = $"assembly:{Assembly.GetExecutingAssembly().FullName}", EntryPoint = $"{Assembly.GetExecutingAssembly().GetName().Name}.{endToendAssemblySuffix}.{typeof(CodelessEndToEndTests_Data).Name}.{invokeFunction.Method.Name}", Language = "DotNetAssembly" }; JObject functionConfig = JObject.Parse(_sampleBindingsJson); JArray bindingArray = (JArray)functionConfig["bindings"]; foreach (JObject binding in bindingArray) { BindingMetadata bindingMetadata = BindingMetadata.Create(binding); functionMetadata.Bindings.Add(bindingMetadata); } return(functionMetadata); }
public void GenerateServiceBusTriggerFunction() { BindingMetadata trigger = BindingMetadata.Create(new JObject { { "type", "ServiceBusTrigger" }, { "name", "input" }, { "direction", "in" }, { "topicName", "testTopic" }, { "subscriptionName", "testSubscription" }, { "accessRights", "Listen" } }); MethodInfo method = GenerateMethod(trigger); VerifyCommonProperties(method); // verify trigger parameter ParameterInfo parameter = method.GetParameters()[0]; Assert.Equal("input", parameter.Name); Assert.Equal(typeof(string), parameter.ParameterType); ServiceBusTriggerAttribute attribute = parameter.GetCustomAttribute <ServiceBusTriggerAttribute>(); Assert.Equal(null, attribute.QueueName); Assert.Equal("testTopic", attribute.TopicName); Assert.Equal("testSubscription", attribute.SubscriptionName); Assert.Equal(AccessRights.Listen, attribute.Access); }
private static bool TryParseFunctionBinding(ScriptJobHostOptions config, IEnumerable <IScriptBindingProvider> bindingProviders, JObject metadata, out FunctionBinding functionBinding) { functionBinding = null; ScriptBindingContext bindingContext = new ScriptBindingContext(metadata); ScriptBinding scriptBinding = null; foreach (var provider in bindingProviders) { if (provider.TryCreate(bindingContext, out scriptBinding)) { break; } } if (scriptBinding == null) { return(false); } BindingMetadata bindingMetadata = BindingMetadata.Create(metadata); functionBinding = new ExtensionBinding(config, scriptBinding, bindingMetadata); return(true); }
public async Task ToFunctionTrigger_Codeless_ReturnsExpected() { var functionMetadata = new FunctionMetadata { Name = "TestFunction1" }; var options = new ScriptJobHostOptions { RootScriptPath = _testRootScriptPath }; functionMetadata.SetIsCodeless(true); JObject functionConfig = JObject.Parse(_sampleBindingsJson); JArray bindingArray = (JArray)functionConfig["bindings"]; foreach (JObject binding in bindingArray) { BindingMetadata bindingMetadata = BindingMetadata.Create(binding); functionMetadata.Bindings.Add(bindingMetadata); } var result = await functionMetadata.ToFunctionTrigger(options); Assert.Equal("TestFunction1", result["functionName"].Value <string>()); Assert.Equal("httpTrigger", result["type"].Value <string>()); // make sure original binding did not change Assert.Null(functionMetadata.Bindings[0].Raw["functionName"]?.Value <string>()); Assert.Equal("httpTrigger", functionMetadata.Bindings[0].Raw["type"].Value <string>()); }
private static (Collection <FunctionMetadata>, ProxyClientExecutor) LoadProxyMetadata(string proxiesJson, Dictionary <string, ICollection <string> > functionErrors, ILogger logger) { var proxies = new Collection <FunctionMetadata>(); ProxyClientExecutor client = null; var rawProxyClient = ProxyClientFactory.Create(proxiesJson, logger); if (rawProxyClient != null) { client = new ProxyClientExecutor(rawProxyClient); } if (client == null) { return(proxies, null); } var routes = client.GetProxyData(); foreach (var route in routes.Routes) { try { // Proxy names should follow the same naming restrictions as in function names. If not, invalid characters will be removed. var proxyName = NormalizeProxyName(route.Name); var proxyMetadata = new FunctionMetadata(); var json = new JObject { { "authLevel", "anonymous" }, { "name", "req" }, { "type", "httptrigger" }, { "direction", "in" }, { "Route", route.UrlTemplate.TrimStart('/') }, { "Methods", new JArray(route.Methods.Select(m => m.Method.ToString()).ToArray()) } }; BindingMetadata bindingMetadata = BindingMetadata.Create(json); proxyMetadata.Bindings.Add(bindingMetadata); proxyMetadata.Name = proxyName; proxyMetadata.IsProxy = true; proxies.Add(proxyMetadata); } catch (Exception ex) { // log any unhandled exceptions and continue Utility.AddFunctionError(functionErrors, route.Name, Utility.FlattenException(ex, includeSource: false), isFunctionShortName: true); } } return(proxies, client); }
private void AddSampleBindings(FunctionMetadata functionMetadata) { JObject functionConfig = JObject.Parse(_sampleBindingsJson); JArray bindingArray = (JArray)functionConfig["bindings"]; foreach (JObject binding in bindingArray) { BindingMetadata bindingMetadata = BindingMetadata.Create(binding); functionMetadata.Bindings.Add(bindingMetadata); } }
public static FunctionBinding CreateTestBinding(JObject json) { ScriptBindingContext context = new ScriptBindingContext(json); WebJobsCoreScriptBindingProvider provider = new WebJobsCoreScriptBindingProvider(new JobHostConfiguration(), new JObject(), null); ScriptBinding scriptBinding = null; provider.TryCreate(context, out scriptBinding); BindingMetadata bindingMetadata = BindingMetadata.Create(json); ScriptHostConfiguration config = new ScriptHostConfiguration(); return(new ExtensionBinding(config, scriptBinding, bindingMetadata)); }
public static FunctionBinding CreateTestBinding(JObject json) { ScriptBindingContext context = new ScriptBindingContext(json); WebJobsCoreScriptBindingProvider provider = new WebJobsCoreScriptBindingProvider(NullLogger <WebJobsCoreScriptBindingProvider> .Instance); ScriptBinding scriptBinding = null; provider.TryCreate(context, out scriptBinding); BindingMetadata bindingMetadata = BindingMetadata.Create(json); var config = new ScriptJobHostOptions(); return(new ExtensionBinding(config, scriptBinding, bindingMetadata)); }
private FunctionMetadata ParseFunctionMetadata(string functionName, JObject configMetadata, string scriptDirectory, IFileSystem fileSystem, IEnumerable <RpcWorkerConfig> workerConfigs) { var functionMetadata = new FunctionMetadata { Name = functionName, FunctionDirectory = scriptDirectory }; JArray bindingArray = (JArray)configMetadata["bindings"]; if (bindingArray == null || bindingArray.Count == 0) { throw new FormatException("At least one binding must be declared."); } if (bindingArray != null) { foreach (JObject binding in bindingArray) { BindingMetadata bindingMetadata = BindingMetadata.Create(binding); functionMetadata.Bindings.Add(bindingMetadata); } } JToken isDirect; if (configMetadata.TryGetValue("configurationSource", StringComparison.OrdinalIgnoreCase, out isDirect)) { var isDirectValue = isDirect.ToString(); if (string.Equals(isDirectValue, "attributes", StringComparison.OrdinalIgnoreCase)) { functionMetadata.SetIsDirect(true); } else if (!string.Equals(isDirectValue, "config", StringComparison.OrdinalIgnoreCase)) { throw new FormatException($"Illegal value '{isDirectValue}' for 'configurationSource' property in {functionMetadata.Name}'."); } } functionMetadata.ScriptFile = DeterminePrimaryScriptFile((string)configMetadata["scriptFile"], scriptDirectory, fileSystem); if (!string.IsNullOrWhiteSpace(functionMetadata.ScriptFile)) { functionMetadata.Language = ParseLanguage(functionMetadata.ScriptFile, workerConfigs); } functionMetadata.EntryPoint = (string)configMetadata["entryPoint"]; //Retry functionMetadata.Retry = configMetadata.Property(ConfigurationSectionNames.Retry)?.Value?.ToObject <RetryOptions>(); Utility.ValidateRetryOptions(functionMetadata.Retry); return(functionMetadata); }
public void CreateTriggerParameter_WithNoBindingMatch_ThrowsExpectedException() { FunctionMetadata functionMetadata = new FunctionMetadata(); BindingMetadata metadata = BindingMetadata.Create(JObject.Parse("{\"type\": \"someInvalidTrigger\",\"name\": \"req\",\"direction\": \"in\"}")); functionMetadata.Bindings.Add(metadata); var ex = Assert.Throws <FunctionConfigurationException>(() => { _provider.TryCreate(functionMetadata, out FunctionDescriptor descriptor); }); Assert.Contains("someInvalidTrigger", ex.Message); }
public async Task VerifyResolvedBindings_WithNoBindingMatch_ThrowsExpectedException() { FunctionMetadata functionMetadata = new FunctionMetadata(); BindingMetadata triggerMetadata = BindingMetadata.Create(JObject.Parse("{\"type\": \"blobTrigger\",\"name\": \"req\",\"direction\": \"in\", \"blobPath\": \"test\"}")); BindingMetadata bindingMetadata = BindingMetadata.Create(JObject.Parse("{\"type\": \"unknownbinding\",\"name\": \"blob\",\"direction\": \"in\"}")); functionMetadata.Bindings.Add(triggerMetadata); functionMetadata.Bindings.Add(bindingMetadata); var ex = await Assert.ThrowsAsync <FunctionConfigurationException>(async() => { var(created, descriptor) = await _provider.TryCreate(functionMetadata); }); Assert.Contains("The binding type(s) 'unknownbinding' are not registered", ex.Message); }
public void VerifyResolvedBindings_WithNoBindingMatch_ThrowsExpectedException() { FunctionMetadata functionMetadata = new FunctionMetadata(); BindingMetadata triggerMetadata = BindingMetadata.Create(JObject.Parse("{\"type\": \"blobTrigger\",\"name\": \"req\",\"direction\": \"in\", \"blobPath\": \"test\"}")); BindingMetadata bindingMetadata = BindingMetadata.Create(JObject.Parse("{\"type\": \"unknownbinding\",\"name\": \"blob\",\"direction\": \"in\"}")); functionMetadata.Bindings.Add(triggerMetadata); functionMetadata.Bindings.Add(bindingMetadata); var ex = Assert.Throws <FunctionConfigurationException>(() => { _provider.TryCreate(functionMetadata, out FunctionDescriptor descriptor); }); Assert.Contains("unknownbinding", ex.Message); }
public void GenerateTimerTriggerFunction() { BindingMetadata trigger = BindingMetadata.Create(new JObject { { "type", "TimerTrigger" }, { "name", "timerInfo" }, { "schedule", "* * * * * *" }, { "runOnStartup", true }, { "direction", "in" } }); MethodInfo method = GenerateMethod(trigger); VerifyCommonProperties(method); // verify trigger parameter ParameterInfo parameter = method.GetParameters()[0]; Assert.Equal("timerInfo", parameter.Name); Assert.Equal(typeof(TimerInfo), parameter.ParameterType); TimerTriggerAttribute attribute = parameter.GetCustomAttribute <TimerTriggerAttribute>(); Assert.Equal("* * * * * *", attribute.ScheduleExpression); Assert.True(attribute.UseMonitor); Assert.True(attribute.RunOnStartup); trigger = BindingMetadata.Create(new JObject { { "type", "TimerTrigger" }, { "name", "timerInfo" }, { "schedule", "* * * * * *" }, { "useMonitor", false }, { "direction", "in" } }); method = GenerateMethod(trigger); VerifyCommonProperties(method); // verify trigger parameter parameter = method.GetParameters()[0]; Assert.Equal("timerInfo", parameter.Name); Assert.Equal(typeof(TimerInfo), parameter.ParameterType); attribute = parameter.GetCustomAttribute <TimerTriggerAttribute>(); Assert.Equal("* * * * * *", attribute.ScheduleExpression); Assert.False(attribute.UseMonitor); Assert.False(attribute.RunOnStartup); }
private static FunctionMetadata ParseFunctionMetadata(string functionName, JObject configMetadata) { FunctionMetadata functionMetadata = new FunctionMetadata { Name = functionName }; JValue triggerDisabledValue = null; JArray bindingArray = (JArray)configMetadata["bindings"]; if (bindingArray == null || bindingArray.Count == 0) { throw new FormatException("At least one binding must be declared."); } if (bindingArray != null) { foreach (JObject binding in bindingArray) { BindingMetadata bindingMetadata = BindingMetadata.Create(binding); functionMetadata.Bindings.Add(bindingMetadata); if (bindingMetadata.IsTrigger) { triggerDisabledValue = (JValue)binding["disabled"]; } } } // A function can be disabled at the trigger or function level if (IsDisabled(triggerDisabledValue) || IsDisabled((JValue)configMetadata["disabled"])) { functionMetadata.IsDisabled = true; } JToken value = null; if (configMetadata.TryGetValue("excluded", StringComparison.OrdinalIgnoreCase, out value) && value.Type == JTokenType.Boolean) { functionMetadata.IsExcluded = (bool)value; } return(functionMetadata); }
public static FunctionBinding CreateBindingFromHost(IHost host, JObject json) { var bindingProviders = host.Services.GetServices <IScriptBindingProvider>(); var context = new ScriptBindingContext(json); ScriptBinding scriptBinding = null; bindingProviders.FirstOrDefault(p => p.TryCreate(context, out scriptBinding)); if (scriptBinding != null) { BindingMetadata bindingMetadata = BindingMetadata.Create(json); var config = new ScriptJobHostOptions(); return(new ExtensionBinding(config, scriptBinding, bindingMetadata)); } return(null); }
public virtual async Task <ImmutableArray <FunctionMetadata> > ReadMetadataAsync() { string metadataFile = Path.Combine(_options.Value.FunctionMetadataFileDrectory, _fileName); if (File.Exists(metadataFile)) { using (var fs = File.OpenText(metadataFile)) { using (var js = new JsonTextReader(fs)) { JArray functionMetadataJson = (JArray)await JToken.ReadFromAsync(js); var functionList = new List <FunctionMetadata>(); foreach (JObject function in functionMetadataJson) { FunctionMetadata metadata = function.ToObject <FunctionMetadata>(); // We need to re-add these by going through the BindingMetadata factory metadata.Bindings.Clear(); JArray bindingArray = (JArray)function["bindings"]; if (bindingArray == null || bindingArray.Count == 0) { throw new FormatException("At least one binding must be declared."); } foreach (JObject binding in bindingArray) { metadata.Bindings.Add(BindingMetadata.Create(binding)); } functionList.Add(metadata); } return(functionList.ToImmutableArray()); } } } else { return(ImmutableArray <FunctionMetadata> .Empty); } }
public void VerifyResolvedBindings_WithValidBindingMatch_DoesNotThrow() { FunctionMetadata functionMetadata = new FunctionMetadata(); BindingMetadata triggerMetadata = BindingMetadata.Create(JObject.Parse("{\"type\": \"httpTrigger\",\"name\": \"req\",\"direction\": \"in\"}")); BindingMetadata bindingMetadata = BindingMetadata.Create(JObject.Parse("{\"type\": \"http\",\"name\": \"$return\",\"direction\": \"out\"}")); functionMetadata.Bindings.Add(triggerMetadata); functionMetadata.Bindings.Add(bindingMetadata); try { _provider.TryCreate(functionMetadata, out FunctionDescriptor descriptor); Assert.True(true, "No exception thrown"); } catch (Exception ex) { Assert.True(false, "Exception not expected:" + ex.Message); throw; } }
private FunctionMetadata GetFunctionMetadata(string functionName) { var assembly = Assembly.GetExecutingAssembly(); var functionMetadata = new FunctionMetadata() { Name = functionName, FunctionDirectory = null, ScriptFile = $"assembly:{assembly.FullName}", EntryPoint = $"{assembly.GetName().Name}.{typeof(OpenApiTriggerFunctionProvider).Name}.{functionName}", Language = "DotNetAssembly" }; var jo = JObject.FromObject(this._bindings[functionName]); var binding = BindingMetadata.Create(jo); functionMetadata.Bindings.Add(binding); return(functionMetadata); }
public void GenerateHttpTriggerFunction() { BindingMetadata trigger = BindingMetadata.Create(new JObject { { "type", "HttpTrigger" }, { "name", "req" } }); MethodInfo method = GenerateMethod(trigger); VerifyCommonProperties(method); // verify trigger parameter ParameterInfo parameter = method.GetParameters()[0]; Assert.Equal("req", parameter.Name); Assert.Equal(typeof(HttpRequestMessage), parameter.ParameterType); NoAutomaticTriggerAttribute attribute = method.GetCustomAttribute <NoAutomaticTriggerAttribute>(); Assert.NotNull(attribute); }
public FunctionInvokerBaseTests() { _metricsLogger = new TestMetricsLogger(); _testLoggerProvider = new TestLoggerProvider(); ILoggerFactory loggerFactory = new LoggerFactory(); loggerFactory.AddProvider(_testLoggerProvider); var eventManager = new ScriptEventManager(); var metadata = new FunctionMetadata { Name = "TestFunction", ScriptFile = "index.js", Language = "node" }; JObject binding = JObject.FromObject(new { type = "manualTrigger", name = "manual", direction = "in" }); metadata.Bindings.Add(BindingMetadata.Create(binding)); var metadataManager = new MockMetadataManager(new[] { metadata }); _host = new HostBuilder() .ConfigureDefaultTestWebScriptHost() .ConfigureServices(s => { s.AddSingleton <IFunctionMetadataManager>(metadataManager); }) .Build(); _scriptHost = _host.GetScriptHost(); _scriptHost.InitializeAsync().Wait(); _invoker = new MockInvoker(_scriptHost, _metricsLogger, metadataManager, metadata, loggerFactory); }
internal static FunctionMetadata ValidateBindings(IEnumerable <string> rawBindings, FunctionMetadata function) { HashSet <string> bindingNames = new HashSet <string>(StringComparer.OrdinalIgnoreCase); foreach (string binding in rawBindings) { var functionBinding = BindingMetadata.Create(JObject.Parse(binding)); Utility.ValidateBinding(functionBinding); // Ensure no duplicate binding names exist if (bindingNames.Contains(functionBinding.Name)) { throw new InvalidOperationException(string.Format("Multiple bindings with name '{0}' discovered. Binding names must be unique.", functionBinding.Name)); } else { bindingNames.Add(functionBinding.Name); } // add binding to function.Bindings once validation is complete function.Bindings.Add(functionBinding); } // ensure there is at least one binding after validation if (function.Bindings == null || function.Bindings.Count == 0) { throw new FormatException("At least one binding must be declared."); } // ensure that there is a trigger binding var triggerMetadata = function.InputBindings.FirstOrDefault(p => p.IsTrigger); if (triggerMetadata == null) { throw new InvalidOperationException("No trigger binding specified. A function must have a trigger input binding."); } return(function); }
public void GenerateBlobTriggerFunction() { BindingMetadata trigger = BindingMetadata.Create(new JObject { { "type", "blobTrigger" }, { "name", "input" }, { "direction", "in" }, { "path", "foo/bar" } }); MethodInfo method = GenerateMethod(trigger); VerifyCommonProperties(method); // verify trigger parameter ParameterInfo parameter = method.GetParameters()[0]; Assert.Equal("input", parameter.Name); Assert.Equal(typeof(Stream), parameter.ParameterType); BlobTriggerAttribute attribute = parameter.GetCustomAttribute <BlobTriggerAttribute>(); Assert.Equal("foo/bar", attribute.BlobPath); }
public void GenerateQueueTriggerFunction() { BindingMetadata trigger = BindingMetadata.Create(new JObject { { "type", "QueueTrigger" }, { "name", "input" }, { "direction", "in" }, { "queueName", "test" } }); MethodInfo method = GenerateMethod(trigger); VerifyCommonProperties(method); // verify trigger parameter ParameterInfo parameter = method.GetParameters()[0]; Assert.Equal("input", parameter.Name); Assert.Equal(typeof(string), parameter.ParameterType); QueueTriggerAttribute attribute = parameter.GetCustomAttribute <QueueTriggerAttribute>(); Assert.Equal("test", attribute.QueueName); }