noah 0.2.1 → 0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,6 @@
1
1
  module Noah
2
2
  class Ephemeral < Model
3
+ include EphemeralValidations
3
4
 
4
5
  attribute :path
5
6
  attribute :data
@@ -11,6 +12,7 @@ module Noah
11
12
  super
12
13
  assert_present :path
13
14
  assert_unique :path
15
+ assert_not_reserved
14
16
  end
15
17
 
16
18
  def name
@@ -0,0 +1,45 @@
1
+ require File.join(File.dirname(__FILE__), 'link_member')
2
+ module Noah
3
+ class Link < Model
4
+ attribute :path
5
+ list :nodes, LinkMember
6
+
7
+ index :path
8
+
9
+ def validate
10
+ super
11
+ assert_present :path
12
+ end
13
+ # Nothing to see yet.
14
+ # This will be for creating "overlays" or "link" relationships
15
+ # between arbitrary objects or modeling your data the way you want.
16
+ #
17
+ # Example:
18
+ # path = "/myservers"
19
+ # path.nodes = ["/applications/myapp","/some/ephemeral/path", "sometag"]
20
+ #
21
+ # would result in a structure like:
22
+ # path/
23
+ # applications/
24
+ # myapp
25
+ # some/ephemeral/path/
26
+ # child1
27
+ # child2
28
+ # child3
29
+ # sometag/
30
+ # tagged_item1
31
+ # tagged_item2
32
+ # tagged_item4
33
+ # tagged_item5
34
+ #
35
+ # The idea is to create a blended view across opinionated, tagged and
36
+ # ephemeral nodes.
37
+ #
38
+ # Almost a "choose your own model" thing.
39
+
40
+ def name
41
+ @name = path
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,18 @@
1
+ module Noah
2
+ class LinkMember
3
+
4
+ class <<self
5
+ def create(path)
6
+ path_to_instance(path)
7
+ end
8
+
9
+ protected
10
+ def path_to_instance(path)
11
+ p = path.split('/')
12
+ model, name = p[1], p[2]
13
+ x = instance_eval(Noah::PATH_MAPPING[model])
14
+ x.find(:name => name).first
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,14 @@
1
+ module Noah
2
+ class Tag < Model
3
+ counter :total
4
+
5
+ def name
6
+ @name = id
7
+ end
8
+
9
+ def self.[](id)
10
+ super(encode(id)) || create(:id => encode(id))
11
+ end
12
+ end
13
+
14
+ end
@@ -1,8 +1,6 @@
1
1
  require 'digest/sha1'
2
2
  module Noah
3
- class Watcher < Model #NYI
4
- # Don't trust anything in here yet
5
- # I'm still trying a few things
3
+ class Watcher < Model
6
4
  include WatcherValidations
7
5
 
8
6
  attribute :pattern
@@ -2,7 +2,7 @@ class Noah::App
2
2
  # Service URIs
3
3
 
4
4
  # get named {Service} for named {Host}
5
- get '/s/:servicename/:hostname/?' do |servicename, hostname|
5
+ get '/services/:servicename/:hostname/?' do |servicename, hostname|
6
6
  hs = host_service(hostname, servicename)
7
7
  if hs.nil?
8
8
  halt 404
@@ -11,7 +11,7 @@ class Noah::App
11
11
  end
12
12
  end
13
13
 
14
- get '/s/:servicename/?' do |servicename|
14
+ get '/services/:servicename/?' do |servicename|
15
15
  s = services(:name => servicename)
16
16
  s.map {|x| x.to_hash}
17
17
  if s.empty?
@@ -21,7 +21,7 @@ class Noah::App
21
21
  end
22
22
  end
23
23
 
24
- get '/s/?' do
24
+ get '/services/?' do
25
25
  if services.empty?
26
26
  halt 404
27
27
  else
@@ -30,7 +30,7 @@ class Noah::App
30
30
  end
31
31
  end
