From: Tomas Sedovic <tsedovic(a)redhat.com>
https://www.aeolusproject.org/redmine/issues/2694
This will allow Pacemaker Cloud to register with Conductor. Conductor will
then be able to send Pacemaker Cloud notifications about instance and
deployable lifetime.
See this wiki page for the notification API spec:
https://www.aeolusproject.org/redmine/projects/aeolus/wiki/Pacemaker_Clou...
Note that the remaining parts of the API are not in scope for 1.0.
---
aeolus-conductor.spec.in | 1 +
src/app/controllers/api/hooks_controller.rb | 74 +++++++
src/app/models/hook.rb | 4 +
src/app/views/api/hooks/_hook.xml.haml | 4 +
src/app/views/api/hooks/index.xml.haml | 4 +
src/app/views/api/hooks/show.xml.haml | 2 +
src/config/routes.rb | 2 +
src/db/migrate/20111101162621_create_hooks.rb | 14 ++
src/spec/controllers/api/hooks_controller_spec.rb | 218 +++++++++++++++++++++
src/spec/factories/hook.rb | 26 +++
10 files changed, 349 insertions(+), 0 deletions(-)
create mode 100644 src/app/controllers/api/hooks_controller.rb
create mode 100644 src/app/models/hook.rb
create mode 100644 src/app/views/api/hooks/_hook.xml.haml
create mode 100644 src/app/views/api/hooks/index.xml.haml
create mode 100644 src/app/views/api/hooks/show.xml.haml
create mode 100644 src/db/migrate/20111101162621_create_hooks.rb
create mode 100644 src/spec/controllers/api/hooks_controller_spec.rb
create mode 100644 src/spec/factories/hook.rb
diff --git a/aeolus-conductor.spec.in b/aeolus-conductor.spec.in
index 6bdcd9c..0de52b6 100644
--- a/aeolus-conductor.spec.in
+++ b/aeolus-conductor.spec.in
@@ -141,6 +141,7 @@ haml="app/views/hardware_profiles app/views/realm_mappings \
app/views/catalog_entries app/views/catalogs \
app/views/provider_types app/views/api/images \
app/views/config_servers \
+ app/views/api/hooks \
app/views/api/builds app/views/api/provider_images \
app/views/api/target_images app/views/api/entrypoint"
html="public"
diff --git a/src/app/controllers/api/hooks_controller.rb
b/src/app/controllers/api/hooks_controller.rb
new file mode 100644
index 0000000..6e18978
--- /dev/null
+++ b/src/app/controllers/api/hooks_controller.rb
@@ -0,0 +1,74 @@
+#
+# Copyright (C) 2011 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at
http://www.gnu.org/copyleft/gpl.html.
+
+# Filters added to this controller apply to all controllers in the application.
+# Likewise, all the methods added will be available for all controllers.
+
+module Api
+ class HooksController < ApplicationController
+ before_filter :require_user_api
+ rescue_from ActiveRecord::RecordNotFound, :with => :not_found
+
+ respond_to :xml
+ layout :false
+
+ def index
+ @hooks = Hook.all
+ respond_with(@hooks)
+ end
+
+ def show
+ @hook = Hook.find(params[:id])
+ respond_with(@hook)
+ end
+
+ def create
+ unless params[:hook]
+ head :status => 400 and return
+ end
+
+ version = params[:hook][:version]
+ unless version == '1'
+ head :status => 501 and return
+ end
+
+ @hook = Hook.new params[:hook]
+ if @hook.save
+ render 'show', :status => :created, :location =>
api_hook_url(@hook)
+ else
+ head :status => 400
+ end
+ end
+
+ def destroy
+ hook = Hook.find(params[:id])
+
+ if hook.destroy
+ head :status => 204
+ else
+ head :status => 500
+ end
+ end
+
+ private
+ def not_found
+ head :status => :not_found
+ end
+
+ end
+end
diff --git a/src/app/models/hook.rb b/src/app/models/hook.rb
new file mode 100644
index 0000000..1fde850
--- /dev/null
+++ b/src/app/models/hook.rb
@@ -0,0 +1,4 @@
+class Hook < ActiveRecord::Base
+ validates_presence_of :uri
+ validates_presence_of :version
+end
diff --git a/src/app/views/api/hooks/_hook.xml.haml
b/src/app/views/api/hooks/_hook.xml.haml
new file mode 100644
index 0000000..af19cfc
--- /dev/null
+++ b/src/app/views/api/hooks/_hook.xml.haml
@@ -0,0 +1,4 @@
+!!!XML
+%hook{:id => hook.id, :href => api_hook_url(hook.id) }
+ %uri= hook.uri
+ %version= hook.version
diff --git a/src/app/views/api/hooks/index.xml.haml
b/src/app/views/api/hooks/index.xml.haml
new file mode 100644
index 0000000..94046b9
--- /dev/null
+++ b/src/app/views/api/hooks/index.xml.haml
@@ -0,0 +1,4 @@
+!!!XML
+%hooks
+ - @hooks.each do |hook|
+ = render :partial => 'hook', :locals => {:hook => hook}
diff --git a/src/app/views/api/hooks/show.xml.haml
b/src/app/views/api/hooks/show.xml.haml
new file mode 100644
index 0000000..1c091c7
--- /dev/null
+++ b/src/app/views/api/hooks/show.xml.haml
@@ -0,0 +1,2 @@
+!!! XML
+= render :partial => "hook", :locals => {:hook => @hook}
diff --git a/src/config/routes.rb b/src/config/routes.rb
index dfba2a7..c11c216 100644
--- a/src/config/routes.rb
+++ b/src/config/routes.rb
@@ -207,6 +207,8 @@ Conductor::Application.routes.draw do
resources :provider_images
# :except => [:new, :edit]
+
+ resources :hooks
end
scope "/api" do
diff --git a/src/db/migrate/20111101162621_create_hooks.rb
b/src/db/migrate/20111101162621_create_hooks.rb
new file mode 100644
index 0000000..022807c
--- /dev/null
+++ b/src/db/migrate/20111101162621_create_hooks.rb
@@ -0,0 +1,14 @@
+class CreateHooks < ActiveRecord::Migration
+ def self.up
+ create_table :hooks do |t|
+ t.string :uri
+ t.string :version
+
+ t.timestamps
+ end
+ end
+
+ def self.down
+ drop_table :hooks
+ end
+end
diff --git a/src/spec/controllers/api/hooks_controller_spec.rb
b/src/spec/controllers/api/hooks_controller_spec.rb
new file mode 100644
index 0000000..3f1f0ce
--- /dev/null
+++ b/src/spec/controllers/api/hooks_controller_spec.rb
@@ -0,0 +1,218 @@
+#
+# Copyright (C) 2011 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at
http://www.gnu.org/copyleft/gpl.html.
+
+require 'spec_helper'
+
+describe Api::HooksController do
+ render_views
+
+ context "when authenticated as admin" do
+
+ before(:each) do
+ send_and_accept_xml
+ @admin_permission = FactoryGirl.create :admin_permission
+ @admin = @admin_permission.user
+ mock_warden(@admin)
+ end
+
+ describe "#index" do
+
+ context "when there are no hooks" do
+
+ before(:each) do
+ get :index
+ end
+
+ it { response.should be_success }
+ it { response.headers['Content-Type'].should
include("application/xml") }
+ it "should have no hooks" do
+ resp = Hash.from_xml(response.body)
+ resp['hooks']['hooks'].should be_nil
+ end
+
+ end
+
+ context "when there are 2 hooks" do
+
+ before(:each) do
+ @hooks = []
+ @hooks << Factory.create(:hook)
+ @hooks << Factory.create(:hook, :uri =>
'https://pcloud.org/events')
+ get :index
+ end
+
+ it { response.should be_success }
+ it { response.headers['Content-Type'].should
include("application/xml") }
+ it "should have hooks with correct attributes" do
+ resp = Hash.from_xml(response.body)
+ hooks = resp['hooks']['hook']
+
+ hooks.should have(2).things
+ hooks.first['uri'].should == @hooks.first.uri
+ hooks.last['uri'].should == @hooks.last.uri
+ end
+ end
+ end
+
+
+
+ describe "#show" do
+ context "when there are no hooks" do
+ before(:each) do
+ get :show, :id => 5
+ end
+
+ it { response.should_not be_success }
+ it { response.headers['Content-Type'].should
include("application/xml") }
+
+ it "should return 404" do
+ response.status.should == 404
+ end
+
+ end
+
+ context "when there is 1 hook" do
+ before(:each) do
+ @hook = Factory.create(:hook)
+ end
+
+ it "should return the requested hook" do
+ get :show, :id => @hook.id
+
+ response.should be_success
+ response.headers['Content-Type'].should
include("application/xml")
+
+ resp = Hash.from_xml(response.body)
+ hook = resp['hook']
+ hook.should_not be_blank
+ hook['uri'].should == @hook.uri
+ hook['version'].should == @hook.version
+ end
+
+ it "should return 404 for nonexistent hook" do
+ get :show, :id => 52983
+
+ response.status.should == 404
+ response.headers['Content-Type'].should
include("application/xml")
+ end
+ end
+ end
+
+ describe "#create" do
+
+ it "should return 501 for unknown version" do
+ post :create, :hook => Factory.attributes_for(:hook, :version =>
'273')
+ response.status.should == 501
+ end
+
+ it "should return 501 for missing version" do
+ post :create, :hook => Factory.attributes_for(:hook, :version => nil)
+ response.status.should == 501
+ end
+
+ it "should return 400 for missing data" do
+ post :create
+ response.status.should == 400
+ end
+
+ it "should return 400 for invalid hook data" do
+ post :create, :hook => Factory.attributes_for(:hook, :uri => nil)
+ response.status.should == 400
+
+ post :create, :hook => Factory.attributes_for(:hook, :uri => '')
+ response.status.should == 400
+ end
+
+ it "should register a new hook" do
+ new_hook = Factory.attributes_for(:hook)
+ post :create, :hook => new_hook
+
+ response.should be_success
+ response.headers['Content-Type'].should
include("application/xml")
+ response.headers['Location'].should include("/api/hooks/")
+
+ resp = Hash.from_xml(response.body)
+ hook = resp['hook']
+ hook.should_not be_blank
+ hook['uri'].should == new_hook[:uri]
+ end
+
+ end
+
+ describe "#destroy" do
+ context "when there are no hooks" do
+ before(:each) do
+ delete :destroy, :id => 29830
+ end
+
+ it { response.should_not be_success }
+ it { response.headers['Content-Type'].should
include("application/xml") }
+
+ it "should return 404" do
+ response.status.should == 404
+ end
+ end
+
+ context "when there is 1 hook" do
+ before(:each) do
+ @hook = Factory.create(:hook)
+ end
+
+ it "should delete requested hook" do
+ delete :destroy, :id => @hook.id
+ response.status.should == 204
+ end
+
+ it "should return 404 for nonexistent hook" do
+ delete :destroy, :id => 52983
+ response.status.should == 404
+ end
+ end
+ end
+ end
+
+ context "when not logged in" do
+
+ before(:each) do
+ send_and_accept_xml
+ @hook = Factory.create(:hook)
+ mock_warden(nil)
+ end
+
+ it "index should return 401" do
+ get :index
+ response.status.should == 401
+ end
+
+ it "show should return 401" do
+ get :show, :id => @hook.id
+ response.status.should == 401
+ end
+
+ it "create should return 401" do
+ post :create, :hook => Factory.create(:hook)
+ response.status.should == 401
+ end
+
+ it "destroy should return 401" do
+ delete :destroy, :id => @hook.id
+ response.status.should == 401
+ end
+ end
+
+end
diff --git a/src/spec/factories/hook.rb b/src/spec/factories/hook.rb
new file mode 100644
index 0000000..a6c2437
--- /dev/null
+++ b/src/spec/factories/hook.rb
@@ -0,0 +1,26 @@
+#
+# Copyright (C) 2011 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at
http://www.gnu.org/copyleft/gpl.html.
+
+FactoryGirl.define do
+
+ factory :hook do
+ uri 'http://example.com'
+ version '1'
+ end
+
+end
--
1.7.6.4