dns_guru 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README ADDED
File without changes
data/Rakefile ADDED
@@ -0,0 +1,43 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ require 'rake/gempackagetask'
5
+
6
+ task :default => [:test]
7
+
8
+ desc 'Tests'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << "test"
11
+ t.test_files = Dir.glob("test/**/test_*.rb")
12
+ t.verbose = true
13
+ end
14
+
15
+ PKG_FILES = FileList[
16
+ '[a-zA-Z]*',
17
+ 'generators/**/*',
18
+ 'lib/**/*',
19
+ 'rails/**/*',
20
+ 'tasks/**/*',
21
+ 'test/**/*'
22
+ ]
23
+
24
+ spec = Gem::Specification.new do |s|
25
+ s.name = "dns_guru"
26
+ s.version = "0.1"
27
+ s.author = "Dns Guru"
28
+ s.email = "ken.miller@gmail.com"
29
+ s.homepage = "http://github.com/kemiller/dns_guru"
30
+ s.platform = Gem::Platform::RUBY
31
+ s.summary = "Parse hostnames into useful information with a routes-like syntax"
32
+ s.files = PKG_FILES.to_a
33
+ s.require_path = "lib"
34
+ s.has_rdoc = false
35
+ s.extra_rdoc_files = ["README"]
36
+ end
37
+
38
+ desc 'Turn this plugin into a gem.'
39
+ Rake::GemPackageTask.new(spec) do |pkg|
40
+ pkg.gem_spec = spec
41
+ end
42
+
43
+
data/init.rb ADDED
@@ -0,0 +1,27 @@
1
+
2
+ $: << File.join(File.dirname(__FILE__), "lib")
3
+ require 'dns_guru'
4
+ require 'rack'
5
+ require 'action_controller/test_process'
6
+
7
+ config_file = File.join(File.dirname(__FILE__), "../../../config/hosts.rb")
8
+ DnsGuru.init(config_file)
9
+
10
+ class Rack::Request
11
+ include DnsGuru::RequestMixin
12
+ end
13
+
14
+ class ActionController::Request
15
+ include DnsGuru::RequestMixin
16
+ end
17
+
18
+ class ActionController::TestRequest
19
+ include DnsGuru::RequestMixin
20
+ end
21
+
22
+ class ActionController::Base
23
+ include DnsGuru::ControllerMixin
24
+
25
+ helper_method :host_name
26
+ helper_method :host_name_params
27
+ end
@@ -0,0 +1,15 @@
1
+
2
+ module DnsGuru
3
+ module ControllerMixin
4
+ def host_name(options = {})
5
+ host = request.canonical_host_name(options)
6
+ if request.port && request.port != 80
7
+ host = "#{host}:#{request.port}"
8
+ end
9
+ host
10
+ end
11
+ def host_name_params
12
+ request.host_name_params
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,52 @@
1
+
2
+ require 'dns_guru/pattern'
3
+
4
+ module DnsGuru
5
+ class Matcher
6
+
7
+ attr_reader :patterns
8
+
9
+ def initialize(patterns = [])
10
+ @patterns = patterns
11
+ end
12
+
13
+ def match(string)
14
+ iterate(:match, string)
15
+ end
16
+
17
+ def generate(options = {})
18
+ @defaults ||= {}
19
+ iterate(:generate, @defaults.merge(options))
20
+ end
21
+
22
+ def rewrite(string, options = {})
23
+ generate(match(string).merge(options))
24
+ end
25
+
26
+ def pattern(pattern_string, params = {})
27
+ @patterns << Pattern.new(pattern_string, params)
28
+ end
29
+
30
+ def defaults(options = {})
31
+ @defaults = options
32
+ end
33
+
34
+ def current_defaults
35
+ @defaults
36
+ end
37
+
38
+ protected
39
+
40
+ def iterate(method, *args)
41
+ @patterns.each do |pat|
42
+ val = pat.send(method, *args)
43
+ if val
44
+ return val
45
+ end
46
+ end
47
+ nil
48
+ end
49
+
50
+ end
51
+
52
+ end
@@ -0,0 +1,128 @@
1
+
2
+ module DnsGuru
3
+ class Pattern
4
+
5
+ attr_reader :segments, :regexp, :params
6
+
7
+ def initialize(pattern, params={})
8
+ @params = params
9
+ parse(pattern)
10
+ end
11
+
12
+ def parse(pattern)
13
+ raw_segments = pattern.split(/(\.|-)/)
14
+
15
+ @segments = raw_segments.map do |seg|
16
+ Segment.make_segment(seg, @params)
17
+ end
18
+
19
+ @regexp = /\A#{segments.map { |s| s.substitute }.join}\Z/
20
+ end
21
+
22
+ def match(string)
23
+ md = @regexp.match(string)
24
+
25
+ unless md
26
+ return nil
27
+ end
28
+
29
+ hash = {}
30
+ md.captures.each_with_index do |m, i|
31
+ if segments[i].param
32
+ hash[segments[i].param] = m
33
+ end
34
+ end
35
+
36
+ params.merge(hash)
37
+ end
38
+
39
+ def generate(options)
40
+ options = options.dup
41
+ hostname = segments.map do |seg|
42
+ seg.generate(options)
43
+ end
44
+
45
+ if hostname.include?(nil)
46
+ return nil
47
+ end
48
+
49
+ # Whatever is left should be identical
50
+ if params == options
51
+ return hostname.join
52
+ end
53
+ end
54
+
55
+ def rewrite(domain, new_options)
56
+ options = match(domain)
57
+ if options
58
+ generate(options.merge(new_options))
59
+ end
60
+ end
61
+ end
62
+
63
+ class Segment
64
+
65
+ class << self
66
+ def inherited(klass)
67
+ types << klass
68
+ end
69
+
70
+ def types
71
+ @types ||= []
72
+ end
73
+
74
+ def make_segment(string, params = {})
75
+ klass = types.detect do |t|
76
+ t.recognize(string)
77
+ end
78
+ klass.new(string, params)
79
+ end
80
+ end
81
+
82
+ def initialize(string, params = {})
83
+ @string = string
84
+ @default = params.delete(param)
85
+ end
86
+
87
+ def param
88
+ nil
89
+ end
90
+
91
+ end
92
+
93
+ class DynamicSegment < Segment
94
+ def self.recognize(string_segment)
95
+ string_segment =~ /\A:(.*)/
96
+ end
97
+
98
+ def substitute
99
+ "([[:alnum:]_-]+)"
100
+ end
101
+
102
+ def generate(options)
103
+ unless options[param]
104
+ return @default
105
+ end
106
+ options.delete(param)
107
+ end
108
+
109
+ def param
110
+ @param ||= @string[1,1000].to_sym
111
+ end
112
+ end
113
+
114
+ class StaticSegment < Segment
115
+ def self.recognize(string_segment)
116
+ true
117
+ end
118
+
119
+ def substitute
120
+ "(#{Regexp.escape(@string)})"
121
+ end
122
+
123
+ def generate(options)
124
+ @string
125
+ end
126
+ end
127
+ end
128
+
@@ -0,0 +1,14 @@
1
+
2
+ module DnsGuru
3
+ module RequestMixin
4
+
5
+ def canonical_host_name(options = {})
6
+ DnsGuru.generate(host_name_params.merge(options))
7
+ end
8
+
9
+ def host_name_params
10
+ @host_name_params ||= DnsGuru.match(host) || DnsGuru.defaults
11
+ end
12
+
13
+ end
14
+ end
data/lib/dns_guru.rb ADDED
@@ -0,0 +1,33 @@
1
+
2
+ require 'dns_guru/matcher'
3
+ require 'dns_guru/pattern'
4
+ require 'dns_guru/request_mixin'
5
+ require 'dns_guru/controller_mixin'
6
+
7
+ module DnsGuru
8
+
9
+ def self.init(filename)
10
+ @matcher = Matcher.new([])
11
+ load filename
12
+ end
13
+
14
+ def self.read
15
+ yield(@matcher)
16
+ end
17
+
18
+ def self.match(domain)
19
+ @matcher.match(domain)
20
+ end
21
+
22
+ def self.generate(options = {})
23
+ @matcher.generate(options)
24
+ end
25
+
26
+ def self.rewrite(domain, options = {})
27
+ @matcher.rewrite(domain, options)
28
+ end
29
+
30
+ def self.defaults
31
+ @matcher.current_defaults
32
+ end
33
+ end
data/rails/init.rb ADDED
@@ -0,0 +1,27 @@
1
+
2
+ $: << File.join(File.dirname(__FILE__), "lib")
3
+ require 'dns_guru'
4
+ require 'rack'
5
+ require 'action_controller/test_process'
6
+
7
+ config_file = File.join(File.dirname(__FILE__), "../../../config/hosts.rb")
8
+ DnsGuru.init(config_file)
9
+
10
+ class Rack::Request
11
+ include DnsGuru::RequestMixin
12
+ end
13
+
14
+ class ActionController::Request
15
+ include DnsGuru::RequestMixin
16
+ end
17
+
18
+ class ActionController::TestRequest
19
+ include DnsGuru::RequestMixin
20
+ end
21
+
22
+ class ActionController::Base
23
+ include DnsGuru::ControllerMixin
24
+
25
+ helper_method :host_name
26
+ helper_method :host_name_params
27
+ end
data/test/config.rb ADDED
@@ -0,0 +1,8 @@
1
+
2
+ DnsGuru.read do |matcher|
3
+ matcher.defaults :app => 'www', :stage => 'production', :brand => 'mmp', :tld => 'com'
4
+ matcher.pattern "localhost", :app => 'www', :stage => 'development', :brand => 'mamasource', :tld => 'com'
5
+ matcher.pattern "seodev.:brand.:tld", :stage => 'qa'
6
+ matcher.pattern ":app.:brand.:tld", :stage => 'production'
7
+ matcher.pattern ":app.:stage.:brand.:tld"
8
+ end
@@ -0,0 +1,48 @@
1
+
2
+ require 'test/unit'
3
+ require 'dns_guru'
4
+
5
+ module DnsGuru
6
+ class TestControllerMixin < Test::Unit::TestCase
7
+
8
+ def setup
9
+ DnsGuru.init(File.join(File.dirname(__FILE__), "../config.rb"))
10
+ @request = MockRequest.new
11
+ @controller = MockController.new
12
+ @controller.request = @request
13
+ end
14
+
15
+ def test_host_name
16
+ @request.host = "www.production.mmp.com"
17
+ assert_equal "www.mmp.com", @controller.host_name
18
+ end
19
+
20
+ def test_host_name_with_port
21
+ @request.host = "www.production.mmp.com"
22
+ @request.port = 3000
23
+ assert_equal "www.mmp.com:3000", @controller.host_name
24
+ end
25
+
26
+ def test_host_name_params
27
+ @request.host = "www.production.mamapedia.com"
28
+ assert_equal({:app => 'www', :stage => 'production', :brand => 'mamapedia', :tld => 'com'},
29
+ @controller.host_name_params, "Wrong host name components derived from raw host name")
30
+ end
31
+
32
+ def test_host_name_params_no_host
33
+ assert_equal({:app => 'www', :stage => 'production', :brand => 'mmp', :tld => 'com'},
34
+ @controller.host_name_params, "No default values given")
35
+ end
36
+ end
37
+
38
+ class MockRequest
39
+ include RequestMixin
40
+ attr_accessor :host
41
+ attr_accessor :port
42
+ end
43
+
44
+ class MockController
45
+ include ControllerMixin
46
+ attr_accessor :request
47
+ end
48
+ end
@@ -0,0 +1,98 @@
1
+
2
+ require 'test/unit'
3
+ require 'dns_guru'
4
+
5
+ module DnsGuru
6
+ class TestMatcher < Test::Unit::TestCase
7
+
8
+ def test_truth
9
+ Matcher
10
+ end
11
+
12
+ def test_initialize
13
+ matcher = Matcher.new
14
+ assert_not_nil matcher
15
+ end
16
+
17
+ def test_match_no_hit
18
+ str = "mymatch_here"
19
+ matcher = Matcher.new([m1 = MockPattern.new, m2 = MockPattern.new])
20
+ matcher.match(str)
21
+ assert_equal str, m1.got_match, "First Pattern wasn't checked"
22
+ assert_equal str, m2.got_match, "Second Pattern wasn't checked"
23
+ end
24
+
25
+ def test_match_hit
26
+ str = "mymatch_here"
27
+ matcher = Matcher.new([m1 = MockPattern.new(true), m2 = MockPattern.new])
28
+ matcher.match(str)
29
+ assert_equal str, m1.got_match, "First Pattern wasn't checked"
30
+ assert_equal nil, m2.got_match, "Second Pattern should not have been checked"
31
+ end
32
+
33
+ def test_generate_no_hit
34
+ hash = { :str => "mygenerate_here" }
35
+ generateer = Matcher.new([m1 = MockPattern.new, m2 = MockPattern.new])
36
+ generateer.generate(hash)
37
+ assert_equal hash, m1.got_generate, "First Pattern wasn't checked"
38
+ assert_equal hash, m2.got_generate, "Second Pattern wasn't checked"
39
+ end
40
+
41
+ def test_generate_hit
42
+ hash = { :str => "mygenerate_here" }
43
+ generateer = Matcher.new([m1 = MockPattern.new(true), m2 = MockPattern.new])
44
+ generateer.generate(hash)
45
+ assert_equal hash, m1.got_generate, "First Pattern wasn't checked"
46
+ assert_equal nil, m2.got_generate, "Second Pattern should not have been checked"
47
+ end
48
+
49
+ def test_pattern
50
+ matcher = Matcher.new
51
+ matcher.pattern ":asdf.:rase", :param => 'p1'
52
+ assert_kind_of Pattern, matcher.patterns.first, "Didn't make a pattern"
53
+ end
54
+
55
+ def test_pattern_precedence
56
+ matcher = Matcher.new
57
+ matcher.pattern ":app.:brand.com", :stage => 'production'
58
+ matcher.pattern ":app.:stage.:brand.com"
59
+
60
+ assert_equal "www.mmp.com", matcher.generate(:app => 'www', :brand => 'mmp', :stage => 'production')
61
+ assert_equal "www.mmp.com", matcher.rewrite("www.production.mmp.com")
62
+ end
63
+
64
+ def test_defaults
65
+ matcher = Matcher.new
66
+ matcher.defaults :stage => 'production', :brand => 'mmp', :app => 'www'
67
+ matcher.pattern ":app.:brand.com", :stage => 'production'
68
+ matcher.pattern ":app.:stage.:brand.com", :app => 'www', :brand => 'mmp', :stage => 'production'
69
+
70
+ assert_equal "www.mmp.com", matcher.generate
71
+ end
72
+
73
+ end
74
+
75
+ class MockPattern
76
+ attr_reader :got_match, :got_generate, :got_rewrite
77
+
78
+ def initialize(rval = false)
79
+ @rval = rval
80
+ end
81
+
82
+ def match(string)
83
+ @got_match = string
84
+ @rval
85
+ end
86
+
87
+ def generate(options)
88
+ @got_generate = options
89
+ @rval
90
+ end
91
+
92
+ def rewrite(string, options)
93
+ @got_rewrite = [string, options]
94
+ @rval
95
+ end
96
+ end
97
+ end
98
+
@@ -0,0 +1,83 @@
1
+
2
+ require 'test/unit'
3
+ require 'dns_guru'
4
+
5
+ module DnsGuru
6
+ class TestPattern < Test::Unit::TestCase
7
+
8
+ def test_initialize
9
+ p = Pattern.new(":blah.:blah")
10
+ assert_not_nil p, "Initialization should work"
11
+ end
12
+
13
+ def test_parse
14
+ p = Pattern.new(":blah.:blah")
15
+ segments = p.segments
16
+ assert !segments.empty?, "Parsing should return an array of segments"
17
+ end
18
+
19
+ def test_segment_types
20
+ p = Pattern.new(":blah.dev.:blah")
21
+ segments = p.segments
22
+ assert_kind_of DynamicSegment, segments.first, "First Segment should be Dynamic"
23
+ assert_kind_of StaticSegment, segments[1], "Second Segment should be Static"
24
+ end
25
+
26
+ def test_match
27
+ p = Pattern.new(":app.:stage.:brand.:tld")
28
+ assert_equal({ :app => 'www', :stage => 'dev', :brand => 'mmp', :tld => 'com' }, p.match("www.dev.mmp.com"))
29
+ assert_equal({ :app => 'www-01', :stage => 'dev', :brand => 'mmp', :tld => 'com' }, p.match("www-01.dev.mmp.com"))
30
+ end
31
+
32
+ def test_match_with_specified_hyphens
33
+ p = Pattern.new(":app.:stage-:machine.:brand.:tld")
34
+ assert_equal({ :app => 'www', :machine => '01', :stage => 'dev', :brand => 'mmp', :tld => 'com' }, p.match("www.dev-01.mmp.com"))
35
+ end
36
+
37
+ def test_match_with_static_segments
38
+ p = Pattern.new(":app.dev.:brand.:tld", :stage => 'development')
39
+ assert_equal({ :app => 'www', :stage => 'development', :brand => 'mmp', :tld => 'com' }, p.match("www.dev.mmp.com"))
40
+ end
41
+
42
+ def test_match_no_match
43
+ p = Pattern.new("foo")
44
+ assert_equal(nil, p.match("ausfark"))
45
+ end
46
+
47
+ def test_localhost
48
+ p = Pattern.new("localhost", :stage => 'development', :brand => 'mms', :tld => 'com', :app => 'www')
49
+ assert_equal({ :app => 'www', :stage => 'development', :brand => 'mms', :tld => 'com' }, p.match("localhost"))
50
+ end
51
+
52
+ def test_generate
53
+ p = Pattern.new(":app.:stage.:brand.:tld")
54
+ assert_equal "www.qa.mms.com", p.generate(:app => 'www', :stage => 'qa', :brand => 'mms', :tld => 'com')
55
+ end
56
+
57
+ def test_generate_with_defaults
58
+ p = Pattern.new(":app.:stage.:brand.:tld", :tld => 'com')
59
+ assert_equal "www.qa.mms.com", p.generate(:app => 'www', :stage => 'qa', :brand => 'mms')
60
+ end
61
+
62
+ def test_generate_with_statics
63
+ p = Pattern.new(":app.dev.:brand.:tld", :stage => 'development')
64
+ assert_equal "www.dev.mms.com", p.generate(:app => 'www', :stage => 'development', :brand => 'mms', :tld => 'com')
65
+ end
66
+
67
+ def test_generate_fails_for_insufficient_params
68
+ p = Pattern.new(":app.dev.:brand.:tld", :stage => 'development')
69
+ assert_equal nil, p.generate(:stage => 'development', :brand => 'mms', :tld => 'com')
70
+ end
71
+
72
+ def test_generate_fails_for_surplus_params
73
+ p = Pattern.new(":app.dev.:brand.:tld", :stage => 'development')
74
+ assert_equal nil, p.generate(:extra => 'foo', :app => 'www', :stage => 'development', :brand => 'mms', :tld => 'com')
75
+ end
76
+
77
+ def test_rewrite
78
+ p = Pattern.new(":app.:stage.:brand.:tld")
79
+ assert_equal "www.qa.mmp.com", p.rewrite("www.qa.google.com", :brand => 'mmp')
80
+ end
81
+
82
+ end
83
+ end
@@ -0,0 +1,30 @@
1
+
2
+ require 'test/unit'
3
+ require 'dns_guru'
4
+
5
+ module DnsGuru
6
+ class TestRequestMixin < Test::Unit::TestCase
7
+
8
+ def setup
9
+ DnsGuru.init(File.join(File.dirname(__FILE__), "../config.rb"))
10
+ @req = MockRequest.new
11
+ end
12
+
13
+ def test_canonical_host_name
14
+ @req.host = "www.production.mamapedia.com"
15
+ assert_equal "www.mamapedia.com", @req.canonical_host_name
16
+ end
17
+
18
+ def test_host_name_params
19
+ @req.host = "www.production.mamapedia.com"
20
+ assert_equal({:app => 'www', :stage => 'production', :brand => 'mamapedia', :tld => 'com'},
21
+ @req.host_name_params, "Wrong host name components derived from raw host name")
22
+ end
23
+ end
24
+
25
+
26
+ class MockRequest
27
+ include RequestMixin
28
+ attr_accessor :host
29
+ end
30
+ end
@@ -0,0 +1,28 @@
1
+
2
+ require 'test/unit'
3
+ require 'dns_guru'
4
+
5
+ class TestDnsGuru < Test::Unit::TestCase
6
+
7
+ def setup
8
+ DnsGuru.init(File.join(File.dirname(__FILE__), "config.rb"))
9
+ end
10
+
11
+ def test_match
12
+ assert_equal({:app => 'www', :stage => 'production', :brand => 'google', :tld => 'com'}, DnsGuru.match("www.google.com"))
13
+ end
14
+
15
+ def test_generate
16
+ assert_equal("www.google.com", DnsGuru.generate(:app => 'www', :stage => 'production', :brand => 'google', :tld => 'com'))
17
+ assert_equal("www.mmp.com", DnsGuru.generate)
18
+ end
19
+
20
+ def test_rewrite
21
+ assert_equal("www.mmp.com", DnsGuru.rewrite("www.google.com", :brand => 'mmp'))
22
+ assert_equal("www.mmp.com", DnsGuru.rewrite("www.production.mmp.com"))
23
+ assert_equal("mail.google.com", DnsGuru.rewrite("www.google.com", :app => 'mail'))
24
+ assert_equal("www.google.co.jp", DnsGuru.rewrite("www.google.com", :tld => 'co.jp')) # this is iffy
25
+ assert_equal(nil, DnsGuru.rewrite("www.google.com", :stage => 'asdf', :nuts => 'too'))
26
+ end
27
+
28
+ end
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dns_guru
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.1"
5
+ platform: ruby
6
+ authors:
7
+ - Dns Guru
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-03-07 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: ken.miller@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README
24
+ files:
25
+ - init.rb
26
+ - Rakefile
27
+ - README
28
+ - lib/dns_guru/controller_mixin.rb
29
+ - lib/dns_guru/matcher.rb
30
+ - lib/dns_guru/pattern.rb
31
+ - lib/dns_guru/request_mixin.rb
32
+ - lib/dns_guru.rb
33
+ - rails/init.rb
34
+ - test/config.rb
35
+ - test/dns_guru/test_controller_mixin.rb
36
+ - test/dns_guru/test_matcher.rb
37
+ - test/dns_guru/test_pattern.rb
38
+ - test/dns_guru/test_request_mixin.rb
39
+ - test/test_dns_guru.rb
40
+ has_rdoc: true
41
+ homepage: http://github.com/kemiller/dns_guru
42
+ licenses: []
43
+
44
+ post_install_message:
45
+ rdoc_options: []
46
+
47
+ require_paths:
48
+ - lib
49
+ required_ruby_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: "0"
54
+ version:
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: "0"
60
+ version:
61
+ requirements: []
62
+
63
+ rubyforge_project:
64
+ rubygems_version: 1.3.5
65
+ signing_key:
66
+ specification_version: 3
67
+ summary: Parse hostnames into useful information with a routes-like syntax
68
+ test_files: []
69
+