32
32
 
33
- put '/s/:servicename/watch' do |servicename|
33
+ put '/services/:servicename/watch' do |servicename|
34
34
  required_params = ["endpoint"]
35
35
  data = JSON.parse(request.body.read)
36
36
  (data.keys.sort == required_params.sort) ? (s = Noah::Service.find(:name => servicename).first) : (raise "Missing Parameters")
@@ -38,7 +38,7 @@ class Noah::App
38
38
  w.to_json
39
39
  end
40
40
 
41
- put '/s/:servicename/?' do |servicename|
41
+ put '/services/:servicename/?' do |servicename|
42
42
  required_params = ["status", "host", "name"]
43
43
  data = JSON.parse(request.body.read)
44
44
  if data.keys.sort == required_params.sort
@@ -57,7 +57,7 @@ class Noah::App
57
57
  end
58
58
  end
59
59
 
60
- delete '/s/:servicename/:hostname/?' do |servicename, hostname|
60
+ delete '/services/:servicename/:hostname/?' do |servicename, hostname|
61
61
  host = Noah::Host.find(:name => hostname).first || (halt 404)
62
62
  service = Noah::Service.find(:name => servicename, :host_id => host.id).first || (halt 404)
63
63
  if host && service
@@ -1 +1,2 @@
1
1
  require File.join(File.dirname(__FILE__), 'validations','watcher_validations')
2
+ require File.join(File.dirname(__FILE__), 'validations','ephemeral_validations')
@@ -0,0 +1,20 @@
1
+ module Noah
2
+ module EphemeralValidations
3
+
4
+ def assert_not_reserved(error = [:path, :reserved_path])
5
+ # This is to work around how Ohm evaluates validations
6
+ # Allows assert_present :path to override
7
+ return if self.path.nil?
8
+ # This is the real test
9
+ self.instance_of?(Noah::Ephemeral) ? (assert valid_path?, error) : (assert false, "Validation not applicable")
10
+ end
11
+
12
+ private
13
+ def valid_path?
14
+ PROTECTED_PATHS.member?(self.path.split("/")[1]) ? (return false) : (return true)
15
+ rescue ArgumentError
16
+ return false
17
+ end
18
+
19
+ end
20
+ end
data/lib/noah/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Noah
2
- VERSION = "0.2.1"
2
+ VERSION = "0.3"
3
3
  end
@@ -1,11 +1,11 @@
1
1
  class Noah::App
2
2
 
3
- get '/w/:name' do |name|
3
+ get '/watches/:name' do |name|
4
4
  w = Noah::Watcher.find_by_name(name)
5
5
  w.nil? ? (halt 404) : w.to_json
6
6
  end
7
7
 
8
- get '/w/?' do
8
+ get '/watches/?' do
9
9
  w = Noah::Watcher.all.sort_by(:pattern)
10
10
  if w.size == 0
11
11
  halt 404
@@ -14,7 +14,7 @@ class Noah::App
14
14
  end
15
15
  end
16
16
 
17
- put '/w/?' do
17
+ put '/watches/?' do
18
18
  required_params = %w[endpoint pattern]
19
19
  data = JSON.parse(request.body.read)
20
20
  (data.keys.sort == required_params.sort) ? (pattern, endpoint = data['pattern'],data['endpoint']) : (raise "Missing Parameters")
@@ -28,7 +28,7 @@ class Noah::App
28
28
  end
29
29
  end
30
30
 
31
- delete '/w/?' do
31
+ delete '/watches/?' do
32
32
  required_params = %w[endpoint pattern]
33
33
  data = JSON.parse(request.body.read)
34
34
  (data.keys.sort == required_params.sort) ? (pattern, endpoint = data['pattern'],data['endpoint']) : (raise "Missing Parameters")
data/noah.gemspec CHANGED
@@ -26,7 +26,7 @@ Gem::Specification.new do |s|
26
26
  s.add_dependency("nest", ["= 1.1.0"])
