torquebox-backstage 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. data/Gemfile +18 -0
  2. data/Gemfile.lock +69 -0
  3. data/README.md +164 -0
  4. data/Rakefile +32 -0
  5. data/TODO +9 -0
  6. data/TORQUEBOX_VERSION +1 -0
  7. data/VERSION +1 -0
  8. data/backstage.rb +84 -0
  9. data/bin/backstage +78 -0
  10. data/config.ru +3 -0
  11. data/config/torquebox.yml +14 -0
  12. data/lib/apps.rb +18 -0
  13. data/lib/apps/models/app.rb +33 -0
  14. data/lib/apps/routes.rb +18 -0
  15. data/lib/authentication.rb +64 -0
  16. data/lib/destinations.rb +21 -0
  17. data/lib/destinations/models/destination.rb +80 -0
  18. data/lib/destinations/models/message.rb +67 -0
  19. data/lib/destinations/models/queue.rb +33 -0
  20. data/lib/destinations/models/topic.rb +59 -0
  21. data/lib/destinations/routes.rb +44 -0
  22. data/lib/has_mbean.rb +59 -0
  23. data/lib/helpers.rb +142 -0
  24. data/lib/jobs.rb +19 -0
  25. data/lib/jobs/models/job.rb +35 -0
  26. data/lib/jobs/routes.rb +18 -0
  27. data/lib/message_processors.rb +18 -0
  28. data/lib/message_processors/models/message_processor.rb +40 -0
  29. data/lib/message_processors/routes.rb +18 -0
  30. data/lib/pools.rb +18 -0
  31. data/lib/pools/models/pool.rb +51 -0
  32. data/lib/pools/routes.rb +41 -0
  33. data/lib/resource.rb +53 -0
  34. data/lib/resource_helpers.rb +63 -0
  35. data/lib/runtimes.rb +19 -0
  36. data/lib/runtimes/models/job.rb +35 -0
  37. data/lib/runtimes/routes.rb +18 -0
  38. data/lib/services.rb +18 -0
  39. data/lib/services/models/service.rb +35 -0
  40. data/lib/services/routes.rb +17 -0
  41. data/lib/torquebox_managed.rb +36 -0
  42. data/lib/util.rb +33 -0
  43. data/spec/api_spec.rb +136 -0
  44. data/spec/auth_spec.rb +70 -0
  45. data/spec/spec_helper.rb +39 -0
  46. data/views/apps/index.haml +15 -0
  47. data/views/apps/show.haml +12 -0
  48. data/views/css/_mixins.sass +51 -0
  49. data/views/css/html5reset.sass +82 -0
  50. data/views/css/style.sass +152 -0
  51. data/views/destinations/index.haml +37 -0
  52. data/views/destinations/show.haml +18 -0
  53. data/views/jobs/index.haml +23 -0
  54. data/views/jobs/show.haml +13 -0
  55. data/views/layout.haml +31 -0
  56. data/views/message_processors/index.haml +28 -0
  57. data/views/message_processors/show.haml +12 -0
  58. data/views/messages/index.haml +20 -0
  59. data/views/messages/properties.haml +3 -0
  60. data/views/messages/show.haml +19 -0
  61. data/views/pools/index.haml +32 -0
  62. data/views/pools/show.haml +44 -0
  63. data/views/services/index.haml +21 -0
  64. data/views/services/show.haml +13 -0
  65. metadata +289 -0
