Commit 526e1e74 authored by John E. Vincent's avatar John E. Vincent

final 1.0 API for applications and configurations

parent 1941fd0c
...@@ -82,6 +82,32 @@ module Noah ...@@ -82,6 +82,32 @@ module Noah
r.to_json r.to_json
end end
def add_config_to_app(appname, config_hash)
begin
config = Noah::Configuration.find_or_create(config_hash)
if config.valid?
dep_action = config.is_new? ? "create" : "update"
else
raise "#{format_errors(config)}"
end
app = Noah::Application.find_or_create(:name => appname)
if app.valid?
action = app.is_new? ? "create" : "update"
app.configurations << config
r = {"result" => "success", "id" => "#{app.id}", "name" => "#{app.name}", "action" => action, "configuration" => {"action" => dep_action, "id" => "#{config.id}", "item" => "#{config.name}"}}
r.to_json
else
raise "#{format_errors(app)}"
end
rescue Exception => e
e.message
ensure
# Clean up partial objects
app.delete if app.valid? == false
config.delete if config.valid? == false
end
end
def application(opts = {}) def application(opts = {})
Noah::Application.find(opts).first Noah::Application.find(opts).first
end end
......
...@@ -20,7 +20,8 @@ module Noah ...@@ -20,7 +20,8 @@ module Noah
configurations.sort.each do |cfg| configurations.sort.each do |cfg|
cfg_hash["#{cfg.name}"] = {:format => cfg.to_hash[:format], :body => cfg.to_hash[:body]} cfg_hash["#{cfg.name}"] = {:format => cfg.to_hash[:format], :body => cfg.to_hash[:body]}
end end
{name => {:id => id, :created_at => created_at, :updated_at => updated_at, :configurations => cfg_hash}} res_hash = {:name => name, :created_at => created_at, :updated_at => updated_at, :configurations => cfg_hash}
super.merge(res_hash)
end end
class << self class << self
...@@ -43,8 +44,7 @@ module Noah ...@@ -43,8 +44,7 @@ module Noah
def self.all(options = {}) def self.all(options = {})
app_hash = Hash.new app_hash = Hash.new
options.empty? ? apps=Application.all.sort : apps=Application.find(options).sort options.empty? ? apps=Application.all.sort : apps=Application.find(options).sort
#apps.each {|x| app_hash["#{x.name}"] = x.to_hash.reject {|k,v| k == :name} } apps.each {|x| app_hash["#{x.name}"] = x.to_hash.reject {|k,v| k == :name} }
apps.each {|x| app_hash.merge!(x.to_hash) }
app_hash app_hash
end end
end end
......
...@@ -44,9 +44,13 @@ module Noah ...@@ -44,9 +44,13 @@ 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(:name => opts[:name]).first.nil? ? (obj = new(opts)) : (obj = find(:name => opts[:name]).first)
if obj.valid? if obj.valid? && obj.new?
obj.save obj.save
else
obj.format = opts[:format]
obj.body = opts[:body]
obj.save if obj.valid?
end end
obj obj
rescue Exception => e rescue Exception => e
......
class Noah::App class Noah::App
# Application URIs # Application URIs
get '/applications/:appname/:config/?' do |appname, config| get '/applications/:appname/configurations/:config/?' do |appname, config|
app = Noah::Application.find(:name => appname).first app = Noah::Application.find(:name => appname).first
(halt 404) if app.nil? (halt 404) if app.nil?
c = app.configurations.find(:name => config).first request.path_info = "/configurations/#{config}"
c.to_json pass
end end
get '/applications/:appname/?' do |appname| get '/applications/:appname/?' do |appname|
...@@ -37,6 +37,14 @@ class Noah::App ...@@ -37,6 +37,14 @@ class Noah::App
a.to_json a.to_json
end end
put '/applications/:appname/configurations/:configname/?' do |appname, configname|
required_params = ["format", "body"]
raise "Missing Parameters" if request.body.nil?
data = JSON.parse(request.body.read)
raise "Missing Parameters" if data.keys.sort != required_params.sort
add_config_to_app(appname, {:name => configname, :format => data['format'], :body => data['body']})
end
put '/applications/:appname/?' do |appname| put '/applications/:appname/?' do |appname|
required_params = ["name"] required_params = ["name"]
data = JSON.parse(request.body.read) data = JSON.parse(request.body.read)
...@@ -64,6 +72,17 @@ class Noah::App ...@@ -64,6 +72,17 @@ class Noah::App
end end
delete '/applications/:appname/configurations/:configname/?' do |appname, configname| delete '/applications/:appname/configurations/:configname/?' do |appname, configname|
app = Noah::Application.find(:name => appname).first
(halt 404) if app.nil?
config = Noah::Configuration.find(:name => configname).first
(halt 404) if config.nil?
if app.configurations.member?(config)
app.configurations.delete(config)
r = {"result" => "success", "action" => "delete", "id" => "#{app.id}", "name" => "#{app.name}", "configuration" => "#{config.name}"}
r.to_json
else
halt 404
end
end end
get '/applications/?' do get '/applications/?' do
......
...@@ -5,19 +5,17 @@ class Noah::App ...@@ -5,19 +5,17 @@ class Noah::App
:xml => "text/xml", :xml => "text/xml",
:string => "text/plain" :string => "text/plain"
} }
# GET the raw data of a configuration object get '/configurations/:configname/?', :provides => :json do |configname|
get '/configurations/:configname/data/?' do |configname|
c = Noah::Configuration.find(:name => configname).first c = Noah::Configuration.find(:name => configname).first
(halt 404) if c.nil? (halt 404) if c.nil?
content_type content_type_mapping[c.format.to_sym] if content_type_mapping[c.format.to_sym] c.to_json
response.headers['Content-Disposition'] = "attachment; filename=#{configname}"
c.body
end end
# GET the JSON representation of a configuration object
get '/configurations/:configname/?' do |configname| get '/configurations/:configname/?' do |configname|
c = Noah::Configuration.find(:name => configname).first c = Noah::Configuration.find(:name => configname).first
(halt 404) if c.nil? (halt 404) if c.nil?
c.to_json content_type content_type_mapping[c.format.to_sym] if content_type_mapping[c.format.to_sym]
#response.headers['Content-Disposition'] = "attachment; filename=#{configname}"
c.body
end end
# GET all configurations # GET all configurations
get '/configurations/?' do get '/configurations/?' do
......
...@@ -2,7 +2,9 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper') ...@@ -2,7 +2,9 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
describe "Using the Application API", :reset_redis => false do describe "Using the Application API", :reset_redis => false do
before(:all) do before(:all) do
Ohm.redis.flushdb
@a = Noah::Application.create(:name => 'rspec_sample_app') @a = Noah::Application.create(:name => 'rspec_sample_app')
@b = Noah::Application.create(:name => 'rspec_sample_app_2')
@c = Noah::Configuration.create(:name => 'rspec_config', :format => 'string', :body => 'rspec is great') @c = Noah::Configuration.create(:name => 'rspec_config', :format => 'string', :body => 'rspec is great')
@a.configurations << @c @a.configurations << @c
@a.save @a.save
...@@ -15,30 +17,39 @@ describe "Using the Application API", :reset_redis => false do ...@@ -15,30 +17,39 @@ describe "Using the Application API", :reset_redis => false do
last_response.should be_ok last_response.should be_ok
response = last_response.should return_json response = last_response.should return_json
response.is_a?(Hash).should == true response.is_a?(Hash).should == true
response.size.should == 2
end end
it "named application should work" do it "named application should work" do
get '/applications/rspec_sample_app' get '/applications/rspec_sample_app'
last_response.should be_ok last_response.should be_ok
response = last_response.should return_json response = last_response.should return_json
response.has_key?(@a.name).should == true response["id"].should == @a.id.to_s
response[@a.name].class.to_s.should == 'Hash' response["name"].should == @a.name
response[@a.name]["id"].should == @a.id.to_s response.has_key?("configurations").should == true
response[@a.name].has_key?("configurations").should == true c = response["configurations"]
c = response[@a.name]["configurations"]
c.has_key?(@c.name).should == true c.has_key?(@c.name).should == true
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
it "named configuration for application should work" do it "named configuration for application should work as JSON" do
get "/applications/#{@a.name}/#{@c.name}" header "Accept", "application/json"
get "/applications/#{@a.name}/configurations/#{@c.name}"
last_response.should be_ok last_response.should be_ok
response = last_response.should return_json response = last_response.should return_json
response["id"].should == @c.id response["id"].should == @c.id
response["name"].should == @c.name response["name"].should == @c.name
response["format"].should == @c.format response["format"].should == @c.format
response["body"].should == @c.body response["body"].should == @c.body
end end
it "named configuration for application should work as raw" do
header "Accept", "application/octet"
get "/applications/#{@a.name}/configurations/#{@c.name}"
last_response.should be_ok
headers = last_response.headers
body = last_response.body
headers["Content-Type"].should == 'text/plain;charset=utf-8'
body.should == @c.body
end
it "invalid application should not work" do it "invalid application should not work" do
get "/applications/should_not_exist" get "/applications/should_not_exist"
last_response.should be_missing last_response.should be_missing
...@@ -64,6 +75,7 @@ describe "Using the Application API", :reset_redis => false do ...@@ -64,6 +75,7 @@ describe "Using the Application API", :reset_redis => false do
Noah::Application.find(:name => @appdata[:name]).size.should == 1 Noah::Application.find(:name => @appdata[:name]).size.should == 1
Noah::Application.find(:name => @appdata[:name]).first.is_new?.should == true Noah::Application.find(:name => @appdata[:name]).first.is_new?.should == true
end end
it "new application with new configuration should work"
it "new application with missing name should not work" do it "new application with missing name should not work" do
put "/applications/should_not_work", '{"foo":"bar"}', "CONTENT_TYPE" => "application/json" put "/applications/should_not_work", '{"foo":"bar"}', "CONTENT_TYPE" => "application/json"
last_response.should be_invalid last_response.should be_invalid
...@@ -80,7 +92,9 @@ describe "Using the Application API", :reset_redis => false do ...@@ -80,7 +92,9 @@ describe "Using the Application API", :reset_redis => false do
response["action"].should == "update" response["action"].should == "update"
Noah::Application.find(:name => @appdata[:name]).size.should == 1 Noah::Application.find(:name => @appdata[:name]).size.should == 1
Noah::Application.find(:name => @appdata[:name]).first.is_new?.should == false Noah::Application.find(:name => @appdata[:name]).first.is_new?.should == false
end end
it "existing application with new configuration"
it "existing application with existing configuration"
end end
describe "DELETE" do describe "DELETE" do
......
...@@ -41,7 +41,8 @@ describe "Using the Configuration API", :reset_redis => true, :populate_sample_d ...@@ -41,7 +41,8 @@ describe "Using the Configuration API", :reset_redis => true, :populate_sample_d
end end
end end
end end
it "named configuration should work" do it "named configuration should work as JSON" do
header "Accept", "application/json"
get '/configurations/redis_url' get '/configurations/redis_url'
last_response.should be_ok last_response.should be_ok
response = last_response.should return_json response = last_response.should return_json
...@@ -55,7 +56,7 @@ describe "Using the Configuration API", :reset_redis => true, :populate_sample_d ...@@ -55,7 +56,7 @@ describe "Using the Configuration API", :reset_redis => true, :populate_sample_d
end end
it "named configuration should work with mime-type" do it "named configuration should work with mime-type" do
require 'yaml' require 'yaml'
get '/configurations/yaml_config/data' get '/configurations/yaml_config'
last_response.should be_ok last_response.should be_ok
last_response.headers["Content-Type"].should == "text/x-yaml;charset=utf-8" last_response.headers["Content-Type"].should == "text/x-yaml;charset=utf-8"
response = YAML.load(last_response.body) response = YAML.load(last_response.body)
......
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