Skip to content

Commit 47bf889

Browse files
authored
Adding function metadata validation for missing or invalid bindings (#3085)
1 parent 4ff06fd commit 47bf889

File tree

2 files changed

+54
-0
lines changed

2 files changed

+54
-0
lines changed

src/WebJobs.Script/Description/FunctionDescriptorProvider.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ public virtual bool TryCreate(FunctionMetadata functionMetadata, out FunctionDes
4242
// parse the bindings
4343
Collection<FunctionBinding> inputBindings = FunctionBinding.GetBindings(Config, functionMetadata.InputBindings, FileAccess.Read);
4444
Collection<FunctionBinding> outputBindings = FunctionBinding.GetBindings(Config, functionMetadata.OutputBindings, FileAccess.Write);
45+
VerifyResolvedBindings(functionMetadata, inputBindings, outputBindings);
4546

4647
BindingMetadata triggerMetadata = functionMetadata.InputBindings.FirstOrDefault(p => p.IsTrigger);
4748
string scriptFilePath = Path.Combine(Config.RootScriptPath, functionMetadata.ScriptFile ?? string.Empty);
@@ -72,6 +73,20 @@ public virtual bool TryCreate(FunctionMetadata functionMetadata, out FunctionDes
7273
}
7374
}
7475

76+
public void VerifyResolvedBindings(FunctionMetadata functionMetadata, IEnumerable<FunctionBinding> inputBindings, IEnumerable<FunctionBinding> outputBindings)
77+
{
78+
IEnumerable<string> bindingsFromMetadata = functionMetadata.InputBindings.Union(functionMetadata.OutputBindings).Select(f => f.Type);
79+
IEnumerable<string> resolvedBindings = inputBindings.Union(outputBindings).Select(b => b.Metadata.Type);
80+
IEnumerable<string> unresolvedBindings = bindingsFromMetadata.Except(resolvedBindings);
81+
82+
if (unresolvedBindings.Any())
83+
{
84+
string allUnresolvedBindings = string.Join(", ", unresolvedBindings);
85+
throw new ScriptConfigurationException($"The binding type(s) '{allUnresolvedBindings}' are not registered. " +
86+
$"Please ensure the type is correct and the binding extension is installed.");
87+
}
88+
}
89+
7590
protected virtual Collection<ParameterDescriptor> GetFunctionParameters(IFunctionInvoker functionInvoker, FunctionMetadata functionMetadata,
7691
BindingMetadata triggerMetadata, Collection<CustomAttributeBuilder> methodAttributes, Collection<FunctionBinding> inputBindings, Collection<FunctionBinding> outputBindings)
7792
{

test/WebJobs.Script.Tests/Description/FunctionDescriptorProviderTests.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,45 @@ public void ValidateFunction_NoTriggerBinding_Throws()
8080
Assert.Equal("No trigger binding specified. A function must have a trigger input binding.", ex.Message);
8181
}
8282

83+
[Fact]
84+
public void VerifyResolvedBindings_WithNoBindingMatch_ThrowsExpectedException()
85+
{
86+
FunctionMetadata functionMetadata = new FunctionMetadata();
87+
BindingMetadata triggerMetadata = BindingMetadata.Create(JObject.Parse("{\"type\": \"blobTrigger\",\"name\": \"req\",\"direction\": \"in\"}"));
88+
BindingMetadata bindingMetadata = BindingMetadata.Create(JObject.Parse("{\"type\": \"unknownbinding\",\"name\": \"blob\",\"direction\": \"in\"}"));
89+
90+
functionMetadata.Bindings.Add(triggerMetadata);
91+
functionMetadata.Bindings.Add(bindingMetadata);
92+
93+
var ex = Assert.Throws<ScriptConfigurationException>(() =>
94+
{
95+
_provider.TryCreate(functionMetadata, out FunctionDescriptor descriptor);
96+
});
97+
98+
Assert.Contains("unknownbinding", ex.Message);
99+
}
100+
101+
[Fact]
102+
public void VerifyResolvedBindings_WithValidBindingMatch_DoesNotThrow()
103+
{
104+
FunctionMetadata functionMetadata = new FunctionMetadata();
105+
BindingMetadata triggerMetadata = BindingMetadata.Create(JObject.Parse("{\"type\": \"httpTrigger\",\"name\": \"req\",\"direction\": \"in\"}"));
106+
BindingMetadata bindingMetadata = BindingMetadata.Create(JObject.Parse("{\"type\": \"http\",\"name\": \"$return\",\"direction\": \"out\"}"));
107+
108+
functionMetadata.Bindings.Add(triggerMetadata);
109+
functionMetadata.Bindings.Add(bindingMetadata);
110+
try
111+
{
112+
_provider.TryCreate(functionMetadata, out FunctionDescriptor descriptor);
113+
Assert.True(true, "No exception thrown");
114+
}
115+
catch (Exception ex)
116+
{
117+
Assert.True(false, "Exception not expected:" + ex.Message);
118+
throw;
119+
}
120+
}
121+
83122
[Fact]
84123
public void CreateTriggerParameter_WithNoBindingMatch_ThrowsExpectedException()
85124
{

0 commit comments

Comments
 (0)