stubby 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +21 -0
- data/README.md +172 -111
- data/lib/stubby/cli/application.rb +1 -50
- data/lib/stubby/extensions/default.rb +72 -0
- data/lib/stubby/extensions/dns.rb +47 -30
- data/lib/stubby/extensions/http.rb +63 -26
- data/lib/stubby/extensions/smtp.rb +47 -0
- data/lib/stubby/kernel.rb +36 -0
- data/lib/stubby/master.rb +83 -42
- data/lib/stubby/process.rb +22 -0
- data/lib/stubby/registry.rb +16 -115
- data/lib/stubby/stub.rb +18 -6
- data/lib/stubby.rb +7 -0
- metadata +38 -2
@@ -26,8 +26,10 @@ module Extensions
|
|
26
26
|
super(:server_settings => server_settings)
|
27
27
|
end
|
28
28
|
|
29
|
-
def adapter(
|
30
|
-
|
29
|
+
def adapter(*names, &block)
|
30
|
+
names.each do |name|
|
31
|
+
adapters[name] = block
|
32
|
+
end
|
31
33
|
end
|
32
34
|
|
33
35
|
def adapters
|
@@ -39,15 +41,7 @@ module Extensions
|
|
39
41
|
set :static, false
|
40
42
|
|
41
43
|
adapter "http-redirect" do
|
42
|
-
|
43
|
-
url.path = request.path if url.path.to_s.empty?
|
44
|
-
redirect to(url.to_s)
|
45
|
-
end
|
46
|
-
|
47
|
-
adapter "https-redirect" do
|
48
|
-
url.scheme = "https"
|
49
|
-
url.path = request.path if url.path.to_s.empty?
|
50
|
-
redirect to(url.to_s)
|
44
|
+
redirect to(instruction_params["to"])
|
51
45
|
end
|
52
46
|
|
53
47
|
adapter "file" do
|
@@ -73,37 +67,54 @@ module Extensions
|
|
73
67
|
not_found(paths.join(",\n"))
|
74
68
|
end
|
75
69
|
|
76
|
-
adapter "
|
70
|
+
adapter "http-proxy" do
|
71
|
+
url.scheme = "http"
|
72
|
+
|
77
73
|
if url.path.empty?
|
78
74
|
# Proxy all requests, preserve incoming path
|
79
75
|
out = url.dup
|
80
76
|
out.path = request.path
|
81
77
|
request = HTTPI::Request.new
|
82
78
|
request.url = out.to_s
|
79
|
+
else
|
80
|
+
# Proxy to the given path
|
81
|
+
request = HTTPI::Request.new
|
82
|
+
request.url = url.to_s
|
83
|
+
end
|
83
84
|
|
84
|
-
|
85
|
+
response = HTTPI.get(request)
|
86
|
+
response.headers.delete "transfer-encoding"
|
87
|
+
response.headers.delete "connection"
|
85
88
|
|
86
|
-
|
87
|
-
|
89
|
+
status(response.code)
|
90
|
+
headers(response.headers)
|
91
|
+
body(response.body)
|
88
92
|
|
89
|
-
|
90
|
-
|
91
|
-
|
93
|
+
end
|
94
|
+
|
95
|
+
adapter "https-proxy" do
|
96
|
+
url.scheme = "https"
|
92
97
|
|
98
|
+
if url.path.empty?
|
99
|
+
# Proxy all requests, preserve incoming path
|
100
|
+
out = url.dup
|
101
|
+
out.path = request.path
|
102
|
+
request = HTTPI::Request.new
|
103
|
+
request.url = out.to_s
|
93
104
|
else
|
94
105
|
# Proxy to the given path
|
95
106
|
request = HTTPI::Request.new
|
96
107
|
request.url = url.to_s
|
108
|
+
end
|
97
109
|
|
98
|
-
|
110
|
+
response = HTTPI.get(request)
|
111
|
+
response.headers.delete "transfer-encoding"
|
112
|
+
response.headers.delete "connection"
|
99
113
|
|
100
|
-
|
101
|
-
|
114
|
+
status(response.code)
|
115
|
+
headers(response.headers)
|
116
|
+
body(response.body)
|
102
117
|
|
103
|
-
status(response.code)
|
104
|
-
headers(response.headers)
|
105
|
-
body(response.body)
|
106
|
-
end
|
107
118
|
end
|
108
119
|
|
109
120
|
get(//) do
|
@@ -126,10 +137,14 @@ module Extensions
|
|
126
137
|
end
|
127
138
|
|
128
139
|
def instruction
|
129
|
-
MultiJson.load(HTTPI.post("http://#{STUBBY_MASTER}:9000/rules/search.json",
|
140
|
+
@instruction ||= MultiJson.load(HTTPI.post("http://#{STUBBY_MASTER}:9000/rules/search.json",
|
130
141
|
trigger: "#{request.scheme}://#{request.host}").body)
|
131
142
|
end
|
132
143
|
|
144
|
+
def instruction_params
|
145
|
+
Rack::Utils.parse_nested_query url.query
|
146
|
+
end
|
147
|
+
|
133
148
|
def url
|
134
149
|
@url ||= URI.parse(instruction)
|
135
150
|
end
|
@@ -181,6 +196,24 @@ module Extensions
|
|
181
196
|
HTTPApp.run!(session)
|
182
197
|
end
|
183
198
|
|
199
|
+
# http://blah.com => localhost:3000
|
200
|
+
# =>
|
201
|
+
# http://blah.com => http-proxy://localhost:3000
|
202
|
+
def expand_rule(trigger, instruction, proto='http')
|
203
|
+
u = URI.parse(instruction)
|
204
|
+
|
205
|
+
(if u.scheme.nil?
|
206
|
+
{ trigger => "http-proxy://#{instruction}" }
|
207
|
+
elsif u.scheme == "http"
|
208
|
+
u.scheme = "http-proxy"
|
209
|
+
{ trigger => u.to_s }
|
210
|
+
else
|
211
|
+
{ trigger => instruction }
|
212
|
+
end).merge({
|
213
|
+
"#{trigger.gsub(proto + "://", "dns://")}/a" => "dns-a://#{STUBBY_MASTER}"
|
214
|
+
})
|
215
|
+
end
|
216
|
+
|
184
217
|
def stop!
|
185
218
|
HTTPApp.quit!
|
186
219
|
end
|
@@ -197,6 +230,10 @@ module Extensions
|
|
197
230
|
def stop!
|
198
231
|
HTTPSApp.quit!
|
199
232
|
end
|
233
|
+
|
234
|
+
def expand_rule(trigger, instruction)
|
235
|
+
super(trigger, instruction, "https")
|
236
|
+
end
|
200
237
|
end
|
201
238
|
end
|
202
239
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'mail_catcher'
|
2
|
+
|
3
|
+
module Extensions
|
4
|
+
module SMTP
|
5
|
+
class Server
|
6
|
+
def run!(session, options)
|
7
|
+
@process = Process.fork {
|
8
|
+
$0 = "stubby: [extension worker sub] Extensions::SMTP::Server"
|
9
|
+
|
10
|
+
sleep 2
|
11
|
+
|
12
|
+
HTTPI.post("http://#{STUBBY_MASTER}:9000/stubs/transient/activate.json",
|
13
|
+
options: MultiJson.dump(smtp_stub), key: "_smtp")
|
14
|
+
|
15
|
+
MailCatcher.run! smtp_ip: STUBBY_MASTER,
|
16
|
+
smtp_port: 25,
|
17
|
+
http_ip: STUBBY_MASTER,
|
18
|
+
http_port: 9001,
|
19
|
+
daemon: false
|
20
|
+
}
|
21
|
+
|
22
|
+
trap("INT", important: true){
|
23
|
+
stop!
|
24
|
+
}
|
25
|
+
|
26
|
+
sleep
|
27
|
+
end
|
28
|
+
|
29
|
+
def smtp_stub
|
30
|
+
{
|
31
|
+
"dns://outbox.stubby.dev/a" => "dns-a://#{STUBBY_MASTER}",
|
32
|
+
"http://outbox.stubby.dev" => "http://#{STUBBY_MASTER}:9001"
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
def expand_rule(trigger, instruction)
|
37
|
+
{
|
38
|
+
"#{trigger.gsub("smtp://", "dns://")}/mx" => "dns-mx://#{STUBBY_MASTER}/?priority=10"
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
def stop!
|
43
|
+
Process.shutdown(@process)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
$tracked = {}
|
2
|
+
|
3
|
+
module Kernel
|
4
|
+
alias _trap trap
|
5
|
+
|
6
|
+
def trap(*args, &block)
|
7
|
+
#puts "kernel::trap: #{args.inspect}\n---------------\n #{caller.join("\n")}\n\n"
|
8
|
+
|
9
|
+
if args.last.is_a? Hash
|
10
|
+
options = args.pop
|
11
|
+
else
|
12
|
+
options = {}
|
13
|
+
end
|
14
|
+
|
15
|
+
if options[:important]
|
16
|
+
track(args.first, _trap(*args, &block))
|
17
|
+
else
|
18
|
+
if tracked?(args.first)
|
19
|
+
puts "kernel::trap: #{args.inspect} ignoring"
|
20
|
+
else
|
21
|
+
_trap(*args, &block)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
def track(signal, child_pid)
|
28
|
+
(($tracked ||= {})[Process.pid] ||= {})[signal] = child_pid
|
29
|
+
end
|
30
|
+
|
31
|
+
def tracked?(signal)
|
32
|
+
!!($tracked[Process.pid][signal])
|
33
|
+
rescue
|
34
|
+
false
|
35
|
+
end
|
36
|
+
end
|
data/lib/stubby/master.rb
CHANGED
@@ -5,8 +5,9 @@ module Stubby
|
|
5
5
|
class << self
|
6
6
|
attr_accessor :enabled_stubs
|
7
7
|
attr_accessor :registry
|
8
|
+
attr_accessor :master
|
8
9
|
attr_accessor :environments, :environment
|
9
|
-
|
10
|
+
|
10
11
|
def enabled_stubs
|
11
12
|
@enabled_stubs ||= {}
|
12
13
|
end
|
@@ -19,6 +20,8 @@ module Stubby
|
|
19
20
|
@enabled_stubs = nil
|
20
21
|
@environment = nil
|
21
22
|
@registry = nil
|
23
|
+
|
24
|
+
yield if block_given?
|
22
25
|
end
|
23
26
|
|
24
27
|
def env_settings
|
@@ -26,26 +29,50 @@ module Stubby
|
|
26
29
|
end
|
27
30
|
|
28
31
|
def environment=(name)
|
29
|
-
reset
|
30
|
-
|
32
|
+
reset do
|
33
|
+
@environment = name
|
31
34
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
+
(env_settings["dependencies"] || []).each do |depname, mode|
|
36
|
+
activate(depname, mode)
|
37
|
+
end
|
35
38
|
|
36
|
-
|
39
|
+
env_settings.delete("dependencies")
|
40
|
+
activate_transient(env_settings)
|
41
|
+
end
|
42
|
+
end
|
37
43
|
|
38
|
-
|
44
|
+
def activate(source, mode)
|
45
|
+
registry_item = RegistryItem.new(source)
|
46
|
+
self.enabled_stubs[source] = registry_item.stub(mode)
|
39
47
|
end
|
40
48
|
|
41
|
-
def
|
42
|
-
|
43
|
-
|
44
|
-
self.enabled_stubs[name] = registry_item.stub(mode)
|
49
|
+
def activate_transient(options, key="_")
|
50
|
+
puts "Transient activation #{options.inspect}, #{key}"
|
51
|
+
self.enabled_stubs[key] = TransientStub.new(options)
|
45
52
|
end
|
46
53
|
|
47
|
-
def
|
48
|
-
|
54
|
+
def expand_rules(options)
|
55
|
+
options.inject({}) do |new_opts, (trigger, instruction)|
|
56
|
+
if instruction.is_a? Hash # dependency modes
|
57
|
+
new_opts[trigger] = instruction
|
58
|
+
else
|
59
|
+
instruction = instruction.gsub("@", STUBBY_MASTER)
|
60
|
+
|
61
|
+
protocol, url = trigger.split("://")
|
62
|
+
url, protocol = protocol, :default if url.nil?
|
63
|
+
|
64
|
+
extension = master.extensions[protocol.to_sym]
|
65
|
+
|
66
|
+
if extension
|
67
|
+
new_opts.delete(trigger)
|
68
|
+
new_opts.merge!(extension.expand_rule(trigger, instruction))
|
69
|
+
else
|
70
|
+
raise "No `#{extension}` extension found for trigger: #{trigger}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
new_opts
|
75
|
+
end
|
49
76
|
end
|
50
77
|
end
|
51
78
|
|
@@ -87,7 +114,7 @@ module Stubby
|
|
87
114
|
end
|
88
115
|
|
89
116
|
post "/stubs/transient/activate.json" do
|
90
|
-
Api.activate_transient(params[:options])
|
117
|
+
Api.activate_transient(MultiJson.load(params[:options]), params[:key])
|
91
118
|
json status: "ok"
|
92
119
|
end
|
93
120
|
|
@@ -107,14 +134,17 @@ module Stubby
|
|
107
134
|
attr_accessor :extensions, :config
|
108
135
|
|
109
136
|
def initialize(environments)
|
110
|
-
@extensions =
|
111
|
-
Extensions::
|
112
|
-
Extensions::
|
113
|
-
Extensions::HTTP::
|
114
|
-
|
137
|
+
@extensions = {
|
138
|
+
default: Extensions::Default.new,
|
139
|
+
dns: Extensions::DNS::Server.new,
|
140
|
+
http: Extensions::HTTP::Server.new,
|
141
|
+
https: Extensions::HTTP::SSLServer.new,
|
142
|
+
smtp: Extensions::SMTP::Server.new
|
143
|
+
}
|
115
144
|
|
116
145
|
@config = Api
|
117
146
|
@config.environments = environments
|
147
|
+
@config.master = self
|
118
148
|
end
|
119
149
|
|
120
150
|
def environment=(environment)
|
@@ -122,50 +152,61 @@ module Stubby
|
|
122
152
|
end
|
123
153
|
|
124
154
|
def run!(options={})
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
puts "wait for #{process}"
|
130
|
-
Process.waitpid(process)
|
131
|
-
end
|
132
|
-
ensure
|
133
|
-
unassume_network_interface
|
155
|
+
run_network do
|
156
|
+
run_master do
|
157
|
+
run_extensions
|
158
|
+
end
|
134
159
|
end
|
135
160
|
end
|
136
161
|
|
137
162
|
private
|
138
|
-
def
|
163
|
+
def run_network
|
164
|
+
assume_network_interface
|
165
|
+
yield
|
166
|
+
ensure
|
167
|
+
unassume_network_interface
|
168
|
+
end
|
169
|
+
|
170
|
+
def run_master
|
171
|
+
$0 = "stubby: master"
|
172
|
+
|
173
|
+
Api.run! do |server|
|
174
|
+
yield
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def run_extensions
|
179
|
+
running.each do |process|
|
180
|
+
Process.waitpid(process)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def stop!
|
139
185
|
puts "Shutting down..."
|
140
186
|
|
187
|
+
Api.stop!
|
188
|
+
|
141
189
|
running.each do |process|
|
142
|
-
Process.
|
190
|
+
Process.shutdown(process)
|
143
191
|
end
|
144
192
|
|
145
193
|
puts "Bye."
|
146
194
|
end
|
147
195
|
|
148
196
|
def running
|
149
|
-
@running ||=
|
150
|
-
end
|
151
|
-
|
152
|
-
def run_master_api
|
153
|
-
Process.fork {
|
154
|
-
$0 = "stubby: [config api]"
|
155
|
-
Api.run!
|
156
|
-
}
|
197
|
+
@running ||= run_extensions
|
157
198
|
end
|
158
199
|
|
159
200
|
def run_extensions
|
160
|
-
@running_extensions ||= @extensions.collect { |plugin|
|
201
|
+
@running_extensions ||= @extensions.collect { |name, plugin|
|
161
202
|
Process.fork {
|
162
203
|
$0 = "stubby: [extension worker] #{plugin.class.name}"
|
163
204
|
plugin.run!(self, {})
|
164
205
|
}
|
165
206
|
}
|
166
207
|
|
167
|
-
trap("INT") {
|
168
|
-
|
208
|
+
trap("INT", important: true) {
|
209
|
+
stop!
|
169
210
|
}
|
170
211
|
|
171
212
|
return @running_extensions
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'timeout'
|
2
|
+
|
3
|
+
module Process extend self
|
4
|
+
def running?(pid)
|
5
|
+
!!(kill(0, pid))
|
6
|
+
rescue
|
7
|
+
false
|
8
|
+
end
|
9
|
+
|
10
|
+
def shutdown(pid, timeout=10, sig1="TERM", sig2="KILL")
|
11
|
+
puts "Shutting down: #{pid}"
|
12
|
+
|
13
|
+
kill(sig1, pid)
|
14
|
+
|
15
|
+
Timeout::timeout(timeout) do
|
16
|
+
sleep 1 and puts "." while running?(pid)
|
17
|
+
end
|
18
|
+
rescue Timeout::Error
|
19
|
+
kill(sig2, pid)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
data/lib/stubby/registry.rb
CHANGED
@@ -3,46 +3,32 @@ require 'httpi'
|
|
3
3
|
|
4
4
|
module Stubby
|
5
5
|
class RegistryItem
|
6
|
-
attr_accessor :name, :
|
6
|
+
attr_accessor :name, :source
|
7
7
|
|
8
|
-
def initialize(
|
9
|
-
@
|
10
|
-
@
|
11
|
-
@source = source
|
12
|
-
@location = "~/.stubby/#{name}"
|
8
|
+
def initialize(source)
|
9
|
+
@source = URI.parse(source)
|
10
|
+
@name = @source.path
|
13
11
|
end
|
14
12
|
|
15
|
-
def
|
16
|
-
|
13
|
+
def install
|
14
|
+
`mkdir -p #{path}`
|
15
|
+
`cd #{path} && git clone #{@source} .`
|
17
16
|
end
|
18
17
|
|
19
|
-
def
|
20
|
-
|
21
|
-
uninstall
|
22
|
-
`ln -s #{source} ~/.stubby/#{name}`
|
23
|
-
else
|
24
|
-
`mkdir -p ~/.stubby`
|
25
|
-
download source, "~/.stubby/#{name}.zip"
|
26
|
-
`curl #{source} > ~/.stubby/#{name}.zip`
|
27
|
-
`unzip -d ~/.stubby/ #{source}`
|
28
|
-
`rm ~/.stubby/#{name}.zip`
|
29
|
-
end
|
18
|
+
def path
|
19
|
+
"~/.stubby/#{@source.path}"
|
30
20
|
end
|
31
21
|
|
32
22
|
def uninstall
|
33
|
-
`rm -rf ~/.stubby/#{
|
23
|
+
`rm -rf ~/.stubby/#{@source.path}`
|
34
24
|
end
|
35
25
|
|
36
26
|
def installed?
|
37
|
-
File.exists?
|
38
|
-
end
|
39
|
-
|
40
|
-
def download(source, destination)
|
41
|
-
`curl #{source} #{destination}`
|
27
|
+
File.exists? path
|
42
28
|
end
|
43
29
|
|
44
30
|
def config
|
45
|
-
|
31
|
+
"~/.stubby/#{@source.path}/stubby.json"
|
46
32
|
end
|
47
33
|
|
48
34
|
def stub(target=nil)
|
@@ -52,97 +38,12 @@ module Stubby
|
|
52
38
|
end
|
53
39
|
|
54
40
|
class Registry
|
55
|
-
def
|
56
|
-
|
57
|
-
[name, versions.collect { |version, source|
|
58
|
-
RegistryItem.new name, version, source
|
59
|
-
}]
|
60
|
-
}]
|
61
|
-
end
|
62
|
-
|
63
|
-
def versions(name)
|
64
|
-
if index[name]
|
65
|
-
index[name].sort { |x, y|
|
66
|
-
Gem::Version.new(y.version) <=> Gem::Version.new(x.version)
|
67
|
-
}
|
68
|
-
else
|
69
|
-
[]
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
def version(name, version)
|
74
|
-
version = version.gsub("v", "")
|
75
|
-
|
76
|
-
index[name].detect { |stub|
|
77
|
-
stub.version == version
|
78
|
-
}
|
79
|
-
end
|
80
|
-
|
81
|
-
def latest(name)
|
82
|
-
versions(name).first
|
83
|
-
end
|
84
|
-
|
85
|
-
def install(name, opts={})
|
86
|
-
source = opts[:source]
|
87
|
-
v = opts[:version]
|
88
|
-
|
89
|
-
if name =~ /https?:\/\//
|
90
|
-
source = name
|
91
|
-
name = File.basename(name).split(".").first
|
92
|
-
RegistryItem.new(name, "v1.0.0", source).install
|
93
|
-
else
|
94
|
-
stub = v.nil? ? latest(name) : version(name, v)
|
95
|
-
|
96
|
-
if stub
|
97
|
-
stub.install
|
98
|
-
elsif source
|
99
|
-
add_new_source(name, source, v)
|
100
|
-
else
|
101
|
-
puts "[ERROR] Cannot find #{name} at #{v}"
|
102
|
-
end
|
103
|
-
end
|
41
|
+
def install(source)
|
42
|
+
RegistryItem.new(source).install
|
104
43
|
end
|
105
44
|
|
106
|
-
def uninstall(
|
107
|
-
|
108
|
-
# version, but we have a convention of using a ~/.stubby/NAME
|
109
|
-
# location, so this shouldn't be a problem for the POC
|
110
|
-
if name =~ /https?:\/\//
|
111
|
-
name = File.basename(name).split(".").first
|
112
|
-
end
|
113
|
-
|
114
|
-
latest(name).uninstall
|
115
|
-
end
|
116
|
-
|
117
|
-
|
118
|
-
private
|
119
|
-
|
120
|
-
def remote_index
|
121
|
-
response = HTTPI.get("http://github.com/jkassemi/stubby/index.json")
|
122
|
-
MultiJson.load(response.body) if response.code == 200
|
123
|
-
end
|
124
|
-
|
125
|
-
def local_index
|
126
|
-
MultiJson.load(File.read(File.expand_path(File.join('~', '.stubby', "index.json"))))
|
127
|
-
rescue
|
128
|
-
{}
|
129
|
-
end
|
130
|
-
|
131
|
-
def write_local_index(&block)
|
132
|
-
File.open File.expand_path(File.join('~', '.stubby', "index.json")), "w", &block
|
133
|
-
end
|
134
|
-
|
135
|
-
def add_new_source(name, source, v=nil)
|
136
|
-
version = v.nil? ? 'v0.0.1' : v
|
137
|
-
|
138
|
-
item = RegistryItem.new name, version, source
|
139
|
-
item.install
|
140
|
-
|
141
|
-
current_index = local_index
|
142
|
-
|
143
|
-
write_local_index do |index|
|
144
|
-
index.puts MultiJson.dump(local_index.merge({item.name => {item.version => item.location}}))
|
145
|
-
end
|
45
|
+
def uninstall(source)
|
46
|
+
RegistryItem.new(source).uninstall
|
146
47
|
end
|
147
48
|
end
|
148
49
|
end
|
data/lib/stubby/stub.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'pry'
|
2
|
-
|
3
1
|
module Stubby
|
4
2
|
class Stub
|
5
3
|
attr_accessor :target, :path, :modes
|
@@ -12,8 +10,11 @@ module Stubby
|
|
12
10
|
|
13
11
|
def modes
|
14
12
|
@modes ||= MultiJson.load(File.read(path))
|
15
|
-
rescue
|
16
|
-
|
13
|
+
rescue => e
|
14
|
+
if File.exists?(path)
|
15
|
+
puts "[INFO] Problem parsing #{path}"
|
16
|
+
raise e
|
17
|
+
end
|
17
18
|
end
|
18
19
|
|
19
20
|
def path=(v)
|
@@ -25,8 +26,14 @@ module Stubby
|
|
25
26
|
@path = File.expand_path(v)
|
26
27
|
end
|
27
28
|
|
29
|
+
def target=(environment)
|
30
|
+
@environment = environment
|
31
|
+
@options = nil
|
32
|
+
options
|
33
|
+
end
|
34
|
+
|
28
35
|
def options
|
29
|
-
modes[
|
36
|
+
@options ||= expand(modes[@environment] || {})
|
30
37
|
end
|
31
38
|
|
32
39
|
def search(trigger)
|
@@ -38,11 +45,16 @@ module Stubby
|
|
38
45
|
|
39
46
|
return nil
|
40
47
|
end
|
48
|
+
|
49
|
+
private
|
50
|
+
def expand(options)
|
51
|
+
Stubby::Api.expand_rules(options)
|
52
|
+
end
|
41
53
|
end
|
42
54
|
|
43
55
|
class TransientStub < Stub
|
44
56
|
def initialize(options)
|
45
|
-
@options = options
|
57
|
+
@options = expand(options)
|
46
58
|
end
|
47
59
|
|
48
60
|
def modes
|
data/lib/stubby.rb
CHANGED
@@ -1,10 +1,17 @@
|
|
1
1
|
STUBBY_MASTER="172.16.123.1"
|
2
2
|
|
3
|
+
require 'oj'
|
3
4
|
require 'multi_json'
|
5
|
+
require 'rubygems'
|
6
|
+
require 'bundler/setup'
|
4
7
|
require 'stubby/extensions/dns/osx'
|
5
8
|
require 'stubby/extensions/dns'
|
6
9
|
require 'stubby/extensions/http'
|
10
|
+
require 'stubby/extensions/smtp'
|
7
11
|
require 'stubby/extensions/reload'
|
12
|
+
require 'stubby/extensions/default'
|
8
13
|
require 'stubby/registry'
|
9
14
|
require 'stubby/stub'
|
10
15
|
require 'stubby/master'
|
16
|
+
require 'stubby/process'
|
17
|
+
require 'stubby/kernel'
|