nimbu 0.4 → 0.5.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/lib/nimbu/client.rb DELETED
@@ -1,289 +0,0 @@
1
- require 'rexml/document'
2
- require 'rest_client'
3
- require 'uri'
4
- require 'time'
5
- require 'nimbu/auth'
6
- require 'nimbu/helpers'
7
- require 'nimbu/version'
8
-
9
- # A Ruby class to call the Nimbu REST API. You might use this if you want to
10
- # manage your Nimbu apps from within a Ruby program, such as Capistrano.
11
- #
12
- # Example:
13
- #
14
- # require 'nimbu'
15
- # nimbu = Nimbu::Client.new('me@example.com', 'mypass')
16
- # nimbu.create('myapp')
17
- #
18
- class Nimbu::Client
19
-
20
- include Nimbu::Helpers
21
- extend Nimbu::Helpers
22
-
23
- def self.version
24
- Nimbu::VERSION
25
- end
26
-
27
- def self.gem_version_string
28
- "nimbu-gem/#{version}"
29
- end
30
-
31
- attr_accessor :host, :user, :password
32
-
33
- def self.auth(user, password, host=Nimbu::Auth.host)
34
- client = new(user, password, host)
35
- json_decode client.post('/login', { :user => {:email => user, :password => password }}, :accept => 'json').to_s
36
- end
37
-
38
- def initialize(user, password, host=Nimbu::Auth.host)
39
- @user = user
40
- @password = password
41
- @host = host
42
- end
43
-
44
- # Show a list of sites
45
- def list
46
- doc = xml(get('/sites').to_s)
47
- doc.elements.to_a("//sites/site").map do |a|
48
- name = a.elements.to_a("name").first
49
- owner = a.elements.to_a("domain").first
50
- [name.text, owner.text]
51
- end
52
- end
53
-
54
- # Show info such as mode, custom domain, and collaborators on an app.
55
- def info(name_or_domain)
56
- raise ArgumentError.new("name_or_domain is required for info") unless name_or_domain
57
- name_or_domain = name_or_domain.gsub(/^(http:\/\/)?(www\.)?/, '')
58
- doc = xml(get("/apps/#{name_or_domain}").to_s)
59
- attrs = hash_from_xml_doc(doc)[:app]
60
- attrs.merge!(:collaborators => list_collaborators(attrs[:name]))
61
- attrs.merge!(:addons => installed_addons(attrs[:name]))
62
- end
63
-
64
- def on_warning(&blk)
65
- @warning_callback = blk
66
- end
67
-
68
- def get_template(params)
69
- post("/engine/template",params)
70
- end
71
-
72
- def get_request(params)
73
- post("/engine/render",params)
74
- end
75
-
76
- def post_request(params)
77
- post("/engine/process",params)
78
- end
79
-
80
- def list_themes
81
- get("/themes")
82
- end
83
-
84
- def show_theme_contents(theme)
85
- get("/themes/#{theme}/list")
86
- end
87
-
88
- def fetch_theme_layout(theme,id)
89
- get("/themes/#{theme}/layouts/#{id}")
90
- end
91
-
92
- def fetch_theme_template(theme,id)
93
- get("/themes/#{theme}/templates/#{id}")
94
- end
95
-
96
- def fetch_theme_assets(theme,id)
97
- get("/themes/#{theme}/assets/#{id}")
98
- end
99
-
100
- def upload_layout(theme,name,content)
101
- post("/themes/#{theme}/layouts", {:name => name, :content => content})
102
- end
103
-
104
- def upload_template(theme,name,content)
105
- post("/themes/#{theme}/templates", {:name => name, :content => content})
106
- end
107
-
108
- def upload_snippet(theme,name,content)
109
- post("/themes/#{theme}/snippets", {:name => name, :content => content})
110
- end
111
-
112
- def upload_asset(theme,name,file)
113
- post("/themes/#{theme}/assets", {:name => name, :file => file})
114
- end
115
-
116
- ##################
117
-
118
- def resource(uri, options={})
119
- if http_proxy
120
- RestClient.proxy = http_proxy
121
- end
122
- resource = RestClient::Resource.new(realize_full_uri(uri), options)
123
- resource
124
- end
125
-
126
- def get(uri, extra_headers={}) # :nodoc:
127
- process(:get, uri, extra_headers)
128
- end
129
-
130
- def post(uri, payload="", extra_headers={}) # :nodoc:
131
- process(:post, uri, extra_headers, payload)
132
- end
133
-
134
- def put(uri, payload, extra_headers={}) # :nodoc:
135
- process(:put, uri, extra_headers, payload)
136
- end
137
-
138
- def delete(uri, extra_headers={}) # :nodoc:
139
- process(:delete, uri, extra_headers)
140
- end
141
-
142
- def process(method, uri, extra_headers={}, payload=nil)
143
- headers = nimbu_headers.merge(extra_headers)
144
- args = [method, payload, headers].compact
145
-
146
- resource_options = default_resource_options_for_uri(uri)
147
-
148
- begin
149
- response = resource(uri, resource_options).send(*args)
150
- rescue Errno::ECONNREFUSED, Errno::ETIMEDOUT, SocketError
151
- host = URI.parse(realize_full_uri(uri)).host
152
- error "Unable to connect to #{host}"
153
- rescue RestClient::SSLCertificateNotVerified => ex
154
- host = URI.parse(realize_full_uri(uri)).host
155
- error "WARNING: Unable to verify SSL certificate for #{host}\nTo disable SSL verification, run with HEROKU_SSL_VERIFY=disable"
156
- end
157
-
158
- extract_warning(response)
159
- response
160
- end
161
-
162
- def extract_warning(response)
163
- return unless response
164
- if response.headers[:x_nimbu_warning] && @warning_callback
165
- warning = response.headers[:x_nimbu_warning]
166
- @displayed_warnings ||= {}
167
- unless @displayed_warnings[warning]
168
- @warning_callback.call(warning)
169
- @displayed_warnings[warning] = true
170
- end
171
- end
172
- end
173
-
174
- def nimbu_headers # :nodoc:
175
- {
176
- 'X-Nimbu-API-Version' => '1',
177
- 'X-Nimbu-Token' => password,
178
- 'User-Agent' => self.class.gem_version_string,
179
- 'X-Ruby-Version' => RUBY_VERSION,
180
- 'X-Ruby-Platform' => RUBY_PLATFORM
181
- }
182
- end
183
-
184
- def xml(raw) # :nodoc:
185
- REXML::Document.new(raw)
186
- end
187
-
188
- def escape(value) # :nodoc:
189
- escaped = URI.escape(value.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
190
- escaped.gsub('.', '%2E') # not covered by the previous URI.escape
191
- end
192
-
193
- module JSON
194
- def self.parse(json)
195
- json_decode(json)
196
- end
197
- end
198
-
199
- private
200
-
201
- def configure_addon(action, app_name, addon, config = {})
202
- response = update_addon action,
203
- addon_path(app_name, addon),
204
- config
205
-
206
- json_decode(response.to_s) unless response.to_s.empty?
207
- end
208
-
209
- def addon_path(app_name, addon)
210
- "/apps/#{app_name}/addons/#{escape(addon)}"
211
- end
212
-
213
- def update_addon(action, path, config)
214
- params = { :config => config }
215
- app = params[:config].delete(:confirm)
216
- headers = { :accept => 'application/json' }
217
- params.merge!(:confirm => app) if app
218
-
219
- case action
220
- when :install
221
- post path, params, headers
222
- when :upgrade
223
- put path, params, headers
224
- when :uninstall
225
- confirm = app ? "confirm=#{app}" : ''
226
- delete "#{path}?#{confirm}", headers
227
- end
228
- end
229
-
230
- def realize_full_uri(given)
231
- full_host = (host =~ /^http/) ? host : "http://#{host}"
232
- host = URI.parse(full_host)
233
- uri = URI.parse(given)
234
- uri.host ||= host.host
235
- uri.scheme ||= host.scheme || "http"
236
- uri.path = "/api/v2" + ((uri.path[0..0] == "/") ? uri.path : "/#{uri.path}")
237
- uri.port = host.port if full_host =~ /\:\d+/
238
- uri.to_s
239
- end
240
-
241
- def default_resource_options_for_uri(uri)
242
- if ENV["HEROKU_SSL_VERIFY"] == "disable"
243
- {}
244
- elsif realize_full_uri(uri) =~ %r|^https://api.getnimbu.com|
245
- { :verify_ssl => OpenSSL::SSL::VERIFY_PEER, :ssl_ca_file => local_ca_file }
246
- else
247
- {}
248
- end
249
- end
250
-
251
- def local_ca_file
252
- File.expand_path("../../../data/cacert.pem", __FILE__)
253
- end
254
-
255
- def hash_from_xml_doc(elements)
256
- elements.inject({}) do |hash, e|
257
- next(hash) unless e.respond_to?(:children)
258
- hash.update(e.name.gsub("-","_").to_sym => case e.children.length
259
- when 0 then nil
260
- when 1 then e.text
261
- else hash_from_xml_doc(e.children)
262
- end)
263
- end
264
- end
265
-
266
- def http_proxy
267
- proxy = ENV['HTTP_PROXY'] || ENV['http_proxy']
268
- if proxy && !proxy.empty?
269
- unless /^[^:]+:\/\// =~ proxy
270
- proxy = "http://" + proxy
271
- end
272
- proxy
273
- else
274
- nil
275
- end
276
- end
277
-
278
- def https_proxy
279
- proxy = ENV['HTTPS_PROXY'] || ENV['https_proxy']
280
- if proxy && !proxy.empty?
281
- unless /^[^:]+:\/\// =~ proxy
282
- proxy = "https://" + proxy
283
- end
284
- proxy
285
- else
286
- nil
287
- end
288
- end
289
- end
@@ -1,76 +0,0 @@
1
- require "timeout"
2
- require "socket"
3
- require "uri"
4
- require "nimbu/client"
5
- require "nimbu/helpers"
6
-
7
- class Nimbu::Client::Rendezvous
8
- attr_reader :rendezvous_url, :connect_timeout, :activity_timeout, :input, :output, :on_connect
9
-
10
- def initialize(opts)
11
- @rendezvous_url = opts[:rendezvous_url]
12
- @connect_timeout = opts[:connect_timeout]
13
- @activity_timeout = opts[:activity_timeout]
14
- @input = opts[:input]
15
- @output = opts[:output]
16
- end
17
-
18
- def on_connect(&blk)
19
- @on_connect = blk if block_given?
20
- @on_connect
21
- end
22
-
23
- def start
24
- uri = URI.parse(rendezvous_url)
25
- host, port, secret = uri.host, uri.port, uri.path[1..-1]
26
-
27
- ssl_socket = Timeout.timeout(connect_timeout) do
28
- ssl_context = OpenSSL::SSL::SSLContext.new
29
- if ((host =~ /nimbu\.com$/) && !(ENV["HEROKU_SSL_VERIFY"] == "disable"))
30
- ssl_context.ca_file = File.expand_path("../../../../data/cacert.pem", __FILE__)
31
- ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER
32
- end
33
- tcp_socket = TCPSocket.open(host, port)
34
- ssl_socket = OpenSSL::SSL::SSLSocket.new(tcp_socket, ssl_context)
35
- ssl_socket.connect
36
- ssl_socket.puts(secret)
37
- ssl_socket.readline
38
- ssl_socket
39
- end
40
-
41
- on_connect.call if on_connect
42
-
43
- readables = [input, ssl_socket].compact
44
-
45
- begin
46
- loop do
47
- if o = IO.select(readables, nil, nil, activity_timeout)
48
- if (input && (o.first.first == input))
49
- begin
50
- data = input.readpartial(10000)
51
- rescue EOFError
52
- readables.delete(input)
53
- next
54
- end
55
- ssl_socket.write(data)
56
- ssl_socket.flush
57
- elsif (o.first.first == ssl_socket)
58
- begin
59
- data = ssl_socket.readpartial(10000)
60
- rescue EOFError
61
- break
62
- end
63
- output.write(data)
64
- end
65
- else
66
- raise(Timeout::Error.new)
67
- end
68
- end
69
- rescue Interrupt
70
- ssl_socket.write("\003")
71
- ssl_socket.flush
72
- retry
73
- rescue Errno::EIO
74
- end
75
- end
76
- end
@@ -1 +0,0 @@
1
- Hello world!