Skip to content
This repository has been archived by the owner on Feb 17, 2023. It is now read-only.

Commit

Permalink
Merge 443ea8b into 735a3a1
Browse files Browse the repository at this point in the history
  • Loading branch information
enigmatic00 committed Jun 20, 2016
2 parents 735a3a1 + 443ea8b commit 28ee9a0
Show file tree
Hide file tree
Showing 10 changed files with 881 additions and 20 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,5 @@ jspm_packages

# Optional REPL history
.node_repl_history

local.js
8 changes: 8 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
language: node_js
sudo: required
addons:
hosts:
- rabbit
services:
- rabbitmq
env:
- NODE_CONFIG_DIR='./test/integration/config'
node_js:
- "6"
- "6.1"
Expand Down
100 changes: 100 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,102 @@
[![Build Status](https://travis-ci.org/GannettDigital/fudd.svg?branch=master)](https://travis-ci.org/GannettDigital/fudd)
[![Coverage Status](https://coveralls.io/repos/github/GannettDigital/fudd/badge.svg?branch=master)](https://coveralls.io/github/GannettDigital/fudd?branch=master)

# fudd
simple rabbit mq infrastructure setup/teardown utility

## Installation
```
npm install fudd
```

## Test

```
npm run test
```
This will run both unit tests & integration tests. To successfully run integration tests, you must have a rabbitmq instance
available & configured. See Configuration for examples

## Coverage

```
npm run cover-html
```

## Usage

```
var fudd = require('fudd');
fudd.setup(config, function(err){
if(err) throw err;
// do your thing with rabbitmq
});
fudd.teardown(config, function(err){
if(err) throw err;
// all things torn
});
```

## Configuration

Configuration should look like the following:
```javascript
{
cluster: {
port: 5672,
vhost: '/',
login: 'guest',
heartbeat: 10,
password: 'guest',
host: 'rabbit'
},
exchanges: [
{
name: 'fanout.fx',
type: 'fanout',
options: {}
},
{
name: 'topic.tx',
type: 'topic',
options: {}
}
],
queues: [
{
name: 'queue1',
options: {durable: true}
},
{
name: 'queue2',
options: {durable: false}
}
],

bindings: [
{
bindingType: 'queue',
from: 'fanout.fx',
to: 'queue1',
bindingKeys: ['#']
},
{
bindingType: 'exchange',
from: 'fanout.fx',
to: 'topic.tx',
bindingKeys: ['#'],
options: {}
},
{
bindingType: 'queue',
from: 'topic.tx',
to: 'queue2',
bindingKeys: ['#.topic1', '#.topic2']
}
]
}
```
1 change: 1 addition & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('./lib/fudd.js');
15 changes: 15 additions & 0 deletions lib/amqp-config-utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
'use strict';

var format = require('util').format;

module.exports = function formatAmqpUrl(urlComponents) {
return format(
'amqp://%s:%s@%s:%s/%s?heartbeat=%s',
urlComponents.login,
urlComponents.password,
urlComponents.host,
urlComponents.port,
encodeURIComponent(urlComponents.vhost),
urlComponents.heartbeat
);
};
106 changes: 97 additions & 9 deletions lib/fudd.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,107 @@
'use strict';
var amqp = require('amqplib/callback_api');
var formatAmqpUrl = require('./amqp-config-utils.js');
var series = require('palinode').series;
var mapEach = require('palinode').mapEach;

function Fudd() {
var Fudd = {
setup: function(config, finalCallback) {

}
var establishChannel = [Fudd._connect.bind(null, config), Fudd._createChannel];

Fudd.prototype.init = function(config) {
return true;
};
series(establishChannel, function(error, connection, channel) {
if (error) return finalCallback(error);
var infrastructure = [];

Fudd.prototype.setup = function() {
config.exchanges.reduce(function(series, exchangeDefinition) {
series.push(Fudd._createExchange.bind(null, channel, exchangeDefinition));
return series;
}, infrastructure);

};
config.queues.reduce(function(series, queueDefinition) {
series.push(Fudd._createQueue.bind(null, channel, queueDefinition));
return series;
}, infrastructure);

config.bindings.reduce(function(series, bindingDefinition) {
series.push(Fudd._createBindings.bind(null, channel, bindingDefinition));
return series;
}, infrastructure);

series(infrastructure, function(error) {
if (error) return finalCallback(error);
Fudd._disconnect(connection, finalCallback);
});
});
},
teardown: function(config, finalCallback) {
var establishChannel = [Fudd._connect.bind(null, config), Fudd._createChannel];

series(establishChannel, function(error, connection, channel) {
if (error) return finalCallback(error);
var infrastructure = [];

config.exchanges.reduce(function(series, exchangeDefinition) {
infrastructure.push(Fudd._deleteExchange.bind(null, channel, exchangeDefinition));
}, infrastructure);

config.queues.reduce(function(series, queueDefinition) {
series.push(Fudd._deleteQueue.bind(null, channel, queueDefinition));
return series;
}, infrastructure);

series(infrastructure, function(error) {
if (error) return finalCallback(error);
Fudd._disconnect(connection, finalCallback);
});
});
},
_createExchange: function(channel, exchangeDefinition, callback) {
channel.assertExchange(exchangeDefinition.name, exchangeDefinition.type, exchangeDefinition.options, function(err) {
callback(err);
});
},
_createQueue: function(channel, queueDefinition, callback) {
channel.assertQueue(queueDefinition.name, queueDefinition.options, function(err) {
callback(err);
});
},
_createBindings: function(channel, bindingDefinition, callback) {
var boundCreateBinding = Fudd._createBinding.bind(null, channel, bindingDefinition);
mapEach(bindingDefinition.bindingKeys, boundCreateBinding, function(error) {
callback(error);
});
},
_createBinding: function(channel, bindingDefinition, bindingKey, callback) {
if (bindingDefinition.bindingType === 'queue') {
channel.bindQueue(bindingDefinition.to, bindingDefinition.from, bindingKey, bindingDefinition.options, callback);

Fudd.prototype.tearDown = function() {
} else if (bindingDefinition.bindingType === 'exchange') {
channel.bindExchange(bindingDefinition.to, bindingDefinition.from, bindingKey, bindingDefinition.options, callback);

} else {
callback(new Error('unsupported binding type: ' + bindingDefinition.bindingType));
}
},
_deleteExchange: function(channel, exchangeDefinition, callback) {
channel.deleteExchange(exchangeDefinition.name, {}, function(error) { callback(error);});
},
_deleteQueue: function(channel, queueDefinition, callback) {
channel.deleteQueue(queueDefinition.name, {}, function(error) { callback(error);});
},
_connect: function(config, callback) {
var url = formatAmqpUrl(config.cluster);
amqp.connect(url, callback);
},
_createChannel: function(connection, callback) {
connection.createChannel(function(error, channel) {
if (error) return callback(error);
callback(null, connection, channel);
});
},
_disconnect: function(connection, callback) {
connection.close(callback);
}
};

module.exports = Fudd;
module.exports = Object.create(Fudd);
10 changes: 7 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,22 @@
"homepage": "https://github.com/GannettDigital/fudd#readme",
"devDependencies": {
"chai": "3.5.0",
"config": "^1.21.0",
"coveralls": "2.11.9",
"istanbul": "0.4.3",
"jscs": "^3.0.4",
"mocha": "2.5.3",
"mockery": "1.7.0"
"mockery": "1.7.0",
"sinon": "1.17.4"
},
"dependencies": {
"amqplib": "0.4.2"
"amqplib": "0.4.2",
"palinode": "0.0.3"
},
"scripts": {
"test": "mocha --recursive test/unit",
"test": "mocha --recursive test/unit --recursive test/integration",
"lint": "./node_modules/.bin/jscs ./lib/ ./test",
"fix-lint": "npm run lint -- -x",
"cover": "node ./node_modules/.bin/istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec test/unit --recursive",
"coveralls": "npm run cover && ./node_modules/coveralls/bin/coveralls.js < coverage/lcov.info"
}
Expand Down
55 changes: 55 additions & 0 deletions test/integration/config/default.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
'use strict';
module.exports = {
cluster: {
port: 5672,
vhost: '/',
login: 'guest',
heartbeat: 10,
password: 'guest',
host: 'rabbit'
},
exchanges: [
{
name: 'fanout.fx',
type: 'fanout',
options: {}
},
{
name: 'topic.tx',
type: 'topic',
options: {}
}
],
queues: [
{
name: 'queue1',
options: {durable: true}
},
{
name: 'queue2',
options: {durable: false}
}
],

bindings: [
{
bindingType: 'queue',
from: 'fanout.fx',
to: 'queue1',
bindingKeys: ['#']
},
{
bindingType: 'exchange',
from: 'fanout.fx',
to: 'topic.tx',
bindingKeys: ['#'],
options: {}
},
{
bindingType: 'queue',
from: 'topic.tx',
to: 'queue2',
bindingKeys: ['#.topic1', '#.topic2']
}
]
};

0 comments on commit 28ee9a0

Please sign in to comment.