noah 0.0.5-jruby

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,112 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Using the Configuration API", :reset_redis => false, :populate_sample_data => true do
4
+ describe "calling" do
5
+
6
+ describe "GET" do
7
+ it "all configurations should work" do
8
+ get '/c'
9
+ last_response.should be_ok
10
+ last_response.should return_json
11
+ end
12
+ it "named application should work" do
13
+ get '/c/noah'
14
+ last_response.should be_ok
15
+ response = last_response.should return_json
16
+
17
+ response.is_a?(Array).should == true
18
+ response.first["name"].should == "redis"
19
+ response.first["format"].should == "string"
20
+ response.first["body"].should == "redis://127.0.0.1:6379/0"
21
+ response.first["application"].should == "noah"
22
+ end
23
+ it "named configuration for application should work" do
24
+ get '/c/noah/redis'
25
+ last_response.should be_ok
26
+ response = last_response.body
27
+ response.should == "redis://127.0.0.1:6379/0"
28
+ end
29
+ it "named configuration should work with mime-type" do
30
+ require 'yaml'
31
+ get '/c/myrailsapp1/database.yml'
32
+ last_response.should be_ok
33
+ last_response.headers["Content-Type"].should == "text/x-yaml;charset=utf-8"
34
+ response = YAML.load(last_response.body)
35
+ response.is_a?(Hash).should == true
36
+ response.keys.should == ["development"]
37
+ response["development"].keys.should == ["database", "adapter", "username", "password"]
38
+ response["development"].values.should == ["development_database", "mysql", "dev_user", "dev_password"]
39
+ end
40
+ it "invalid application should not work" do
41
+ get '/c/badapp'
42
+ last_response.should be_missing
43
+ end
44
+ it "invalid configuration for application should not work" do
45
+ get '/c/badapp/badconfig'
46
+ last_response.should be_missing
47
+ end
48
+ end
49
+
50
+ describe "PUT" do
51
+ it "new configuration should work" do
52
+ config_data = {:format => "string", :body => "sample_config_entry"}.to_json
53
+ put '/c/newapp/newconfig', config_data, "CONTENT_TYPE" => "application/json"
54
+ last_response.should be_ok
55
+ response = last_response.should return_json
56
+ response["result"].should == "success"
57
+ response["action"].should == "create"
58
+ response["dependencies"].should == "created"
59
+ response["application"].should == "newapp"
60
+ response["item"].should == "newconfig"
61
+ end
62
+ it "existing configuration should work" do
63
+ config_data = {:format => "string", :body => "sample_config_entry"}.to_json
64
+ sleep 3
65
+ put '/c/newapp/newconfig', config_data, "CONTENT_TYPE" => "application/json"
66
+ last_response.should be_ok
67
+ response = last_response.should return_json
68
+ response["result"].should == "success"
69
+ response["action"].should == "update"
70
+ response["dependencies"].should == "updated"
71
+ response["application"].should == "newapp"
72
+ response["item"].should == "newconfig"
73
+ end
74
+ it "new configuration with missing format should not work" do
75
+ config_data = {:body => "a string"}.to_json
76
+ put '/c/newnewapp/someconfig', config_data, "CONTENT_TYPE" => "application/json"
77
+ last_response.should be_invalid
78
+ end
79
+ it "new configuration with missing body should not work" do
80
+ config_data = {:body => "a string"}.to_json
81
+ put '/c/newnewapp/someconfig', config_data, "CONTENT_TYPE" => "application/json"
82
+ last_response.should be_invalid
83
+ end
84
+ end
85
+
86
+ describe "DELETE" do
87
+ before(:all) do
88
+ cparms = {:name => 'a', :format => 'string', :body => 'asdf'}
89
+ @a = Application.create(:name => 'delete_test_app')
90
+ @a.configurations << Configuration.create(cparms)
91
+ @a.save
92
+ @c = @a.configurations.first
93
+ end
94
+
95
+ it "existing configuration should work" do
96
+ delete "/c/#{@a.name}/#{@c.name}"
97
+ last_response.should be_ok
98
+ response = last_response.should return_json
99
+ response["result"].should == "success"
100
+ response["id"].should == @c.id
101
+ response["action"].should == "delete"
102
+ response["application"].should == @a.name
103
+ response["item"].should == @c.name
104
+ end
105
+ it "invalid configuration should not work" do
106
+ delete "/c/#{@a.name}/#{@c.name}"
107
+ last_response.should be_missing
108
+ end
109
+ end
110
+
111
+ end
112
+ end
@@ -0,0 +1,116 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Using the Host API", :reset_redis => false, :populate_sample_data => true do
4
+ describe "calling" do
5
+
6
+ describe "GET" do
7
+ it "all hosts should work" do
8
+ get '/h'
9
+ last_response.should be_ok
10
+ last_response.should return_json
11
+ end
12
+
13
+ it "existing host should work" do
14
+ get '/h/localhost'
15
+ last_response.should be_ok
16
+ response = last_response.should return_json
17
+
18
+ services = response["services"]
19
+
20
+ response["name"].should == "localhost"
21
+ response["status"].should == "up"
22
+ services.size.should == 2
23
+ services.first["name"].should == "redis"
24
+ services.first["status"].should == "up"
25
+ services.first["host"].should == "localhost"
26
+ services.last["name"].should == "noah"
27
+ services.last["status"].should == "up"
28
+ services.last["host"].should == "localhost"
29
+ end
30
+
31
+ it "named service for host should work" do
32
+ get '/h/localhost/noah'
33
+ last_response.should be_ok
34
+ response = last_response.should return_json
35
+
36
+ response["name"].should == "noah"
37
+ response["status"].should == "up"
38
+ response["host"].should == "localhost"
39
+ end
40
+ end
41
+
42
+ describe "PUT" do
43
+ it "new host should work" do
44
+ host_data = {:name => "host99.domain.com", :status => "down"}.to_json
45
+ put '/h/host99.domain.com', host_data, "CONTENT_TYPE" => "application/json"
46
+ last_response.should be_ok
47
+ response = last_response.should return_json
48
+
49
+ response["result"].should == "success"
50
+ response["id"].nil?.should == false
51
+ response["name"].should == "host99.domain.com"
52
+ response["status"].should == "down"
53
+ response["new_record"].should == true
54
+ end
55
+
56
+ it "existing host should work" do
57
+ sleep 3
58
+ host_data = {:name => "host99.domain.com", :status => "pending"}.to_json
59
+ put '/h/host99.domain.com', host_data, "CONTENT_TYPE" => "application/json"
60
+ last_response.should be_ok
61
+ response = last_response.should return_json
62
+
63
+ response["new_record"].should == false
64
+ end
65
+
66
+ it "host missing name parameter should not work" do
67
+ host_data = {:status => "pending"}.to_json
68
+ put '/h/host100.domain.com', host_data, "CONTENT_TYPE" => "application/json"
69
+ last_response.should be_invalid
70
+ end
71
+
72
+ it "host missing status parameter should not work" do
73
+ host_data = {:name => "host100.domain.com"}.to_json
74
+ put '/h/host100.domain.com', host_data, "CONTENT_TYPE" => "application/json"
75
+ last_response.should be_invalid
76
+ end
77
+
78
+ it "host with invalid status parameter should not work" do
79
+ host_data = {:name => "host100.domain.com", :status => "fscked"}.to_json
80
+ put '/h/host100.domain.com', host_data, "CONTENT_TYPE" => "application/json"
81
+ last_response.should_not be_ok
82
+ response = last_response.should return_json
83
+
84
+ response["result"].should == "failure"
85
+ response["error_message"].should == "[[:status, :not_member]]"
86
+ end
87
+ end
88
+
89
+ describe "DELETE" do
90
+ before(:all) do
91
+ @h = Host.create(:name => 'h', :status => 'up')
92
+ sparms = {:name => 's', :status => "up"}
93
+ @h.services << Service.create(sparms.merge({:host => @h}))
94
+ @h.save
95
+ @s = @h.services.first
96
+ end
97
+ it "existing host should work" do
98
+ svc_size = @h.services.size
99
+ delete "/h/#{@h.name}"
100
+ last_response.should be_ok
101
+ response = last_response.should return_json
102
+
103
+ response["result"].should == "success"
104
+ response["id"].should == @h.id
105
+ response["name"].should == @h.name
106
+ response["service_count"].should == svc_size.to_s
107
+ end
108
+
109
+ it "invalid host should not work" do
110
+ delete "/h/#{@h.name}"
111
+ last_response.should be_missing
112
+ end
113
+ end
114
+
115
+ end
116
+ end
@@ -0,0 +1,121 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Using the Service API", :reset_redis => false, :populate_sample_data => true do
4
+ before(:all) do
5
+ @sample_host = {:name => 'rspec_sample_host', :status => 'up'}
6
+ @sample_service = {:name => 'rspec_sample_service', :status => 'up'}
7
+ @h = Host.create(:name => 'rspec_sample_host', :status => 'up')
8
+ @h.services << Service.create({:host => @h}.merge(@sample_service))
9
+ @h.save
10
+ @s = Service.find(@sample_service).first
11
+ end
12
+ describe "calling" do
13
+
14
+ describe "GET" do
15
+ it "all services should work" do
16
+ get '/s'
17
+ last_response.should be_ok
18
+ response = last_response.should return_json
19
+ response.is_a?(Array).should == true
20
+ end
21
+ it "all named services should work" do
22
+ get "/s/#{@sample_service[:name]}"
23
+ last_response.should be_ok
24
+ response = last_response.should return_json
25
+ response.is_a?(Array).should == true
26
+ s = response.first
27
+ s["id"].should == @s.id
28
+ s["name"].should == @s.name
29
+ s["status"].should == @s.status
30
+ s["host"].should == @h.name
31
+ end
32
+ it "named service for host should work" do
33
+ get "/s/#{@sample_service[:name]}/#{@sample_host[:name]}"
34
+ last_response.should be_ok
35
+ response = last_response.should return_json
36
+ response["id"].should == @s.id
37
+ response["name"].should == @s.name
38
+ response["status"].should == @s.status
39
+ response["host"].should == @h.name
40
+ end
41
+ it "missing service for host should not work" do
42
+ get '/s/foobar/baz'
43
+ last_response.should be_missing
44
+ end
45
+ end
46
+
47
+ describe "PUT" do
48
+ before(:all) do
49
+ @payload = {:name => 'another_rspec_service', :status => 'up', :host => @h.name}
50
+ end
51
+ it "new service should work" do
52
+ put "/s/#{@payload[:name]}/", @payload.to_json, "CONTENT_TYPE" => "application/json"
53
+ last_response.should be_ok
54
+ response = last_response.should return_json
55
+ response["result"].should == "success"
56
+ response["action"].should == "create"
57
+ response["id"].nil?.should == false
58
+ response["name"].should == @payload[:name]
59
+ response["host"].should == @payload[:host]
60
+ Service.find(:name => @payload[:name]).size.should == 1
61
+ Service.find(:name => @payload[:name]).first.is_new?.should == true
62
+ end
63
+ it "new service without host should not work" do
64
+ put "/s/foobar", {:name => "foobar", :status => "up"}.to_json, "CONTENT_TYPE" => "application/json"
65
+ last_response.should be_invalid
66
+ end
67
+ it "new service with invalid status should not work" do
68
+ put "/s/foobar", {:name => "foobar", :status => "fsck", :host => @h.name}.to_json, "CONTENT_TYPE" => "application/json"
69
+ last_response.should_not be_ok
70
+ response = last_response.should return_json
71
+ response["error_message"].should == "[[:status, :not_member]]"
72
+ end
73
+ it "new service with missing name should not work" do
74
+ put "/s/foobar", {:status => "fsck", :host => @h.name}.to_json, "CONTENT_TYPE" => "application/json"
75
+ last_response.should be_invalid
76
+ end
77
+ it "new service with missing status should not work" do
78
+ put "/s/foobar", {:name => "foobar", :host => @h.name}.to_json, "CONTENT_TYPE" => "application/json"
79
+ last_response.should be_invalid
80
+ end
81
+ it "existing service should work" do
82
+ sleep 3
83
+ put "/s/#{@payload[:name]}", {:name => @payload[:name], :status => "down", :host => @payload[:host]}.to_json, "CONTENT_TYPE" => "application/json"
84
+ last_response.should be_ok
85
+ response = last_response.should return_json
86
+ response["result"].should == "success"
87
+ response["action"].should == "update"
88
+ response["id"].nil?.should == false
89
+ response["name"].should == @payload[:name]
90
+ response["host"].should == @payload[:host]
91
+ Service.find(:name => @payload[:name]).size.should == 1
92
+ Service.find(:name => @payload[:name]).first.is_new?.should == false
93
+ end
94
+ end
95
+
96
+ describe "DELETE" do
97
+ before(:all) do
98
+ @h = Host.create(:name => "h1", :status => "up")
99
+ @h.services << Service.create(:name => "s1", :status => "up", :host => @h)
100
+ @h.save
101
+ @s = @h.services.first
102
+ end
103
+ it "existing host should work" do
104
+ delete "/s/#{@s.name}/#{@h.name}"
105
+ last_response.should be_ok
106
+ response = last_response.should return_json
107
+
108
+ response["result"].should == "success"
109
+ response["action"].should == "delete"
110
+ response["id"].should == @s.id
111
+ response["host"].should == @h.name
112
+ response["service"].should == @s.name
113
+ end
114
+ it "invalid host should not work" do
115
+ delete "/s/#{@s.name}/#{@h.name}"
116
+ last_response.should be_missing
117
+ end
118
+ end
119
+
120
+ end
121
+ end
@@ -0,0 +1,20 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Noah App Basics", :reset_redis => true do
4
+
5
+ it "should show the index page" do
6
+ get '/'
7
+ last_response.should be_ok
8
+ last_response.body.include?("Noah Start Page").should == true
9
+ end
10
+
11
+ it "should test the 404 message" do
12
+ get '/foo'
13
+ last_response.status.should == 404
14
+ last_response.headers["Content-Type"].should == "application/json"
15
+ response = JSON.parse(last_response.body)
16
+ response["result"].should == "failure"
17
+ response["error_message"].should == "Resource not found"
18
+ end
19
+
20
+ end
@@ -0,0 +1,112 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Noah Service Model", :reset_redis => true do
4
+ describe "should" do
5
+
6
+ it "create a new Service" do
7
+ servicename = "myservice"
8
+ servicestatus = "up"
9
+ hostname = "mytesthost1"
10
+ hoststatus = "up"
11
+ host = Host.create(:name => hostname, :status => hoststatus)
12
+ host.save
13
+ service = Service.create(:name => servicename, :status => servicestatus, :host => host)
14
+ service.valid?.should == true
15
+ service.save
16
+ service.name.should == servicename
17
+ service.status.should == servicestatus
18
+ service.host_id.should == host.id
19
+ host.services[1].name.should == servicename
20
+ end
21
+
22
+ it "create a new Service with find_or_create" do
23
+ host = Host.create(:name => "h1", :status => "up")
24
+ host.save
25
+ service = Service.find_or_create(:name => "s1", :status => "up", :host => host)
26
+ service.save
27
+ service.is_new?.should == true
28
+ end
29
+
30
+ it "update an existing Service with find_or_create" do
31
+ host = Host.create(:name => "h2", :status => "up")
32
+ host.save
33
+ service = Service.find_or_create(:name => "s2", :status => "up", :host => host)
34
+ service.save
35
+ sleep 1
36
+ service2 = Service.find_or_create(:name => "s2", :status => "up", :host => host)
37
+ service2.save
38
+ service2.is_new?.should == false
39
+ end
40
+
41
+ it "delete a Service" do
42
+ h = Host.create(:name => "h1", :status => "up")
43
+ h.save
44
+ s = Service.create(:name => "s1", :status => "up", :host => h)
45
+ s.save
46
+ s = Service.find(:name => "s1").first
47
+ s.delete
48
+ s = Service.find(:name => "s1").first
49
+ s.should == nil
50
+ end
51
+
52
+ it "find multiple Services" do
53
+ h = Host.create(:name => "h1", :status => "up")
54
+ if h.valid?
55
+ h.services << Service.create(:name => "s1", :status => "up", :host => h)
56
+ h.services << Service.create(:name => "s2", :status => "up", :host => h)
57
+ h.save
58
+ end
59
+ Services.all.size.should == 2
60
+ Services.all.first.name.should == "s1"
61
+ Services.all.last.name.should == "s2"
62
+ end
63
+
64
+ end
65
+
66
+ describe "should not" do
67
+
68
+ it "create a new Service when missing a Host" do
69
+ servicename = "myservice1"
70
+ servicestatus = "up"
71
+ service = Service.create(:name => servicename, :status => servicestatus)
72
+ service.valid?.should == false
73
+ service.errors.should == [[:host_id, :not_present]]
74
+ end
75
+
76
+ it "create a new Service when missing a name" do
77
+ host = Host.create(:name => "host1.domain.com", :status => "up")
78
+ host.save
79
+ service = Service.create(:status => "up", :host => host)
80
+ service.valid?.should == false
81
+ service.errors.should == [[:name, :not_present]]
82
+ end
83
+
84
+ it "create a new Service when missing a status" do
85
+ host = Host.create(:name => "host1.domain.com", :status => "up")
86
+ host.save
87
+ service = Service.create(:name => 'foo', :host => host)
88
+ service.valid?.should == false
89
+ service.errors.should == [[:status, :not_present], [:status, :not_member]]
90
+ end
91
+
92
+ it "create a new Service with an invalid status" do
93
+ host = Host.create(:name => "host1.domain.com", :status => "up")
94
+ host.save
95
+ service = Service.create(:name => "myservice", :status => "invalid_status", :host => host)
96
+ service.valid?.should == false
97
+ service.errors.should == [[:status, :not_member]]
98
+ end
99
+
100
+ it "create a duplicate Service" do
101
+ host = Host.create(:name => "host1.domain.com", :status => "up")
102
+ host.save
103
+ s = Service.create(:name => "myservice", :status => "up", :host => host)
104
+ s.save
105
+ s1 = Service.create(:name => "myservice", :status => "up", :host => host)
106
+ s1.valid?.should == false
107
+ s1.errors.should == [[[:name, :host_id], :not_unique]]
108
+ end
109
+
110
+ end
111
+
112
+ end
@@ -0,0 +1,105 @@
1
+ require 'bundler/setup'
2
+ require 'ohm'
3
+ begin
4
+ require 'yajl'
5
+ rescue LoadError
6
+ require 'json'
7
+ end
8
+
9
+ ENV['RACK_ENV'] = 'test'
10
+ ENV['REDIS_URL'] = 'redis://localhost:6379/3'
11
+ Ohm::connect
12
+
13
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'noah')
14
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'noah', 'app')
15
+ require 'rspec'
16
+ require 'rack/test'
17
+
18
+ RSpec.configure do |config|
19
+ config.color_enabled = true
20
+ config.formatter = "documentation"
21
+ config.before(:each, :reset_redis => true) { Ohm::redis.flushdb }
22
+ config.after(:each, :reset_redis => true) {Ohm::redis.flushdb }
23
+ config.after(:all, :populate_sample_data => true) {Ohm::redis.flushdb }
24
+ config.before(:all, :populate_sample_data => true) do
25
+ Ohm::redis.flushdb
26
+ h = Host.create(:name => 'localhost', :status => "up")
27
+ if h.save
28
+ %w[redis noah].each do |service|
29
+ s = Service.create(:name => service, :status => "up", :host => h)
30
+ h.services << s
31
+ end
32
+ end
33
+
34
+ a = Application.create(:name => 'noah')
35
+ if a.save
36
+ cr = Configuration.create(:name => 'redis', :format => 'string', :body => 'redis://127.0.0.1:6379/0', :application => a)
37
+ ch = Configuration.create(:name => 'host', :format => 'string', :body => 'localhost', :application => a)
38
+ cp = Configuration.create(:name => 'port', :format => 'string', :body => '9292', :application => a)
39
+ %w[cr ch cp].each do |c|
40
+ a.configurations << eval(c)
41
+ end
42
+ end
43
+
44
+ my_yaml = <<EOY
45
+ development:
46
+ database: development_database
47
+ adapter: mysql
48
+ username: dev_user
49
+ password: dev_password
50
+ EOY
51
+ my_json = <<EOJ
52
+ {
53
+ "id":"hostname",
54
+ "data":"localhost"
55
+ }
56
+ EOJ
57
+
58
+ a1 = Application.create(:name => 'myrailsapp1')
59
+ if a1.save
60
+ c1 = Configuration.create(:name => 'database.yml', :format => 'yaml', :body => my_yaml, :application => a1)
61
+ a1.configurations << c1
62
+ end
63
+
64
+ a2 = Application.create(:name => 'myrestapp1')
65
+ if a2.save
66
+ c2 = Configuration.create(:name => 'config.json', :format => 'json', :body => my_json, :application => a2)
67
+ a2.configurations << c2
68
+ end
69
+ end
70
+ config.include Rack::Test::Methods
71
+ end
72
+
73
+ def app
74
+ Noah::App
75
+ end
76
+
77
+ RSpec::Matchers.define :return_json do
78
+ match do |last_response|
79
+ last_response.headers["Content-Type"].should == "application/json"
80
+ response = JSON.parse(last_response.body)
81
+ end
82
+
83
+ failure_message_for_should do
84
+ "Response was not valid JSON"
85
+ end
86
+ end
87
+
88
+ RSpec::Matchers.define :be_missing do
89
+ match do |last_response|
90
+ last_response.headers["Content-Type"].should == "application/json"
91
+ last_response.status.should == 404
92
+ response = JSON.parse(last_response.body)
93
+ response["result"].should == "failure"
94
+ response["error_message"].should == "Resource not found"
95
+ end
96
+ end
97
+
98
+ RSpec::Matchers.define :be_invalid do
99
+ match do |last_response|
100
+ last_response.headers["Content-Type"].should == "application/json"
101
+ response = JSON.parse(last_response.body)
102
+ response["result"].should == "failure"
103
+ response["error_message"].should == "Missing Parameters"
104
+ end
105
+ end
data/views/200.erb ADDED
@@ -0,0 +1 @@
1
+ <%= {:status => "success"}.merge(api_call_results).to_json %>
data/views/404.erb ADDED
@@ -0,0 +1 @@
1
+ {"result":"failure","error_message":"Resource not found"}
data/views/500.erb ADDED
@@ -0,0 +1 @@
1
+ {"result":"failure","error_message":"<%= request.env['sinatra.error'].message %>"}
data/views/index.haml ADDED
@@ -0,0 +1,49 @@
1
+ %html
2
+ %head
3
+ %title Noah Start Page
4
+
5
+ #header
6
+ %h1 Sample links
7
+ #header
8
+ %h2 Hosts
9
+ %ul
10
+ %li
11
+ %a{:href => "/h/"} All registered Hosts
12
+ %li
13
+ %a{:href => "/h/localhost"} localhost (this server)
14
+ %li
15
+ %a{:href => "/h/localhost/noah"} localhost noah service
16
+ #header
17
+ %h2 Services
18
+ %ul
19
+ %li
20
+ %a{:href => "/s/"} All registered Services
21
+ %li
22
+ %a{:href => "/s/http"} All hosts providing 'http'
23
+ %li
24
+ %a{:href => "/s/noah/localhost"} localhost noah service
25
+ #header
26
+ %h2 Applications
27
+ %ul
28
+ %li
29
+ %a{:href => "/a/"} All registered Applications
30
+ %li
31
+ %a{:href => "/a/noah"} Noah Application entry
32
+ %li
33
+ %a{:href => "/a/noah/redis"} Noah Redis configuration entry
34
+ #header
35
+ %h2 Configurations
36
+ %ul
37
+ %li
38
+ %a{:href => "/c/"} All registered Configurations
39
+ %li
40
+ %a{:href => "/c/noah"} Noah Configuration entry
41
+ %li
42
+ %a{:href => "/c/myrailsapp1"} myrailsapp1 Configuration entry
43
+ %li
44
+ %a{:href => "/c/myrestapp1"} myrestapp1 Configuration entry
45
+ %li
46
+ %a{:href => "/c/myrailsapp1/database.yml"} database.yml file for myrailsapp1 (should return the proper content-type)
47
+ %li
48
+ %a{:href => "/c/myrestapp1/config.json"} config.json file for myrestapp1
49
+