├── .gitignore ├── .travis.yml ├── Gemfile ├── MIT-LICENSE.txt ├── README.org ├── Rakefile ├── carrot-top.gemspec ├── carrot-top.jpg ├── lib └── carrot-top.rb └── test └── query_api_tests.rb /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | .bundle 3 | Gemfile.lock 4 | pkg/* 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | rvm: 3 | - 1.9.3 4 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "http://rubygems.org" 2 | 3 | # Specify your gem's dependencies in carrot-top.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /MIT-LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011 Sean Porter. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.org: -------------------------------------------------------------------------------- 1 | [[https://secure.travis-ci.org/portertech/carrot-top.png]] 2 | 3 | * Install 4 | 5 | : gem install carrot-top 6 | 7 | * Usage 8 | 9 | : require "carrot-top" 10 | : 11 | : carrot_top = CarrotTop.new( 12 | : :host => "localhost", 13 | : :port => 55672, 14 | : :user => "user", 15 | : :password => "password" 16 | : ) 17 | 18 | Use SSL if the management API supports it (optional) 19 | 20 | : :ssl => true 21 | 22 | Various random bits of information that describe the whole system. 23 | 24 | : carrot_top.overview 25 | 26 | A list of all open connections. 27 | 28 | : carrot_top.connections 29 | 30 | A list of all open channels. 31 | 32 | : carrot_top.channels 33 | 34 | A list of all exchanges. 35 | 36 | : carrot_top.exchanges 37 | 38 | A list of all queues. 39 | 40 | : carrot_top.queues 41 | 42 | A list of all bindings. 43 | 44 | : carrot_top.bindings 45 | 46 | A list of all vhosts. 47 | 48 | : carrot_top.vhosts 49 | 50 | A list of all users. 51 | 52 | : carrot_top.users 53 | 54 | A list of all permissions for all users. 55 | 56 | : carrot_top.permissions 57 | 58 | * License 59 | Carrot-Top is released under the [[https://raw.github.com/portertech/carrot-top/master/MIT-LICENSE.txt][MIT license]]. 60 | 61 | * Nothing to do with this guy 62 | 63 | [[https://github.com/portertech/carrot-top/raw/master/carrot-top.jpg]] 64 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | require "rake/testtask" 3 | 4 | Rake::TestTask.new do |test| 5 | test.pattern = "test/*_tests.rb" 6 | end 7 | 8 | task :default => "test" 9 | -------------------------------------------------------------------------------- /carrot-top.gemspec: -------------------------------------------------------------------------------- 1 | $:.push File.expand_path("../lib", __FILE__) 2 | 3 | Gem::Specification.new do |s| 4 | s.name = "carrot-top" 5 | s.version = "0.0.7" 6 | s.authors = ["Sean Porter"] 7 | s.email = ["portertech@gmail.com"] 8 | s.homepage = "https://github.com/portertech/carrot-top" 9 | s.summary = "A Ruby library for querying the RabbitMQ Management API" 10 | s.description = "A Ruby library for querying the RabbitMQ Management API, `top` for RabbitMQ." 11 | 12 | s.rubyforge_project = "carrot-top" 13 | 14 | s.files = `git ls-files`.split("\n").reject {|f| f =~ /(test|jpg)/} 15 | s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") 16 | s.require_paths = ["lib"] 17 | 18 | s.add_dependency "json" 19 | s.add_development_dependency "rake" 20 | s.add_development_dependency "webmock" 21 | end 22 | -------------------------------------------------------------------------------- /carrot-top.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/portertech/carrot-top/1411765aaf0f3735415e223f4aa2a6a03756c438/carrot-top.jpg -------------------------------------------------------------------------------- /lib/carrot-top.rb: -------------------------------------------------------------------------------- 1 | require "rubygems" 2 | require "net/http" 3 | require "net/https" 4 | require "uri" 5 | require "json" 6 | 7 | class CarrotTop 8 | attr_reader :rabbitmq_api 9 | 10 | def initialize(options={}) 11 | [:host, :port, :user, :password].each do |option| 12 | if options[option].nil? 13 | raise ArgumentError, "You must supply a RabbitMQ management API #{option}" 14 | end 15 | end 16 | protocol = options[:ssl] ? "https" : "http" 17 | credentials = "#{options[:user]}:#{options[:password]}" 18 | location = "#{options[:host]}:#{options[:port]}" 19 | @rabbitmq_api = "#{protocol}://#{credentials}@#{location}/api" 20 | end 21 | 22 | def query_api(options={}) 23 | raise ArgumentError, "You must supply an API path" if options[:path].nil? 24 | fetch_uri(@rabbitmq_api + options[:path]) 25 | end 26 | 27 | def method_missing(method, *args, &block) 28 | response = self.query_api(:path => "/#{method}") 29 | begin 30 | JSON.parse(response.body) 31 | rescue JSON::ParserError 32 | Hash.new 33 | end 34 | end 35 | 36 | private 37 | 38 | def fetch_uri(uri, limit=5) 39 | raise ArgumentError, "HTTP redirect too deep" if limit == 0 40 | url = URI.parse(uri) 41 | http = Net::HTTP.new(url.host, url.port) 42 | if url.scheme == "https" 43 | http.use_ssl = true 44 | http.verify_mode = OpenSSL::SSL::VERIFY_NONE 45 | end 46 | request = Net::HTTP::Get.new(url.request_uri) 47 | request.add_field("content-type", "application/json") 48 | request.basic_auth(url.user, url.password) 49 | response = http.request(request) 50 | case response 51 | when Net::HTTPSuccess 52 | response 53 | when Net::HTTPRedirection 54 | redirect_url = URI.parse(response["location"]) 55 | redirect_url.user = url.user 56 | redirect_url.password = url.password 57 | fetch_uri(redirect_url.to_s, limit - 1) 58 | else 59 | response.error! 60 | end 61 | end 62 | 63 | end 64 | -------------------------------------------------------------------------------- /test/query_api_tests.rb: -------------------------------------------------------------------------------- 1 | require "minitest/spec" 2 | require "minitest/autorun" 3 | require "webmock/minitest" 4 | 5 | require File.join(File.dirname(__FILE__), "..", "lib", "carrot-top") 6 | 7 | describe CarrotTop do 8 | before do 9 | @options = { 10 | :host => "localhost", 11 | :port => 55672, 12 | :user => "user", 13 | :password => "password" 14 | } 15 | @body = {"foo" => "bar"} 16 | api_uri = "#{@options[:user]}:#{@options[:password]}@#{@options[:host]}:#{@options[:port]}/api" 17 | stub_request(:get, /.*#{api_uri}.*/). 18 | with(:headers => {"content-type" => "application/json"}). 19 | to_return(:status => 200, :body => @body.to_json, :headers => {"content-type" => "application/json"}) 20 | end 21 | 22 | it "can query the rabbitmq management api" do 23 | carrot_top = CarrotTop.new(@options) 24 | response = carrot_top.query_api(:path => "/foo") 25 | response.code.must_equal("200") 26 | response.body.must_equal(@body.to_json) 27 | end 28 | 29 | it "can query the rabbitmq management using ssl" do 30 | carrot_top = CarrotTop.new(@options.merge(:ssl => true)) 31 | carrot_top.rabbitmq_api.must_match(/^https/) 32 | response = carrot_top.query_api(:path => "/foo") 33 | response.code.must_equal("200") 34 | response.body.must_equal(@body.to_json) 35 | end 36 | 37 | it "can query the rabbitmq management api with method missing" do 38 | carrot_top = CarrotTop.new(@options) 39 | body = carrot_top.foo 40 | body.must_equal(@body) 41 | end 42 | 43 | it "must be provided mandatory options" do 44 | options = @options 45 | options.delete(:port) 46 | lambda { 47 | CarrotTop.new(options) 48 | }.must_raise(ArgumentError) 49 | end 50 | end 51 | --------------------------------------------------------------------------------