serverless-azure-functions
serverless-azure-functions copied to clipboard
Incorrect Service Bus Out binding
This is a Bug Report
Description
- What went wrong?
- A default queueName is added to the function.json along with the specified topicName
- What did you expect should have happened?
- The queueName should not be included in the function.json
- What was the config you used?
save-condition:
handler: src/handlers/save-condition.handler
name: save-condition
events:
- http: true
x-azure-settings:
methods:
- POST
authLevel: anonymous
route: conditions
- serviceBus:
x-azure-settings:
direction: out
name: conditionsTopic
topicName: condition-saved
connection: ServiceBusConnection
- What stacktrace or error message from your provider did you see?
- function.json
{
"disabled": false,
"bindings": [
{
"type": "httpTrigger",
"direction": "in",
"name": "req",
"route": "conditions",
"authLevel": "anonymous",
"methods": [
"POST"
]
},
{
"type": "serviceBus",
"direction": "out",
"name": "conditionsTopic",
"queueName": "outqueue",
"topicName": "condition-saved",
"connection": "ServiceBusConnection",
"accessRights_": "Manage"
}
],
"entryPoint": "handler",
"scriptFile": "..\\src\\handlers\\save-condition.js"
}
Microsoft.Azure.ServiceBus: Put token failebus.windows.net:outqueue, Timestamp:2019-09-30T16:35:11.ed. status-code: 404, status-description: The messaging entity 'sb://service-bus-name-here.servicebus.windows.net/outqueue' could not be found
Similar or dependent issues:
- #57
Additional Data
- Serverless Framework Version you're using:
- 1.53.0
- Serverless CLI Version you're using:
- 1.2.3
- Serverless Azure Plugin Version you're using:
- 1.0.2-4
- Operating System:
- Windows 10
- Stack Trace:
- Provider Error messages:
Could you tell me what is the current status of this bug and when do you plan to fix this?
According to the Azure Servicebus output binding docs you can provide either queueName or topicName in function.json. If both of them are provided, then queue has bigger priority. That makes sending messages through out binding impossible for topic out binding. The only workaround that I have found so far is to create a queue that will forward those messages to topic but it seems to be too excessive.
I've taken a quick look into the source code and it seems that the problem lies in the missing ValidateIf logic for serviceBus out binding(required value is either queueName or topicName+ subscription). Also a quick fix might be probably done by changing true required flag in queueName and topicName for serviceBus in bindings.json. I am not sure why in the serviceBusTrigger those two values are false but as a consequence it may result in not having those values function.json unless they are provided in serverless.yml.
Nonetheless this issue is pretty serious and IMO should be fixed any time soon.
I have the same issue. There is a workaround or fix?
Hello, I have a workaround, I created a plugin with the following code:
'use strict';
const path = require('path');
const fs = require('fs');
class ServerlessPlugin {
constructor(serverless, options) {
this.serverless = serverless;
this.options = options;
this.hooks = {
'after:package:setupProviderConfiguration': this.bindingCleanup.bind(this),
'before:deploy:function:packageFunction': this.bindingCleanup.bind(this),
'before:deploy:deploy': this.bindingCleanup.bind(this),
'after:offline:build': this.bindingCleanup.bind(this),
};
}
bindingCleanup() {
this.serverless.cli.log('Hello from ServiceBus Binding Cleanup!');
const parsedFunctions = this.serverless.service.getAllFunctions();
parsedFunctions.forEach((parseFunction) => {
this.serverless.cli.log('checking binding in -> ' + parseFunction);
this.serverless.cli.log(this.serverless.config.servicePath);
const functionJSON = JSON.parse(fs.readFileSync(path.join(this.serverless.config.servicePath, parseFunction,'function.json')).toString());
const bindings = functionJSON.bindings;
let update = false;
bindings.forEach((binding, index) => {
if (binding.queueName === false) {
this.serverless.cli.log(' Found serviceBus with default queueName, updating ...');
delete binding.queueName;
functionJSON.bindings[index] = binding;
update = true;
}
});
if (update) {
this.serverless.cli.log(' ... updated to ' + JSON.stringify(functionJSON));
fs.writeFileSync(path.join(this.serverless.config.servicePath, parseFunction,'function.json'), JSON.stringify(functionJSON, null, 4));
}
});
this.serverless.cli.log('All cleanup done, please check the binding in function.json!');
}
}
module.exports = ServerlessPlugin;
With this, you only need to put queueName: false in your serverless.yml function