27
27
  s.add_dependency("rack", ["= 1.2.1"])
28
28
  s.add_dependency("tilt", ["= 1.2.2"])
29
- s.add_dependency("sinatra", ["= 1.1.2"])
29
+ s.add_dependency("sinatra", ["= 1.2.0"])
30
30
  s.add_dependency("ohm", ["= 0.1.3"])
31
31
  s.add_dependency("ohm-contrib", ["= 0.1.1"])
32
32
  s.add_dependency("haml", ["= 3.0.25"])
@@ -42,6 +42,12 @@ describe "Using the Ephemeral Model", :reset_redis => true do
42
42
  @good_ephemeral.delete
43
43
  Noah::Ephemeral[@good_ephemeral.id].should == nil
44
44
  end
45
+ it "should allow reserved keywords as subpaths" do
46
+ Noah::PROTECTED_PATHS.each do |path|
47
+ e = Noah::Ephemeral.new :path => "/this/should/be/#{path}"
48
+ e.valid?.should == true
49
+ end
50
+ end
45
51
  end
46
52
  describe "should not" do
47
53
  it "create a new Noah::Ephemeral with missing path" do
@@ -55,5 +61,12 @@ describe "Using the Ephemeral Model", :reset_redis => true do
55
61
  f.valid?.should == false
56
62
  f.errors.should == [[:path, :not_unique]]
57
63
  end
64
+ it "allow a reserved keyword as a path" do
65
+ Noah::PROTECTED_PATHS.each do |path|
66
+ e = Noah::Ephemeral.new :path => "/#{path}"
67
+ e.valid?.should == false
68
+ e.errors.should == [[:path, :reserved_path]]
69
+ end
70
+ end
58
71
  end
59
72
  end
@@ -11,13 +11,13 @@ describe "Using the Application API", :reset_redis => false do
11
11
 
12
12
  describe "GET" do
13
13
  it "all applications should work" do
14
- get '/a'
14
+ get '/applications'
15
15
  last_response.should be_ok
16
16
  response = last_response.should return_json
17
17
  response.is_a?(Array).should == true
18
18
  end
19
19
  it "named application should work" do
20
- get '/a/rspec_sample_app'
20
+ get '/applications/rspec_sample_app'
21
21
  last_response.should be_ok
22
22
  response = last_response.should return_json
23
23
 
@@ -30,7 +30,7 @@ describe "Using the Application API", :reset_redis => false do
30
30
  c["format"].should == @c.format
31
31
  end
32
32
  it "named configuration for application should work" do
33
- get "/a/#{@a.name}/#{@c.name}"
33
+ get "/applications/#{@a.name}/#{@c.name}"
34
34
  last_response.should be_ok
35
35
  response = last_response.should return_json
36
36
 
@@ -41,11 +41,11 @@ describe "Using the Application API", :reset_redis => false do
41
41
  response["application"].should == @a.name
42
42
  end
43
43
  it "invalid application should not work" do
44
- get "/a/should_not_exist"
44
+ get "/applications/should_not_exist"
45
45
  last_response.should be_missing
46
46
  end
47
47
  it "invalid configuration for application should not work" do
48
- get "/a/should_not_exist/should_not_exist"
48
+ get "/applications/should_not_exist/should_not_exist"
49
49
  last_response.should be_missing
50
50
  end
51
51
  end
@@ -55,7 +55,7 @@ describe "Using the Application API", :reset_redis => false do
55
55
  @appdata = {:name => "should_now_exist"}
56
56
  end
57
57
  it "new application should work" do
58
- put "/a/#{@appdata[:name]}", @appdata.to_json, "CONTENT_TYPE" => "application/json"
58
+ put "/applications/#{@appdata[:name]}", @appdata.to_json, "CONTENT_TYPE" => "application/json"
59
59
  last_response.should be_ok
60
60
  response = last_response.should return_json
