Connector API
The Connector API is a Ruby gem you use to create custom connectors for the Factor.io Connector. Connectors like like Github, Heroku, Rackspace, and Hipchat were built using this gem. This readme will help you create a custom connector.
Building a custom Connector
Each Connector ships as a Ruby Gem which gets included in the Connector app to host the integration. Each of these gems can contain one or more services to integrate. For example, Rackspace has numerous files in /lib/factor/connector.
Base
For the sake of example we'll call this service "myservice". Start by creating a new repo in Github. You can call it factor-connector-myservice
. Next, we need to have at least these three files.
factor-connector-myservice.gemspec
This integration to "myservice" is going to be bundled as a Ruby gem, and therefore we need a .gemspec
file.
# encoding: UTF-8
$LOAD_PATH.push File.expand_path('../lib', __FILE__)
Gem::Specification.new do |s|
s.name = 'factor-connector-myservice'
s.version = '0.0.3'
s.platform = Gem::Platform::RUBY
s.authors = ['Maciej Skierkowski']
s.email = ['maciej@factor.io']
s.homepage = 'https://factor.io'
s.summary = 'My Service Factor.io Connector'
s.files = Dir.glob('lib/factor/connector/*.rb')
s.require_paths = ['lib']
s.add_runtime_dependency 'factor-connector-api', '~> 0.0.3'
s.add_runtime_dependency 'fog', '~> 1.23.0'
end
One of the most important lines is s.add_runtime_dependency 'factor-connector-api', '~> 0.0.3'
as it ensures that the Connector API is loaded. Other than that, include any other gems your app may need.
Gemfile
Since we are delivering this as a Gem all the dependencies are defined in our gemspec file.
source "https://rubygems.org"
gemspec
lib/factor/connector/myservice.rb
require 'factor-connector-api'
Factor::Connector.service 'myservice' do
action 'hello' do
name = params['name']
fail 'Name (name) is required' unless name
fail 'Name (name) must be a string' unless name.is_a?(String)
info "Sending response to #{name}"
action_callback hello_world:name
end
listener 'sometimes' do
start do |params|
info "Going to randomly start every 0-60 seconds"
do
sleep rand 60
start_workflow time: Time.now.to_s
while true
end
stop do |params|
info "Stopping. KTHXBYE"
end
end
end
Building, Push, and Use
The above example is fully functional. You can build and push the gem like so.
gem build factor-connector-myservice.gemspec
gem push factor-connector-myservice-0.0.1.gem
To use this gem you need to go into your Connector service and do the following:
- Add
gem 'factor-connector-myservice'
to the connector Gemfile. - Run
bundle install
- Add
require 'factor/connector/myservice
toinit.rb
- If you added multiple files to /lib/factor/connector/ in this gem, you'll need to to repeat #3 for each of those.
The Connector API
More here: https://github.com/factor-io/connector-api/wiki/Connector-API-DSL
Testing
For testing we recommend using RSpec. As an example, check out the Rackspace connector.
Here is an example spec.
require 'spec_helper'
describe 'Compute' do
it 'can list servers' do
username = ENV['RACKSPACE_USERNAME']
api_key = ENV['RACKSPACE_API_KEY']
service_instance = service_instance('rackspace_compute')
params = {
'username' => username,
'api_key' => api_key,
'region' => 'dfw'
}
service_instance.test_action('list',params) do
expect_info message:"Retreiving list of servers"
expect_return
end
end
end
There are a few key methods provided by factor-connector-api/test
to use in your specs.
test_action(method,params={})
This is a method on ServiceInstance which takes the method name, parameters, and a block. The method refers to the acion you want to call. The parameters are the ones that get passed into your action call. The block should include the provided tests to validate the type of responses.
expect_return
This ensures that your action called action_callback
. It will return a hash of the form {type:'return', payload:{}}
, where the payload is the hash that was passed in when action_callback
.
expect_info, expect_warn, expect_error
These three methods react to calls for info
, warn
, and error
respecively. You can also (optionally) pass in {message: 'test message'}, to check that a particulare message was generated by the service connector. This method will return a hash with information about the matched response. It will be of the form {type:'log', status:'info', message:'...'}
, where status can be info
, warn
, or error
.
expect_fail
This is similar to expect_return except in this case we are testing that fail
was called in your connector and execution was stopped. This is great for negeative test cases. This method will returned a hash with the matched information of the form {type:'fail', message:'...'}
.