Commit 8ba5a858 authored by John E. Vincent's avatar John E. Vincent

finished tagging API. need specs for Tag REST API

parent 1a001230
...@@ -58,6 +58,7 @@ module Noah ...@@ -58,6 +58,7 @@ module Noah
erb :'500' erb :'500'
end end
load File.join(File.dirname(__FILE__), 'tag_routes.rb')
load File.join(File.dirname(__FILE__), 'host_routes.rb') load File.join(File.dirname(__FILE__), 'host_routes.rb')
load File.join(File.dirname(__FILE__), 'service_routes.rb') load File.join(File.dirname(__FILE__), 'service_routes.rb')
load File.join(File.dirname(__FILE__), 'application_routes.rb') load File.join(File.dirname(__FILE__), 'application_routes.rb')
......
...@@ -38,8 +38,9 @@ class Noah::App ...@@ -38,8 +38,9 @@ class Noah::App
put '/applications/:appname/link' do |appname| put '/applications/:appname/link' do |appname|
required_params = ["link_name"] required_params = ["link_name"]
data = JSON.parse(request.body.read) data = JSON.parse(request.body.read)
(data.keys.sort == required_params.sort) ? (a = Noah::Applicaiton.find(:name => appname).first) : (raise "Missing Parameters") (data.keys.sort == required_params.sort) ? (a = Noah::Application.find(:name => appname).first) : (raise "Missing Parameters")
#a.nil? ? (halt 404) : (a.link! a.nil? ? (halt 404) : (a.link! data["link_name"])
a.to_json
end end
put '/applications/:appname/?' do |appname| put '/applications/:appname/?' do |appname|
......
...@@ -38,6 +38,14 @@ class Noah::App ...@@ -38,6 +38,14 @@ class Noah::App
end end
end end
put '/configurations/:configname/tag' do |configname|
required_params = ["tags"]
data = JSON.parse(request.body.read)
(data.keys.sort == required_params.sort) ? (c=Noah::Configuration.find(:name=>configname).first) : (raise "Missing Parameters")
c.nil? ? (halt 404) : (c.tag!(data['tags']))
c.to_json
end
put '/configurations/:configname/watch' do |configname| put '/configurations/:configname/watch' do |configname|
required_params = ["endpoint"] required_params = ["endpoint"]
data = JSON.parse(request.body.read) data = JSON.parse(request.body.read)
......
class Noah::App class Noah::App
get '/e/?' do get '/ephemerals/?' do
halt 404 halt 404
end end
get '/e/*' do get '/ephemerals/*' do
params["splat"].size == 0 ? (halt 404) : (e=Noah::Ephemeral.find(:path => "/#{params["splat"][0]}").first) params["splat"].size == 0 ? (halt 404) : (e=Noah::Ephemeral.find(:path => "/#{params["splat"][0]}").first)
(halt 404) if e.nil? (halt 404) if e.nil?
content_type "application/octet-stream" content_type "application/octet-stream"
e.data.nil? ? "" : "#{e.data}" e.data.nil? ? "" : "#{e.data}"
end end
put '/e/*/watch' do put '/ephemerals/*/watch' do
required_params = ["endpoint"] required_params = ["endpoint"]
data = JSON.parse(request.body.read) data = JSON.parse(request.body.read)
(data.keys.sort == required_params.sort) ? (e = Noah::Watcher.find(:path => params[:splat][0]).first) : (raise "Missing Parameters") (data.keys.sort == required_params.sort) ? (e = Noah::Watcher.find(:path => params[:splat][0]).first) : (raise "Missing Parameters")
...@@ -18,7 +18,7 @@ class Noah::App ...@@ -18,7 +18,7 @@ class Noah::App
w.to_json w.to_json
end end
put '/e/*' do put '/ephemerals/*' do
raise("Data too large") if request.body.size > 512 raise("Data too large") if request.body.size > 512
d = request.body.read || nil d = request.body.read || nil
opts = {:path => "/#{params[:splat][0]}", :data => d} opts = {:path => "/#{params[:splat][0]}", :data => d}
...@@ -32,7 +32,7 @@ class Noah::App ...@@ -32,7 +32,7 @@ class Noah::App
end end
end end
delete '/e/*' do delete '/ephemerals/*' do
p = params[:splat][0] p = params[:splat][0]
e = Noah::Ephemeral.find(:path => "/"+p).first e = Noah::Ephemeral.find(:path => "/"+p).first
if e if e
......
...@@ -32,6 +32,14 @@ class Noah::App ...@@ -32,6 +32,14 @@ class Noah::App
end end
end end
put '/hosts/:hostname/tag' do |hostname|
required_params = ["tags"]
data = JSON.parse(request.body.read)
(data.keys.sort == required_params.sort) ? (a=Noah::Host.find(:name=>hostname).first) : (raise "Missing Parameters")
a.nil? ? (halt 404) : (a.tag!(data['tags']))
a.to_json
end
put '/hosts/:hostname/watch' do |hostname| put '/hosts/:hostname/watch' do |hostname|
required_params = ["endpoint"] required_params = ["endpoint"]
data = JSON.parse(request.body.read) data = JSON.parse(request.body.read)
...@@ -40,6 +48,14 @@ class Noah::App ...@@ -40,6 +48,14 @@ class Noah::App
w.to_json w.to_json
end end
put '/hosts/:hostname/link' do |hostname|
required_params = ["link_name"]
data = JSON.parse(request.body.read)
(data.keys.sort == required_params.sort) ? (a = Noah::Host.find(:name => hostname).first) : (raise "Missing Parameters")
a.nil? ? (halt 404) : (a.link! data["link_name"])
a.to_json
end
put '/hosts/:hostname/?' do |hostname| put '/hosts/:hostname/?' do |hostname|
required_params = ["name", "status"] required_params = ["name", "status"]
data = JSON.parse(request.body.read) data = JSON.parse(request.body.read)
......
...@@ -111,10 +111,11 @@ module Noah ...@@ -111,10 +111,11 @@ module Noah
end end
require File.join(File.dirname(__FILE__), 'models','tags') require File.join(File.dirname(__FILE__), 'linkable')
require File.join(File.dirname(__FILE__), 'models','link') require File.join(File.dirname(__FILE__), 'models','link')
require File.join(File.dirname(__FILE__), 'taggable') require File.join(File.dirname(__FILE__), 'taggable')
require File.join(File.dirname(__FILE__), 'linkable') require File.join(File.dirname(__FILE__), 'models','tags')
require File.join(File.dirname(__FILE__), 'models','link')
require File.join(File.dirname(__FILE__), 'models','hosts') require File.join(File.dirname(__FILE__), 'models','hosts')
require File.join(File.dirname(__FILE__), 'models','services') require File.join(File.dirname(__FILE__), 'models','services')
require File.join(File.dirname(__FILE__), 'models','applications') require File.join(File.dirname(__FILE__), 'models','applications')
......
...@@ -23,7 +23,7 @@ module Noah ...@@ -23,7 +23,7 @@ module Noah
end end
else else
self.key[:nodes].sadd(node.key) self.key[:nodes].sadd(node.key)
n.links << self node.links << self
end end
end end
...@@ -38,6 +38,7 @@ module Noah ...@@ -38,6 +38,7 @@ module Noah
%w[applications configurations hosts services ephemerals].each {|x| instance_variable_set("@#{x}", Hash.new)} %w[applications configurations hosts services ephemerals].each {|x| instance_variable_set("@#{x}", Hash.new)}
if nodes.size > 0 if nodes.size > 0
nodes.each do |node| nodes.each do |node|
rejected_vals = [:created_at, :updated_at, :links, :name]
n = node_to_class(node) n = node_to_class(node)
cls = class_to_lower(n.class.to_s) cls = class_to_lower(n.class.to_s)
hsh = instance_variable_get("@#{cls}s") hsh = instance_variable_get("@#{cls}s")
...@@ -53,7 +54,7 @@ module Noah ...@@ -53,7 +54,7 @@ module Noah
when "host" when "host"
hsh["#{n.name}"].merge!({:id => n.id, :status => n.status, :tags => n.to_hash[:tags], :services => n.to_hash[:services]}) hsh["#{n.name}"].merge!({:id => n.id, :status => n.status, :tags => n.to_hash[:tags], :services => n.to_hash[:services]})
else else
hsh[n.name].merge!(n.to_hash.reject{|key, value| key == :created_at || key == :updated_at || key == :name}) hsh["#{n.name}"].merge!(n.to_hash.reject{|key, value| rejected_vals.member?(key)})
end end
end end
end end
...@@ -68,10 +69,7 @@ module Noah ...@@ -68,10 +69,7 @@ module Noah
class <<self class <<self
def find_or_create(opts={}) def find_or_create(opts={})
begin begin
find(opts).first.nil? ? obj=new(opts) : obj=find(opts).first find(opts).first.nil? ? obj=create(opts) : obj=find(opts).first
if obj.valid?
obj.save
end
obj obj
rescue Exception => e rescue Exception => e
e.message e.message
......
module Noah module Noah
class Tag < Model class Tag < Model
attribute :name attribute :name
attribute :members attribute :members
...@@ -23,35 +24,72 @@ module Noah ...@@ -23,35 +24,72 @@ module Noah
cls = class_to_lower(n.class.to_s) cls = class_to_lower(n.class.to_s)
hash_key = "#{cls}s".to_sym hash_key = "#{cls}s".to_sym
hsh[hash_key] = Array.new unless hsh.has_key?(hash_key) hsh[hash_key] = Array.new unless hsh.has_key?(hash_key)
hsh[hash_key] << n.name hsh[hash_key] << n
end end
hsh hsh
end end
def self.tagged(tag) def to_hash
t = find(:name => tag).first h = {:name => name, :created_at => created_at, :updated_at => updated_at}
t.members h.merge!(members_to_hash)
super.merge(h)
end end
class <<self class <<self
def find_or_create(opts={}) def find_or_create(opts={})
begin begin
find(opts).first.nil? ? obj=new(opts) : obj=find(opts).first find(opts).first.nil? ? obj=create(opts) : obj=find(opts).first
if obj.valid? obj
obj.save rescue Exception => e
e.message
end end
obj
rescue Exception => e
e.message
end end
end end
end
private private
def node_to_class(node) def node_to_class(node)
node.match(/^Noah::(.*):(\d+)$/) node.match(/^Noah::(.*):(\d+)$/)
Noah.const_get($1).send(:[], $2) Noah.const_get($1).send(:[], $2)
end end
def members_to_hash
new_hash = Hash.new
members.keys.each {|k| new_hash[k] = Hash.new}
members.each do |category, member_array|
rejected_vals = [:created_at, :updated_at, :tags, :name, :host]
h = new_hash[category]
member_array.each {|mem| h["#{mem.name}"] = Hash.new unless h.has_key?(mem.name)}
case category
when :services
member_array.each do |s|
sh = Noah::Host[s.host_id].name
h["#{s.name}"]["#{sh}"] = Hash.new unless h["#{s.name}"].has_key?(sh)
h["#{s.name}"]["#{sh}"].merge!(s.to_hash.reject{|k,v| rejected_vals.member?(k)})
end
else
member_array.each do |m|
h["#{m.name}"].merge!(m.to_hash.reject{|k,v| rejected_vals.member?(k)})
end
end
end
new_hash
end
end
class Tags
def self.all(options = {})
tag_hash = Hash.new
options.empty? ? tags=Tag.all.sort : tags=Tag.find(options).sort
tags.each {|t| tag_hash["#{t.name}"] = t.to_hash.reject {|k,v| k == :name } }
tag_hash
end
class <<self
def tagged(tag)
t = Tag.find(:name => tag).first
t.members
end
end
end end
end end
...@@ -22,6 +22,14 @@ class Noah::App ...@@ -22,6 +22,14 @@ class Noah::App
services.to_json services.to_json
end end
put '/services/:servicename/:hostname/tag' do |servicename, hostname|
required_params = ["tags"]
data = JSON.parse(request.body.read)
(data.keys.sort == required_params.sort) ? (a=host_service(hostname, servicename)) : (raise "Missing Parameters")
a.nil? ? (halt 404) : (a.tag!(data['tags']))
a.to_json
end
put '/services/:servicename/watch' do |servicename| put '/services/:servicename/watch' do |servicename|
required_params = ["endpoint"] required_params = ["endpoint"]
data = JSON.parse(request.body.read) data = JSON.parse(request.body.read)
......
class Noah::App
get '/tags/:tagname/?' do |tagname|
tags = Noah::Tags.all(:name => tagname).to_hash
(halt 404) if tags.size == 0
tags.to_json
end
get '/tags/?' do
tags = Noah::Tags.all.to_hash
(halt 404) if tags.size == 0
tags.to_json
end
end
...@@ -27,8 +27,6 @@ describe "Using the Application API", :reset_redis => false do ...@@ -27,8 +27,6 @@ describe "Using the Application API", :reset_redis => false do
response.has_key?("configurations").should == true response.has_key?("configurations").should == true
c = response["configurations"] c = response["configurations"]
c.has_key?(@c.name).should == true c.has_key?(@c.name).should == true
p @c
p c
c["#{@c.name}"]["format"].should == "#{@c.format}" c["#{@c.name}"]["format"].should == "#{@c.format}"
c["#{@c.name}"]["body"].should == "#{@c.body}" c["#{@c.name}"]["body"].should == "#{@c.body}"
end end
......
...@@ -13,7 +13,7 @@ describe "Using the Ephemeral API", :reset_redis => true do ...@@ -13,7 +13,7 @@ describe "Using the Ephemeral API", :reset_redis => true do
describe "GET" do describe "GET" do
it "all ephemerals should return 404" do it "all ephemerals should return 404" do
get '/e' get '/ephemerals'
last_response.should_not be_ok last_response.should_not be_ok
last_response.status.should == 404 last_response.status.should == 404
response = last_response.should return_json response = last_response.should return_json
...@@ -22,13 +22,13 @@ describe "Using the Ephemeral API", :reset_redis => true do ...@@ -22,13 +22,13 @@ describe "Using the Ephemeral API", :reset_redis => true do
end end
it "named path with data should work" do it "named path with data should work" do
get '/e/foo/bar/baz' get '/ephemerals/foo/bar/baz'
last_response.should be_ok last_response.should be_ok
last_response.body.should == 'value1' last_response.body.should == 'value1'
end end
it "named path without data should work" do it "named path without data should work" do
get '/e/baz/bar' get '/ephemerals/baz/bar'
last_response.status.should == 200 last_response.status.should == 200
last_response.body.should == "" last_response.body.should == ""
end end
...@@ -45,7 +45,7 @@ describe "Using the Ephemeral API", :reset_redis => true do ...@@ -45,7 +45,7 @@ describe "Using the Ephemeral API", :reset_redis => true do
describe "PUT" do describe "PUT" do
it "new ephemeral with data should work" do it "new ephemeral with data should work" do
put '/e/whiz/bang/', 'value3' put '/ephemerals/whiz/bang/', 'value3'
last_response.should be_ok last_response.should be_ok
response = last_response.should return_json response = last_response.should return_json
response['result'].should == 'success' response['result'].should == 'success'
...@@ -55,7 +55,7 @@ describe "Using the Ephemeral API", :reset_redis => true do ...@@ -55,7 +55,7 @@ describe "Using the Ephemeral API", :reset_redis => true do
end end
it "new ephemeral without data should work" do it "new ephemeral without data should work" do
put '/e/bang/whiz' put '/ephemerals/bang/whiz'
last_response.should be_ok last_response.should be_ok
response = last_response.should return_json response = last_response.should return_json
response['result'].should == 'success' response['result'].should == 'success'
...@@ -67,35 +67,35 @@ describe "Using the Ephemeral API", :reset_redis => true do ...@@ -67,35 +67,35 @@ describe "Using the Ephemeral API", :reset_redis => true do
it "existing ephemeral with data should work" do it "existing ephemeral with data should work" do
Noah::Ephemeral.create(:path => '/new/ephemeral', :data => 'old_value') Noah::Ephemeral.create(:path => '/new/ephemeral', :data => 'old_value')
get '/e/new/ephemeral' get '/ephemerals/new/ephemeral'
last_response.should be_ok last_response.should be_ok
last_response.body.should == 'old_value' last_response.body.should == 'old_value'
put '/e/new/ephemeral', 'new_value' put '/ephemerals/new/ephemeral', 'new_value'
last_response.should be_ok last_response.should be_ok
get '/e/new/ephemeral' get '/ephemerals/new/ephemeral'
last_response.should be_ok last_response.should be_ok
last_response.body.should == 'new_value' last_response.body.should == 'new_value'
end end
it "existing ephemeral without data should work" do it "existing ephemeral without data should work" do
Noah::Ephemeral.create(:path => '/a/random/key') Noah::Ephemeral.create(:path => '/a/random/key')
get '/e/a/random/key' get '/ephemerals/a/random/key'
last_response.should be_ok last_response.should be_ok
last_response.body.should == "" last_response.body.should == ""
put '/e/a/random/key', 'a new value' put '/ephemerals/a/random/key', 'a new value'
last_response.should be_ok last_response.should be_ok
get '/e/a/random/key' get '/ephemerals/a/random/key'
last_response.should be_ok last_response.should be_ok
last_response.body.should == 'a new value' last_response.body.should == 'a new value'
end end
it "ephemeral with reserved word in subpath should work" do it "ephemeral with reserved word in subpath should work" do
Noah::PROTECTED_PATHS.each do |path| Noah::PROTECTED_PATHS.each do |path|
put "/e/a/valid/path/with/#{path}" put "/ephemerals/a/valid/path/with/#{path}"
last_response.should be_ok last_response.should be_ok
end end
end end
it "ephemeral with reserved word as path should not work" do it "ephemeral with reserved word as path should not work" do
Noah::PROTECTED_PATHS.each do |path| Noah::PROTECTED_PATHS.each do |path|
put "/e/#{path}/other/stuff" put "/ephemerals/#{path}/other/stuff"
last_response.should_not be_ok last_response.should_not be_ok
response = last_response.should return_json response = last_response.should return_json
response['error_message'].should == 'Path is reserved' response['error_message'].should == 'Path is reserved'
...@@ -108,7 +108,7 @@ describe "Using the Ephemeral API", :reset_redis => true do ...@@ -108,7 +108,7 @@ describe "Using the Ephemeral API", :reset_redis => true do
it "existing path should work" do it "existing path should work" do
e = Noah::Ephemeral.new(:path => '/slart/i/bart/fast', :data => 'someddata') e = Noah::Ephemeral.new(:path => '/slart/i/bart/fast', :data => 'someddata')
e.save e.save
delete "/e/slart/i/bart/fast" delete "/ephemerals/slart/i/bart/fast"
last_response.should be_ok last_response.should be_ok
response = last_response.should return_json response = last_response.should return_json
response['result'].should == 'success' response['result'].should == 'success'
...@@ -118,7 +118,7 @@ describe "Using the Ephemeral API", :reset_redis => true do ...@@ -118,7 +118,7 @@ describe "Using the Ephemeral API", :reset_redis => true do
end end
it "invalid path should not work" do it "invalid path should not work" do
delete '/e/fork/spoon/knife' delete '/ephemerals/fork/spoon/knife'
last_response.should_not be_ok last_response.should_not be_ok
last_response.status.should == 404 last_response.status.should == 404
response = last_response.should return_json response = last_response.should return_json
......
...@@ -13,7 +13,6 @@ if h.save ...@@ -13,7 +13,6 @@ if h.save
%w[redis noah].each do |service| %w[redis noah].each do |service|
puts "Create Service entry for #{service}" puts "Create Service entry for #{service}"
s = Noah::Service.create(:name => service, :status => "up", :host_id => h.id) s = Noah::Service.create(:name => service, :status => "up", :host_id => h.id)
h.services << s
end end
end end
...@@ -24,8 +23,8 @@ if a.save ...@@ -24,8 +23,8 @@ if a.save
cr = Noah::Configuration.create(:name => 'redis', :format => 'string', :body => 'redis://127.0.0.1:6379/0') cr = Noah::Configuration.create(:name => 'redis', :format => 'string', :body => 'redis://127.0.0.1:6379/0')
ch = Noah::Configuration.create(:name => 'host', :format => 'string', :body => 'localhost') ch = Noah::Configuration.create(:name => 'host', :format => 'string', :body => 'localhost')
cp = Noah::Configuration.create(:name => 'port', :format => 'string', :body => '9292') cp = Noah::Configuration.create(:name => 'port', :format => 'string', :body => '9292')
%w[cr ch cp].each do |c| [cr,ch,cp].each do |c|
a.configurations << eval(c) a.configurations << c
end end
end end
...@@ -34,7 +33,7 @@ puts "Creating sample entries - Host and Service" ...@@ -34,7 +33,7 @@ puts "Creating sample entries - Host and Service"
h = Noah::Host.create(:name => host, :status => "up") h = Noah::Host.create(:name => host, :status => "up")
if h.save if h.save
%w[http https smtp mysql].each do |service| %w[http https smtp mysql].each do |service|
s = Noah::Service.create(:name => service, :status => "pending", :host => h) s = Noah::Service.create(:name => service, :status => "pending", :host_id => h.id)
h.services << s h.services << s
end end
end end
...@@ -77,7 +76,11 @@ l1.path = "/my_sample_organization" ...@@ -77,7 +76,11 @@ l1.path = "/my_sample_organization"
l1.save l1.save
l1.nodes = [a1, c2, Noah::Host.find(:name => 'localhost').first, Noah::Service.find(:name => 'redis').first, e1, e2] l1.nodes = [a1, c2, Noah::Host.find(:name => 'localhost').first, Noah::Service.find(:name => 'redis').first, e1, e2]
a1.tag! ["production", "sample_data"] a1.tag! ["production", "sample_data"]
e2.tag! "ephemeral" e2.tag! ["ephemeral", "development"]
c1.tag! "development"
Noah::Service[1].tag! "development"
Noah::Service[2].tag! ["development", "out-of-service"]
Noah::Service[2].link! "/my_sample_organization"
puts "Sample data populated!" puts "Sample data populated!"
......
...@@ -28,14 +28,14 @@ describe "Using the Tag Model", :reset_redis => true do ...@@ -28,14 +28,14 @@ describe "Using the Tag Model", :reset_redis => true do
t.members = @host t.members = @host
@host.tags.member?(t).should == true @host.tags.member?(t).should == true
t.members[:hosts].size.should == 1 t.members[:hosts].size.should == 1
t.members[:hosts].member?(@host.name).should == true t.members[:hosts].member?(@host).should == true
end end
it "tag! an existing object with a single tag" do it "tag! an existing object with a single tag" do
@host.tag! @tags2 @host.tag! @tags2
t = Noah::Tag.find(:name => @tags2).first t = Noah::Tag.find(:name => @tags2).first
@host.tags.member?(t).should == true @host.tags.member?(t).should == true
t.members[:hosts].size.should == 1 t.members[:hosts].size.should == 1
t.members[:hosts].member?(@host.name).should == true t.members[:hosts].member?(@host).should == true
end end
it "tag! an existing object with an array of tags" do it "tag! an existing object with an array of tags" do
@host.tag! @tags1 @host.tag! @tags1
...@@ -43,18 +43,20 @@ describe "Using the Tag Model", :reset_redis => true do ...@@ -43,18 +43,20 @@ describe "Using the Tag Model", :reset_redis => true do
t = Noah::Tag.find(:name => tag).first t = Noah::Tag.find(:name => tag).first
@host.tags.member?(t).should == true @host.tags.member?(t).should == true
t.members[:hosts].size.should == 1 t.members[:hosts].size.should == 1
t.members[:hosts].member?(@host.name).should == true t.members[:hosts].member?(@host).should == true
end end
Noah::Tag.all.size.should == 3 Noah::Tag.all.size.should == 3
end end
it "tag all object types and find via tagged" do it "tag all object types and find via tagged" do
[@host, @service, @application, @configuration, @ephemeral].each do |o| @host.tag! @tags1
o.tag! @tags1 @ephemeral.tag! @tags1
end @configuration.tag! @tags1
@application.tag! @tags1
@service.tag! @tags1
@tags1.each do |tag| @tags1.each do |tag|
Noah::Tag.tagged(tag).size.should == 5 Noah::Tags.tagged(tag).size.should == 5
[@host, @service, @application, @configuration, @ephemeral].each do |o| [@host, @service, @application, @configuration, @ephemeral].each do |o|
Noah::Tag.tagged(tag).values.flatten.member?(o.name).should == true Noah::Tags.tagged(tag).values.flatten.member?(o).should == true
end end
end end
end end
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment