Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Ruby API client

Change-Id: I54001eaff699f667d4029691700b363f9db3ecc4
  • Loading branch information...
commit 37452a77d8432316de2edad00324893a52c8501e 1 parent a525a7a
@dougm dougm authored
View
3  api/ruby/Gemfile
@@ -0,0 +1,3 @@
+source :rubygems
+
+gemspec
View
28 api/ruby/Gemfile.lock
@@ -0,0 +1,28 @@
+PATH
+ remote: .
+ specs:
+ gonit_api (0.0.1)
+
+GEM
+ remote: http://rubygems.org/
+ specs:
+ builder (3.1.4)
+ ci_reporter (1.7.3)
+ builder (>= 2.1.2)
+ diff-lcs (1.1.3)
+ rspec (2.11.0)
+ rspec-core (~> 2.11.0)
+ rspec-expectations (~> 2.11.0)
+ rspec-mocks (~> 2.11.0)
+ rspec-core (2.11.1)
+ rspec-expectations (2.11.3)
+ diff-lcs (~> 1.1.3)
+ rspec-mocks (2.11.3)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ ci_reporter
+ gonit_api!
+ rspec
View
20 api/ruby/README
@@ -0,0 +1,20 @@
+Ruby JSON RPC Client for Go RPC Servers
+
+The gonit daemon serves its API over the standard net/rpc go package.
+Existing Ruby json rpc clients do not support unix sockets, afaict.
+
+Go's json rpc implementation may not be compatible with existing clients in any
+case; rsc on json rpc:
+
+ `It's not a standard. It's a web page some guy wrote,
+ and it's not terribly fleshed out.' [1]
+
+This module is currently generic, but may become gonit specific in the future.
+
+While gonit and this client can talk over a TCP connection, such use is
+discouraged as the connection is not authenticated. If you tinker with TCP, it
+should only be to localhost, in which case no connect timeouts are needed.
+
+File based permissions can be used for unix socket connections.
+
+[1] https://groups.google.com/d/msg/golang-nuts/6sCvbBaZvtI/TgjOa-rZ12EJ
View
13 api/ruby/Rakefile
@@ -0,0 +1,13 @@
+#!/usr/bin/env rake
+require "ci/reporter/rake/rspec"
+require "rspec/core/rake_task"
+
+desc "Run all specs"
+RSpec::Core::RakeTask.new("spec") do |t|
+ t.rspec_opts = %w[--color --format documentation]
+end
+
+desc "Run all specs and provide output for ci"
+RSpec::Core::RakeTask.new("spec:ci" => "ci:setup:rspec") do |t|
+ t.rspec_opts = %w[--no-color --format documentation]
+end
View
16 api/ruby/gonit_api.gemspec
@@ -0,0 +1,16 @@
+$:.unshift(File.join(File.dirname(__FILE__), 'lib'))
+
+require 'gonit_api/version'
+
+Gem::Specification.new do |s|
+ s.name = 'gonit_api'
+ s.version = GonitApi::VERSION
+ s.summary = 'Gonit API client'
+ s.description = s.summary
+ s.homepage = 'https://github.com/cloudfoundry/gonit'
+
+ s.add_development_dependency "rspec"
+ s.add_development_dependency "ci_reporter"
+
+ s.files = `git ls-files`.split("\n")
+ end
View
8 api/ruby/lib/gonit_api.rb
@@ -0,0 +1,8 @@
+# Copyright (c) 2012 VMware, Inc.
+
+require "json"
+require "socket"
+require "uri"
+
+require "gonit_api/client"
+require "gonit_api/version"
View
59 api/ruby/lib/gonit_api/client.rb
@@ -0,0 +1,59 @@
+# Copyright (c) 2012 VMware, Inc.
+
+module GonitApi
+
+ class RpcError < StandardError; end
+
+ class Client
+
+ def initialize(uri="#{ENV['HOME']}/.gonit.sock")
+ @uri = URI.parse(uri)
+ end
+
+ def request(method, *args)
+ socket = connect
+
+ begin
+ request = {
+ "method" => "API.#{method}",
+ "params" => args
+ }.to_json
+
+ socket.puts(request)
+
+ response = socket.gets
+
+ begin
+ response = JSON.parse(response)
+ rescue JSON::ParserError => e
+ raise RpcError, "parsing response `#{response}': #{e.message}"
+ end
+
+ if err = response["error"]
+ raise RpcError, err
+ end
+
+ response["result"]
+ ensure
+ socket.close
+ end
+ end
+
+ def method_missing(name, *args)
+ name = name.to_s.split("_").map { |s| s.capitalize }.join("")
+ request(name, *args)
+ end
+
+ private
+
+ def connect
+ case @uri.scheme
+ when "tcp"
+ TCPSocket.new(@uri.host, @uri.port)
+ else
+ UNIXSocket.new(@uri.path)
+ end
+ end
+
+ end
+end
View
5 api/ruby/lib/gonit_api/version.rb
@@ -0,0 +1,5 @@
+# Copyright (c) 2012 VMware, Inc.
+
+module GonitApi
+ VERSION = "0.0.1"
+end
View
4 api/ruby/spec/spec_helper.rb
@@ -0,0 +1,4 @@
+# Copyright (c) 2012 VMware, Inc.
+
+require "rspec"
+require "gonit_api"
View
81 api/ruby/spec/unit/client_spec.rb
@@ -0,0 +1,81 @@
+# Copyright (c) 2012 VMware, Inc.
+
+require File.dirname(__FILE__) + '/../spec_helper'
+
+describe GonitApi::Client do
+
+ let(:client) { GonitApi::Client.new() }
+
+ it "should request process status" do
+ socket = mock("socket")
+
+ client.should_receive(:connect).and_return(socket)
+
+ socket.should_receive(:puts).with { |json|
+ request = JSON.parse(json)
+ request["method"].should == "API.StatusProcess"
+ request["params"].should == ["gofy"]
+ }
+
+ result = {"license" => "gfl"}
+ response = {"result" => result}
+ socket.should_receive(:gets).and_return(response.to_json)
+
+ socket.should_receive(:close)
+
+ client.request("StatusProcess", "gofy").should == result
+ end
+
+ it "should request group stop" do
+ socket = mock("socket")
+
+ client.should_receive(:connect).and_return(socket)
+
+ socket.should_receive(:puts).with { |json|
+ request = JSON.parse(json)
+ request["method"].should == "API.StopGroup"
+ request["params"].should == ["bosh_animal_eraser"]
+ }
+
+ result = {"location" => "oleg's trunk"}
+ response = {"result" => result}
+ socket.should_receive(:gets).and_return(response.to_json)
+
+ socket.should_receive(:close)
+
+ client.stop_group("bosh_animal_eraser").should == result
+ end
+
+ it "should propagate response error" do
+ socket = mock("socket")
+
+ client.should_receive(:connect).and_return(socket)
+
+ socket.should_receive(:puts).with { |json|
+ request = JSON.parse(json)
+ request["method"].should == "API.MonitorGroup"
+ request["params"].should == ["dogs"]
+ }
+
+ response = {"error" => "pancakes"}
+ socket.should_receive(:gets).and_return(response.to_json)
+
+ socket.should_receive(:close)
+
+ expect { client.monitor_group("dogs") }.to raise_error(GonitApi::RpcError)
+ end
+
+ it "should handle invalid response" do
+ socket = mock("socket")
+
+ client.should_receive(:connect).and_return(socket)
+
+ socket.should_receive(:puts)
+
+ socket.should_receive(:close)
+
+ socket.should_receive(:gets).and_return("nonsense")
+
+ expect { client.stop_all }.to raise_error(GonitApi::RpcError)
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.