61
61
  response["result"].should == "success"
@@ -66,13 +66,13 @@ describe "Using the Application API", :reset_redis => false do
66
66
  Noah::Application.find(:name => @appdata[:name]).first.is_new?.should == true
67
67
  end
68
68
  it "new application with missing name should not work" do
69
- put "/a/should_not_work", '{"foo":"bar"}', "CONTENT_TYPE" => "application/json"
69
+ put "/applications/should_not_work", '{"foo":"bar"}', "CONTENT_TYPE" => "application/json"
70
70
  last_response.should be_invalid
71
71
  end
72
72
  it "existing application should work" do
73
73
  sleep 3
74
74
 
75
- put "/a/#{@appdata[:name]}", @appdata.to_json, "CONTENT_TYPE" => "application/json"
75
+ put "/applications/#{@appdata[:name]}", @appdata.to_json, "CONTENT_TYPE" => "application/json"
76
76
  last_response.should be_ok
77
77
  response = last_response.should return_json
78
78
  response["result"].should == "success"
@@ -89,7 +89,7 @@ describe "Using the Application API", :reset_redis => false do
89
89
  @appdata = {:name => "should_now_exist"}
90
90
  end
91
91
  it "existing application should work" do
92
- delete "/a/#{@appdata[:name]}"
92
+ delete "/applications/#{@appdata[:name]}"
93
93
  last_response.should be_ok
94
94
  response = last_response.should return_json
95
95
  response["result"].should == "success"
@@ -99,7 +99,7 @@ describe "Using the Application API", :reset_redis => false do
99
99
  response["configurations"].should == "0"
100
100
  end
101
101
  it "invalid application should not work" do
102
- delete "/a/should_not_work"
102
+ delete "/applications/should_not_work"
103
103
  last_response.should be_missing
104
104
  end
105
105
  end
@@ -5,12 +5,12 @@ describe "Using the Configuration API", :reset_redis => false, :populate_sample_
5
5
 
6
6
  describe "GET" do
7
7
  it "all configurations should work" do
8
- get '/c'
8
+ get '/configurations'
9
9
  last_response.should be_ok
10
10
  last_response.should return_json
11
11
  end
12
12
  it "named application should work" do
13
- get '/c/noah'
13
+ get '/configurations/noah'
14
14
  last_response.should be_ok
15
15
  response = last_response.should return_json
16
16
 
@@ -21,14 +21,14 @@ describe "Using the Configuration API", :reset_redis => false, :populate_sample_
21
21
  response.first["application"].should == "noah"
22
22
  end
23
23
  it "named configuration for application should work" do
24
- get '/c/noah/redis'
24
+ get '/configurations/noah/redis'
25
25
  last_response.should be_ok
26
26
  response = last_response.body
27
27
  response.should == "redis://127.0.0.1:6379/0"
28
28
  end
29
29
  it "named configuration should work with mime-type" do
30
30
  require 'yaml'
31
- get '/c/myrailsapp1/database.yml'
31
+ get '/configurations/myrailsapp1/database.yml'
32
32
  last_response.should be_ok
33
33
  last_response.headers["Content-Type"].should == "text/x-yaml;charset=utf-8"
34
34
  response = YAML.load(last_response.body)
@@ -38,11 +38,11 @@ describe "Using the Configuration API", :reset_redis => false, :populate_sample_
38
38
  response["development"].values.sort.should == ["dev_password", "dev_user", "development_database", "mysql"]
39
39
  end
40
40
  it "invalid application should not work" do
41
- get '/c/badapp'
41
+ get '/configurations/badapp'
42
42
  last_response.should be_missing
43
43
  end
44
44
  it "invalid configuration for application should not work" do
45
- get '/c/badapp/badconfig'
45
+ get '/configurations/badapp/badconfig'
46
46
  last_response.should be_missing
47
47
  end
48
48
  end