@@ -0,0 +1,53 @@
1
+ #
2
+ # Copyright 2011 Red Hat, Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ module Backstage
18
+ module Resource
19
+
20
+ def self.included(base)
21
+ base.extend( ClassMethods )
22
+ base.send( :attr_accessor, :parent )
23
+ end
24
+
25
+ def association_chain
26
+ chain = []
27
+ chain << parent if parent
28
+ chain << self
29
+ chain
30
+ end
31
+
32
+ def to_hash
33
+ self.class.to_hash_attributes.inject({ }) do |response, attribute|
34
+ response[attribute] = __send__( attribute )
35
+ response
36
+ end
37
+ end
38
+
39
+ def resource
40
+ self
41
+ end
42
+
43
+ def available_actions
44
+ []
45
+ end
46
+
47
+ module ClassMethods
48
+ def to_hash_attributes
49
+ [:resource]
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,63 @@
1
+ #
2
+ # Copyright 2011 Red Hat, Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ module Backstage
18
+ class Application < Sinatra::Base
19
+ def self.resource(*resources)
20
+ options = resources.pop if resources.last.is_a?(Hash)
21
+ options ||= {}
22
+ resources.each do |resource|
23
+ resource = resource.to_s
24
+ klass = "backstage/#{resource}".constantize
25
+ view_path = options[:view_path] || resource.pluralize
26
+ get "/#{resource.pluralize}" do
27
+ @collection = klass.all
28
+ if html_requested?
29
+ haml :"#{view_path}/index"
30
+ else
31
+ content_type :json
32
+ collection_to_json( @collection )
33
+ end
34
+ end
35
+
36
+ get "/#{resource}/:name" do
37
+ @object = klass.find( Util.decode_name( params[:name] ) )
38
+ if html_requested?
39
+ haml :"#{view_path}/show"
40
+ else
41
+ content_type :json
42
+ object_to_json( @object )
43
+ end
44
+ end
45
+
46
+ (options[:actions] || []).each do |action|
47
+ post "/#{resource}/:name/#{action}" do
48
+ object = klass.find( Util.decode_name( params[:name] ) )
49
+ object.__send__( action )
50
+ if html_requested?
51
+ flash[:notice] = "'#{action}' called on #{simple_class_name( object ).humanize} #{object.name}"
52
+ redirect_to object_path( object )
53
+ else
54
+ content_type :json
55
+ object_to_json( object )
56
+ end
57
+ end
58
+
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,19 @@
1
+ #
2
+ # Copyright 2011 Red Hat, Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ require 'runtimes/models/runtime'
18
+ require 'runtimes/routes'
19
+
@@ -0,0 +1,35 @@
1
+ #
2
+ # Copyright 2011 Red Hat, Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ module Backstage
18
+ class Job
19
+ include HasMBean
20
+ include TorqueBoxManaged
21
+ include Resource
22
+
23
+ def self.filter
24
+ "torquebox.jobs:*"
25
+ end
26
+
27
+ def self.to_hash_attributes
28
+ super + [:name, :app, :app_name, :ruby_class_name, :status, :cron_expression]
29
+ end
30
+
31
+ def available_actions
32
+ status == 'Started' ? %w{stop} : %w{start}
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,18 @@
1
+ #
2
+ # Copyright 2011 Red Hat, Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ Backstage::Application.resource :job, :actions => [:start, :stop]
18
+
@@ -0,0 +1,18 @@
1
+ #
2
+ # Copyright 2011 Red Hat, Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ require 'services/models/service'
18
+ require 'services/routes'
@@ -0,0 +1,35 @@
1
+ #
2
+ # Copyright 2011 Red Hat, Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ module Backstage
18
+ class Service
19
+ include HasMBean
20
+ include TorqueBoxManaged
21
+ include Resource
22
+
23
+ def self.filter
24
+ "torquebox.services:*"
25
+ end
26
+
27
+ def self.to_hash_attributes
28
+ super + [:name, :app, :app_name, :status]
29
+ end
30
+
31
+ def available_actions
32
+ status == 'Started' ? %w{ stop } : %w{ start' }
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,17 @@
1
+ #
2
+ # Copyright 2011 Red Hat, Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ Backstage::Application.resource :service, :actions => [:start, :stop]
@@ -0,0 +1,36 @@
1
+ #
2
+ # Copyright 2011 Red Hat, Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ module Backstage
18
+ module TorqueBoxManaged
19
+ def name
20
+ return mbean.name if mbean.respond_to?( :name )
21
+ $1 if full_name =~ /name=(.*?)(,|$)/
22
+ end
23
+
24
+ def app_name
25
+ $1 if full_name =~ /app=(.*?)(,|$)/
26
+ end
27
+
28
+ def app
29
+ App.find( "torquebox.apps:app=#{app_name}" )
30
+ end
31
+
32
+ def status
33
+ mbean.status.downcase.capitalize
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,33 @@
1
+ #
2
+ # Copyright 2011 Red Hat, Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ require 'base64'
18
+
19
+ module Backstage
20
+ module Util
21
+ class << self
22
+ def encode_name(name)
23
+ #ugh, I'd rather encode a different way, but other attempts
24
+ #seem to break sinatra?
25
+ Base64.encode64( name ).gsub("\n", '')
26
+ end
27
+
28
+ def decode_name(name)
29
+ Base64.decode64( name )
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,136 @@
1
+ #
2
+ # Copyright 2011 Red Hat, Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ require 'spec_helper'
18
+
19
+ module Backstage
20
+
21
+ describe '/api' do
22
+ before(:each) do
23
+ get '/api'
24
+ @response = JSON.parse(last_response.body, :symbolize_names => true)
25
+ end
26
+
27
+ it "should work" do
28
+ last_response.should be_ok
29
+ end
30
+
31
+
32
+ it "should be a hash" do
33
+ @response.is_a?(Hash).should be_true
34
+ end
35
+
36
+ it "should contain a hash of collection urls" do
37
+ collections = [:apps, :queues, :topics, :message_processors, :jobs, :services, :pools]
38
+ @response[:collections].keys.should =~ collections
39
+ collections.each do |collection|
40
+ @response[:collections][collection].should =~ %r{^http://example.org/#{collection}\?format=json$}
41
+ end
42
+ end
43
+
44
+ end
45
+
46
+ describe 'with authentication enabled' do
47
+ before(:each) do
48
+ ENV['REQUIRE_AUTHENTICATION'] = 'true'
49
+ @authenticator = mock(:authenticator)
50
+ TorqueBox::Authentication.stub(:default).and_return(@authenticator)
51
+ end
52
+
53
+ it "api should work with authentication" do
54
+ @authenticator.should_receive(:authenticate).with('blah', 'pw').and_return(true)
55
+ authorize 'blah', 'pw'
56
+ get '/api'
57
+ last_response.should be_ok
58
+ end
59
+
60
+ it "should 401 w/o credentials" do
61
+ get '/api'
62
+ last_response.status.should == 401
63
+ end
64
+
65
+ it "should 401 with invalid credentials" do
66
+ @authenticator.should_receive(:authenticate).with('foo', 'bar').and_return(false)
67
+ authorize 'foo', 'bar'
68
+ get '/api'
69
+ last_response.status.should == 401
70
+ end
71
+
72
+ after(:each) do
73
+ ENV['REQUIRE_AUTHENTICATION'] = nil
74
+ end
75
+ end
76
+
77
+ %w{ app queue topic job message_processor service pool }.each do |resource|
78
+ klass = "backstage/#{resource}".constantize
79
+ describe resource do
80
+ it "should have hash attributes beyond :resource" do
81
+ klass.to_hash_attributes.size.should > 1
82
+ end
83
+
84
+ describe "/#{resource.pluralize}" do
85
+ before(:each) do
86
+ klass.stub(:all).and_return([resource_with_mock_mbean(klass)])
87
+ get "/#{resource.pluralize}", :format => 'json'
88
+ @response = JSON.parse(last_response.body, :symbolize_names => true)
89
+ end
90
+
91
+ it "should work" do
92
+ last_response.should be_ok
93
+ end
94
+
95
+ it "should be an array" do
96
+ @response.is_a?(Array).should be_true
97
+ end
98
+
99
+ context "each item" do
100
+ it "should include the resource" do
101
+ @response.first[:resource].should =~ %r{/#{resource}/.*format=json$}
102
+ end
103
+
104
+ klass.to_hash_attributes.each do |attribute|
105
+ it "should include #{attribute}" do
106
+ @response.first[attribute].should_not be_nil
107
+ end
108
+ end
109
+ end
110
+ end
111
+
112
+ describe "/#{resource}" do
113
+ before(:each) do
114
+ klass.stub(:find).and_return(resource_with_mock_mbean(klass))
115
+ get "/#{resource}/somename", :format => 'json'
116
+ @response = JSON.parse(last_response.body, :symbolize_names => true)
117
+ end
118
+
119
+ it "should work" do
120
+ last_response.should be_ok
121
+ end
122
+
123
+ it "should include the resource" do
124
+ @response[:resource].should =~ %r{/#{resource}/.*format=json$}
125
+ end
126
+
127
+ klass.to_hash_attributes.each do |attribute|
128
+ it "should include #{attribute}" do
129
+ @response[attribute.to_sym].should_not be_nil
130
+ end
131
+ end
132
+ end
133
+ end
134
+
135
+ end
136
+ end