@@ -50,7 +50,7 @@ describe "Using the Configuration API", :reset_redis => false, :populate_sample_
50
50
  describe "PUT" do
51
51
  it "new configuration should work" do
52
52
  config_data = {:format => "string", :body => "sample_config_entry"}.to_json
53
- put '/c/newapp/newconfig', config_data, "CONTENT_TYPE" => "application/json"
53
+ put '/configurations/newapp/newconfig', config_data, "CONTENT_TYPE" => "application/json"
54
54
  last_response.should be_ok
55
55
  response = last_response.should return_json
56
56
  response["result"].should == "success"
@@ -62,7 +62,7 @@ describe "Using the Configuration API", :reset_redis => false, :populate_sample_
62
62
  it "existing configuration should work" do
63
63
  config_data = {:format => "string", :body => "sample_config_entry"}.to_json
64
64
  sleep 3
65
- put '/c/newapp/newconfig', config_data, "CONTENT_TYPE" => "application/json"
65
+ put '/configurations/newapp/newconfig', config_data, "CONTENT_TYPE" => "application/json"
66
66
  last_response.should be_ok
67
67
  response = last_response.should return_json
68
68
  response["result"].should == "success"
@@ -73,12 +73,12 @@ describe "Using the Configuration API", :reset_redis => false, :populate_sample_
73
73
  end
74
74
  it "new configuration with missing format should not work" do
75
75
  config_data = {:body => "a string"}.to_json
76
- put '/c/newnewapp/someconfig', config_data, "CONTENT_TYPE" => "application/json"
76
+ put '/configurations/newnewapp/someconfig', config_data, "CONTENT_TYPE" => "application/json"
77
77
  last_response.should be_invalid
78
78
  end
79
79
  it "new configuration with missing body should not work" do
80
80
  config_data = {:body => "a string"}.to_json
81
- put '/c/newnewapp/someconfig', config_data, "CONTENT_TYPE" => "application/json"
81
+ put '/configurations/newnewapp/someconfig', config_data, "CONTENT_TYPE" => "application/json"
82
82
  last_response.should be_invalid
83
83
  end
84
84
  end
@@ -93,7 +93,7 @@ describe "Using the Configuration API", :reset_redis => false, :populate_sample_
93
93
  end
94
94
 
95
95
  it "existing configuration should work" do
96
- delete "/c/#{@a.name}/#{@c.name}"
96
+ delete "/configurations/#{@a.name}/#{@c.name}"
97
97
  last_response.should be_ok
98
98
  response = last_response.should return_json
99
99
  response["result"].should == "success"
@@ -103,7 +103,7 @@ describe "Using the Configuration API", :reset_redis => false, :populate_sample_
103
103
  response["item"].should == @c.name
104
104
  end
105
105
  it "invalid configuration should not work" do
106
- delete "/c/#{@a.name}/#{@c.name}"
106
+ delete "/configurations/#{@a.name}/#{@c.name}"
107
107
  last_response.should be_missing
108
108
  end
109
109
  end
@@ -87,6 +87,21 @@ describe "Using the Ephemeral API", :reset_redis => true do
87
87
  last_response.should be_ok
88
88
  last_response.body.should == 'a new value'
89
89
  end
90
+ it "ephemeral with reserved word in subpath should work" do
91
+ Noah::PROTECTED_PATHS.each do |path|
92
+ put "/e/a/valid/path/with/#{path}"
93
+ last_response.should be_ok
94
+ end
95
+ end
96
+ it "ephemeral with reserved word as path should not work" do
97
+ Noah::PROTECTED_PATHS.each do |path|
98
+ put "/e/#{path}/other/stuff"
99
+ last_response.should_not be_ok
100
+ response = last_response.should return_json
101
+ response['error_message'].should == 'Path is reserved'
102
+ response['result'].should == 'failure'
103
+ end
104
+ end
90
105
  end
91
106
 
92
107
  describe "DELETE" do