ridley 0.5.2 → 0.6.0
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/.travis.yml +4 -0
- data/Guardfile +1 -1
- data/README.md +2 -12
- data/bootstrappers/omnibus.erb +3 -0
- data/lib/ridley/bootstrapper/context.rb +2 -2
- data/lib/ridley/bootstrapper.rb +42 -48
- data/lib/ridley/connection.rb +55 -19
- data/lib/ridley/logging.rb +1 -0
- data/lib/ridley/resource.rb +14 -1
- data/lib/ridley/resources/node.rb +84 -13
- data/lib/ridley/resources/sandbox.rb +38 -6
- data/lib/ridley/ssh/response.rb +16 -1
- data/lib/ridley/ssh/response_set.rb +72 -25
- data/lib/ridley/ssh/worker.rb +25 -10
- data/lib/ridley/ssh.rb +12 -30
- data/lib/ridley/version.rb +1 -1
- data/lib/ridley.rb +8 -16
- data/ridley.gemspec +1 -0
- data/spec/support/actor_mocking.rb +9 -0
- data/spec/support/shared_examples/ridley_resource.rb +36 -3
- data/spec/unit/ridley/connection_spec.rb +4 -0
- data/spec/unit/ridley/resources/node_spec.rb +57 -0
- data/spec/unit/ridley/ssh/response_set_spec.rb +112 -0
- data/spec/unit/ridley/ssh/worker_spec.rb +13 -0
- data/spec/unit/ridley/ssh_spec.rb +23 -6
- metadata +11 -4
data/.travis.yml
CHANGED
data/Guardfile
CHANGED
@@ -12,7 +12,7 @@ guard 'yard', stdout: '/dev/null', stderr: '/dev/null' do
|
|
12
12
|
watch(%r{ext/.+\.c})
|
13
13
|
end
|
14
14
|
|
15
|
-
guard 'rspec',
|
15
|
+
guard 'rspec', cli: "--color --drb --format Fuubar", all_on_start: false, all_after_pass: false do
|
16
16
|
watch(%r{^spec/unit/.+_spec\.rb$})
|
17
17
|
watch(%r{^spec/acceptance/.+_spec\.rb$})
|
18
18
|
|
data/README.md
CHANGED
@@ -291,22 +291,12 @@ Given the previous example you could set the default node attribute with the `se
|
|
291
291
|
|
292
292
|
### Node Attributes
|
293
293
|
|
294
|
-
Setting the `
|
294
|
+
Setting the `node[:my_app][:billing][:enabled]` node level attribute on the node "jwinsor-1"
|
295
295
|
|
296
296
|
conn = Ridley.connection
|
297
297
|
conn.sync do
|
298
298
|
obj = node.find("jwinsor-1")
|
299
|
-
obj.
|
300
|
-
obj.save
|
301
|
-
end
|
302
|
-
|
303
|
-
Other attribute precedence levels can be set with their own respective set attribute functions
|
304
|
-
|
305
|
-
conn = Ridley.connection
|
306
|
-
conn.sync do
|
307
|
-
obj = node.find("jwinsor-1")
|
308
|
-
obj.set_override_attribute("my_app.proxy.enabled", false)
|
309
|
-
obj.set_normal_attribute("my_app.webapp.enabled", false)
|
299
|
+
obj.set_attribute("my_app.billing.enabled", false)
|
310
300
|
obj.save
|
311
301
|
end
|
312
302
|
|
data/bootstrappers/omnibus.erb
CHANGED
@@ -146,7 +146,7 @@ CONFIG
|
|
146
146
|
|
147
147
|
# @return [String]
|
148
148
|
def first_boot
|
149
|
-
attributes.merge(run_list: run_list)
|
149
|
+
MultiJson.encode attributes.merge(run_list: run_list)
|
150
150
|
end
|
151
151
|
|
152
152
|
# The validation key to create a new client for the node
|
@@ -155,7 +155,7 @@ CONFIG
|
|
155
155
|
#
|
156
156
|
# @return [String]
|
157
157
|
def validation_key
|
158
|
-
IO.read(validator_path).chomp
|
158
|
+
IO.read(File.expand_path(validator_path)).chomp
|
159
159
|
rescue Errno::ENOENT
|
160
160
|
raise Errors::ValidatorNotFound, "Error bootstrapping: Validator not found at '#{validator_path}'"
|
161
161
|
end
|
data/lib/ridley/bootstrapper.rb
CHANGED
@@ -25,43 +25,45 @@ module Ridley
|
|
25
25
|
attr_reader :contexts
|
26
26
|
|
27
27
|
# @return [Hash]
|
28
|
-
attr_reader :
|
28
|
+
attr_reader :options
|
29
29
|
|
30
30
|
# @param [Array<#to_s>] hosts
|
31
|
-
# @option options [
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
# timeout value for SSH bootstrap
|
31
|
+
# @option options [Hash] :ssh
|
32
|
+
# * :user (String) a shell user that will login to each node and perform the bootstrap command on (required)
|
33
|
+
# * :password (String) the password for the shell user that will perform the bootstrap
|
34
|
+
# * :keys (Array, String) an array of keys (or a single key) to authenticate the ssh user with instead of a password
|
35
|
+
# * :timeout (Float) [5.0] timeout value for SSH bootstrap
|
36
36
|
# @option options [String] :validator_client
|
37
37
|
# @option options [String] :validator_path
|
38
38
|
# filepath to the validator used to bootstrap the node (required)
|
39
|
-
# @option options [String] :bootstrap_proxy
|
40
|
-
# URL to a proxy server to bootstrap through
|
41
|
-
# @option options [String] :encrypted_data_bag_secret_path
|
42
|
-
# filepath on your host machine to your organizations encrypted data bag secret
|
43
|
-
# @option options [Hash] :hints
|
44
|
-
# a hash of Ohai hints to place on the bootstrapped node
|
45
|
-
# @option options [Hash] :attributes
|
46
|
-
# a hash of attributes to use in the first Chef run
|
47
|
-
# @option options [Array] :run_list
|
48
|
-
# an initial run list to bootstrap with
|
49
|
-
# @option options [String] :chef_version
|
50
|
-
# version of Chef to install on the node
|
51
|
-
# @option options [String] :environment
|
52
|
-
# environment to join the node to
|
53
|
-
# @option options [Boolean] :sudo
|
39
|
+
# @option options [String] :bootstrap_proxy (nil)
|
40
|
+
# URL to a proxy server to bootstrap through
|
41
|
+
# @option options [String] :encrypted_data_bag_secret_path (nil)
|
42
|
+
# filepath on your host machine to your organizations encrypted data bag secret
|
43
|
+
# @option options [Hash] :hints (Hash.new)
|
44
|
+
# a hash of Ohai hints to place on the bootstrapped node
|
45
|
+
# @option options [Hash] :attributes (Hash.new)
|
46
|
+
# a hash of attributes to use in the first Chef run
|
47
|
+
# @option options [Array] :run_list (Array.new)
|
48
|
+
# an initial run list to bootstrap with
|
49
|
+
# @option options [String] :chef_version (Ridley::CHEF_VERSION)
|
50
|
+
# version of Chef to install on the node
|
51
|
+
# @option options [String] :environment ('_default')
|
52
|
+
# environment to join the node to
|
53
|
+
# @option options [Boolean] :sudo (true)
|
54
54
|
# bootstrap with sudo (default: true)
|
55
|
-
# @option options [String] :template
|
56
|
-
# bootstrap template to use
|
55
|
+
# @option options [String] :template ('omnibus')
|
56
|
+
# bootstrap template to use
|
57
57
|
def initialize(hosts, options = {})
|
58
|
-
@hosts
|
59
|
-
@
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
}
|
58
|
+
@hosts = Array(hosts).collect(&:to_s).uniq
|
59
|
+
@options = options.dup
|
60
|
+
@options[:ssh] ||= Hash.new
|
61
|
+
@options[:ssh] = {
|
62
|
+
timeout: 5.0,
|
63
|
+
sudo: true
|
64
|
+
}.merge(@options[:ssh])
|
65
|
+
|
66
|
+
@options[:sudo] = @options[:ssh][:sudo]
|
65
67
|
|
66
68
|
@contexts = @hosts.collect do |host|
|
67
69
|
Context.new(host, options)
|
@@ -70,30 +72,22 @@ module Ridley
|
|
70
72
|
|
71
73
|
# @return [SSH::ResponseSet]
|
72
74
|
def run
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
pool = SSH::Worker.new(self.ssh_config)
|
77
|
-
end
|
75
|
+
workers = Array.new
|
76
|
+
futures = contexts.collect do |context|
|
77
|
+
info "Running bootstrap command on #{context.host}"
|
78
78
|
|
79
|
-
|
80
|
-
|
81
|
-
end
|
79
|
+
workers << worker = SSH::Worker.new_link(self.options[:ssh].freeze)
|
80
|
+
worker.future.run(context.host, context.boot_command)
|
81
|
+
end
|
82
82
|
|
83
83
|
SSH::ResponseSet.new.tap do |response_set|
|
84
|
-
|
85
|
-
status, response =
|
86
|
-
|
87
|
-
case status
|
88
|
-
when :ok
|
89
|
-
response_set.add_ok(response)
|
90
|
-
when :error
|
91
|
-
response_set.add_error(response)
|
92
|
-
end
|
84
|
+
futures.each do |future|
|
85
|
+
status, response = future.value
|
86
|
+
response_set.add_response(response)
|
93
87
|
end
|
94
88
|
end
|
95
89
|
ensure
|
96
|
-
|
90
|
+
workers.map(&:terminate)
|
97
91
|
end
|
98
92
|
end
|
99
93
|
end
|
data/lib/ridley/connection.rb
CHANGED
@@ -3,7 +3,10 @@ module Ridley
|
|
3
3
|
class Connection
|
4
4
|
class << self
|
5
5
|
def sync(options, &block)
|
6
|
-
new(options)
|
6
|
+
conn = new(options)
|
7
|
+
conn.sync(&block)
|
8
|
+
ensure
|
9
|
+
conn.terminate if conn && conn.alive?
|
7
10
|
end
|
8
11
|
|
9
12
|
# @raise [ArgumentError]
|
@@ -16,6 +19,12 @@ module Ridley
|
|
16
19
|
missing.collect! { |opt| "'#{opt}'" }
|
17
20
|
raise ArgumentError, "Missing required option(s): #{missing.join(', ')}"
|
18
21
|
end
|
22
|
+
|
23
|
+
missing_values = options.slice(*REQUIRED_OPTIONS).select { |key, value| !value.present? }
|
24
|
+
unless missing_values.empty?
|
25
|
+
values = missing_values.keys.collect { |opt| "'#{opt}'" }
|
26
|
+
raise ArgumentError, "Missing value for required option(s): '#{values.join(', ')}'"
|
27
|
+
end
|
19
28
|
end
|
20
29
|
|
21
30
|
# A hash of default options to be used in the Connection initializer
|
@@ -30,17 +39,20 @@ module Ridley
|
|
30
39
|
end
|
31
40
|
|
32
41
|
extend Forwardable
|
42
|
+
|
43
|
+
include Celluloid
|
33
44
|
include Ridley::DSL
|
45
|
+
include Ridley::Logging
|
34
46
|
|
35
|
-
attr_reader :client_name
|
36
|
-
attr_reader :client_key
|
37
47
|
attr_reader :organization
|
38
|
-
attr_reader :ssh
|
39
48
|
|
40
|
-
|
41
|
-
|
42
|
-
|
49
|
+
attr_accessor :client_name
|
50
|
+
attr_accessor :client_key
|
51
|
+
attr_accessor :validator_client
|
52
|
+
attr_accessor :validator_path
|
53
|
+
attr_accessor :encrypted_data_bag_secret_path
|
43
54
|
|
55
|
+
attr_accessor :ssh
|
44
56
|
attr_accessor :thread_count
|
45
57
|
|
46
58
|
def_delegator :conn, :build_url
|
@@ -60,6 +72,18 @@ module Ridley
|
|
60
72
|
|
61
73
|
def_delegator :conn, :in_parallel
|
62
74
|
|
75
|
+
OPTIONS = [
|
76
|
+
:server_url,
|
77
|
+
:client_name,
|
78
|
+
:client_key,
|
79
|
+
:organization,
|
80
|
+
:validator_client,
|
81
|
+
:validator_path,
|
82
|
+
:encrypted_data_bag_secret_path,
|
83
|
+
:thread_count,
|
84
|
+
:ssl
|
85
|
+
].freeze
|
86
|
+
|
63
87
|
REQUIRED_OPTIONS = [
|
64
88
|
:server_url,
|
65
89
|
:client_name,
|
@@ -73,20 +97,20 @@ module Ridley
|
|
73
97
|
# @option options [String] :client_name
|
74
98
|
# name of the client used to authenticate with the Chef API
|
75
99
|
# @option options [String] :client_key
|
76
|
-
# filepath to the client's private key used to authenticate with
|
77
|
-
# the Chef API
|
100
|
+
# filepath to the client's private key used to authenticate with the Chef API
|
78
101
|
# @option options [String] :organization
|
79
102
|
# the Organization to connect to. This is only used if you are connecting to
|
80
103
|
# private Chef or hosted Chef
|
81
|
-
# @option options [String] :validator_client
|
82
|
-
#
|
83
|
-
# @option options [String] :
|
84
|
-
#
|
85
|
-
# @option options [
|
86
|
-
#
|
87
|
-
#
|
88
|
-
#
|
89
|
-
#
|
104
|
+
# @option options [String] :validator_client (nil)
|
105
|
+
# @option options [String] :validator_path (nil)
|
106
|
+
# @option options [String] :encrypted_data_bag_secret_path (nil)
|
107
|
+
# @option options [Integer] :thread_count (DEFAULT_THREAD_COUNT)
|
108
|
+
# @option options [Hash] :ssh (Hash.new)
|
109
|
+
# * :user (String) a shell user that will login to each node and perform the bootstrap command on (required)
|
110
|
+
# * :password (String) the password for the shell user that will perform the bootstrap
|
111
|
+
# * :keys (Array, String) an array of keys (or a single key) to authenticate the ssh user with instead of a password
|
112
|
+
# * :timeout (Float) [5.0] timeout value for SSH bootstrap
|
113
|
+
# * :sudo (Boolean) [true] bootstrap with sudo
|
90
114
|
# @option options [Hash] :params
|
91
115
|
# URI query unencoded key/value pairs
|
92
116
|
# @option options [Hash] :headers
|
@@ -94,10 +118,18 @@ module Ridley
|
|
94
118
|
# @option options [Hash] :request
|
95
119
|
# request options
|
96
120
|
# @option options [Hash] :ssl
|
97
|
-
# SSL
|
121
|
+
# * :verify (Boolean) [true] set to false to disable SSL verification
|
98
122
|
# @option options [URI, String, Hash] :proxy
|
99
123
|
# URI, String, or Hash of HTTP proxy options
|
100
124
|
def initialize(options = {})
|
125
|
+
log.info { "Ridley starting..." }
|
126
|
+
configure(options)
|
127
|
+
end
|
128
|
+
|
129
|
+
# Configure this instance of Ridley::Connection
|
130
|
+
#
|
131
|
+
# @param [Hash] options
|
132
|
+
def configure(options)
|
101
133
|
options = self.class.default_options.merge(options)
|
102
134
|
self.class.validate_options(options)
|
103
135
|
|
@@ -180,6 +212,10 @@ module Ridley
|
|
180
212
|
raise Errors::EncryptedDataBagSecretNotFound, "Encrypted data bag secret provided but not found at '#{encrypted_data_bag_secret_path}'"
|
181
213
|
end
|
182
214
|
|
215
|
+
def finalize
|
216
|
+
log.info { "Ridley stopping..." }
|
217
|
+
end
|
218
|
+
|
183
219
|
private
|
184
220
|
|
185
221
|
attr_reader :conn
|
data/lib/ridley/logging.rb
CHANGED
data/lib/ridley/resource.rb
CHANGED
@@ -234,13 +234,26 @@ module Ridley
|
|
234
234
|
# if the resource does not pass validations
|
235
235
|
#
|
236
236
|
# @return [Boolean]
|
237
|
-
# true if successful and false for failure
|
238
237
|
def save
|
239
238
|
raise Errors::InvalidResource.new(self.errors) unless valid?
|
240
239
|
|
241
240
|
self.attributes = self.class.create(connection, self).attributes
|
242
241
|
true
|
243
242
|
rescue Errors::HTTPConflict
|
243
|
+
self.update
|
244
|
+
true
|
245
|
+
end
|
246
|
+
|
247
|
+
# Updates the instantiated resource on the target remote with any changes made
|
248
|
+
# to self
|
249
|
+
#
|
250
|
+
# @raise [Errors::InvalidResource]
|
251
|
+
# if the resource does not pass validations
|
252
|
+
#
|
253
|
+
# @return [Boolean]
|
254
|
+
def update
|
255
|
+
raise Errors::InvalidResource.new(self.errors) unless valid?
|
256
|
+
|
244
257
|
self.attributes = self.class.update(connection, self).attributes
|
245
258
|
true
|
246
259
|
end
|
@@ -5,11 +5,11 @@ module Ridley
|
|
5
5
|
# @overload bootstrap(connection, nodes, options = {})
|
6
6
|
# @param [Ridley::Connection] connection
|
7
7
|
# @param [Array<String>, String] nodes
|
8
|
-
# @
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
# timeout value for SSH bootstrap
|
8
|
+
# @param [Hash] ssh
|
9
|
+
# * :user (String) a shell user that will login to each node and perform the bootstrap command on (required)
|
10
|
+
# * :password (String) the password for the shell user that will perform the bootstrap
|
11
|
+
# * :keys (Array, String) an array of keys (or a single key) to authenticate the ssh user with instead of a password
|
12
|
+
# * :timeout (Float) [5.0] timeout value for SSH bootstrap
|
13
13
|
# @option options [String] :validator_client
|
14
14
|
# @option options [String] :validator_path
|
15
15
|
# filepath to the validator used to bootstrap the node (required)
|
@@ -31,22 +31,40 @@ module Ridley
|
|
31
31
|
# bootstrap with sudo (default: true)
|
32
32
|
# @option options [String] :template
|
33
33
|
# bootstrap template to use (default: omnibus)
|
34
|
+
#
|
35
|
+
# @return [SSH::ResponseSet]
|
34
36
|
def bootstrap(connection, *args)
|
35
|
-
options = args.
|
37
|
+
options = args.extract_options!
|
36
38
|
|
37
39
|
default_options = {
|
38
40
|
server_url: connection.server_url,
|
39
|
-
ssh_user: connection.ssh[:user],
|
40
|
-
ssh_password: connection.ssh[:password],
|
41
|
-
ssh_timeout: connection.ssh[:timeout],
|
42
41
|
validator_path: connection.validator_path,
|
43
42
|
validator_client: connection.validator_client,
|
44
|
-
encrypted_data_bag_secret_path: connection.encrypted_data_bag_secret_path
|
43
|
+
encrypted_data_bag_secret_path: connection.encrypted_data_bag_secret_path,
|
44
|
+
ssh: connection.ssh
|
45
45
|
}
|
46
46
|
|
47
47
|
options = default_options.merge(options)
|
48
48
|
|
49
|
-
Bootstrapper.new(args, options).run
|
49
|
+
Bootstrapper.new(*args, options).run
|
50
|
+
end
|
51
|
+
|
52
|
+
# Merges the given data with the the data of the target node on the remote
|
53
|
+
#
|
54
|
+
# @param [Ridley::Cnonection] connection
|
55
|
+
# @param [Ridley::Node, String] target
|
56
|
+
# node or identifier of the node to merge
|
57
|
+
# @option options [Array] :run_list
|
58
|
+
# run list items to merge
|
59
|
+
# @option options [Hash] :attributes
|
60
|
+
# attributes of normal precedence to merge
|
61
|
+
#
|
62
|
+
# @raise [Errors::HTTPNotFound]
|
63
|
+
# if the target node is not found
|
64
|
+
#
|
65
|
+
# @return [Ridley::Node]
|
66
|
+
def merge_data(connection, target, options = {})
|
67
|
+
find!(connection, target).merge_data(options)
|
50
68
|
end
|
51
69
|
end
|
52
70
|
|
@@ -184,12 +202,65 @@ module Ridley
|
|
184
202
|
|
185
203
|
# Run Chef-Client on the instantiated node
|
186
204
|
#
|
205
|
+
# @param [Hash] options
|
206
|
+
# a hash of options to pass to {Ridley::SSH.start}
|
207
|
+
#
|
187
208
|
# @return [SSH::Response]
|
188
|
-
def chef_client
|
189
|
-
|
209
|
+
def chef_client(options = {})
|
210
|
+
options = connection.ssh.merge(options)
|
211
|
+
|
212
|
+
Ridley.log.debug "Running Chef Client on: #{self.public_hostname}"
|
213
|
+
Ridley::SSH.start(self, options) do |ssh|
|
190
214
|
ssh.run("sudo chef-client").first
|
191
215
|
end
|
192
216
|
end
|
217
|
+
|
218
|
+
# Put the connection's encrypted data bag secret onto the instantiated node. If no
|
219
|
+
# encrypted data bag key path is set on the resource's connection then nil will be
|
220
|
+
# returned
|
221
|
+
#
|
222
|
+
# @param [Hash] options
|
223
|
+
# a hash of options to pass to {Ridley::SSH.start}
|
224
|
+
#
|
225
|
+
# @return [SSH::Response, nil]
|
226
|
+
def put_secret(options = {})
|
227
|
+
if connection.encrypted_data_bag_secret_path.nil? ||
|
228
|
+
!File.exists?(connection.encrypted_data_bag_secret_path)
|
229
|
+
|
230
|
+
return nil
|
231
|
+
end
|
232
|
+
|
233
|
+
options = connection.ssh.merge(options)
|
234
|
+
secret = File.read(connection.encrypted_data_bag_secret_path).chomp
|
235
|
+
command = "echo '#{secret}' > /etc/chef/encrypted_data_bag_secret; chmod 0600 /etc/chef/encrypted_data_bag_secret"
|
236
|
+
|
237
|
+
Ridley.log.debug "Writing Encrypted Data Bag Secret to: #{self.public_hostname}"
|
238
|
+
Ridley::SSH.start(self, options) do |ssh|
|
239
|
+
ssh.run(command).first
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
# Merges the instaniated nodes data with the given data and updates
|
244
|
+
# the remote with the merged results
|
245
|
+
#
|
246
|
+
# @option options [Array] :run_list
|
247
|
+
# run list items to merge
|
248
|
+
# @option options [Hash] :attributes
|
249
|
+
# attributes of normal precedence to merge
|
250
|
+
#
|
251
|
+
# @return [Ridley::Node]
|
252
|
+
def merge_data(options = {})
|
253
|
+
unless options[:run_list].nil?
|
254
|
+
self.run_list = (self.run_list + Array(options[:run_list])).uniq
|
255
|
+
end
|
256
|
+
|
257
|
+
unless options[:attributes].nil?
|
258
|
+
self.normal = self.normal.deep_merge(options[:attributes])
|
259
|
+
end
|
260
|
+
|
261
|
+
self.update
|
262
|
+
self
|
263
|
+
end
|
193
264
|
end
|
194
265
|
|
195
266
|
module DSL
|
@@ -3,15 +3,19 @@ module Ridley
|
|
3
3
|
class << self
|
4
4
|
# @param [Ridley::Connection] connection
|
5
5
|
# @param [Array] checksums
|
6
|
+
# @option options [Integer] :size (12)
|
7
|
+
# size of the upload pool
|
6
8
|
#
|
7
9
|
# @return [Ridley::Sandbox]
|
8
|
-
def create(connection, checksums = [])
|
10
|
+
def create(connection, checksums = [], options = {})
|
11
|
+
options.reverse_merge!(size: 12)
|
12
|
+
|
9
13
|
sumhash = { checksums: Hash.new }.tap do |chks|
|
10
14
|
Array(checksums).each { |chk| chks[:checksums][chk] = nil }
|
11
15
|
end
|
12
16
|
|
13
17
|
attrs = connection.post("sandboxes", sumhash.to_json).body
|
14
|
-
|
18
|
+
pool(size: options[:size], args: [connection, attrs[:sandbox_id], attrs[:checksums]])
|
15
19
|
end
|
16
20
|
|
17
21
|
# Checksum the file at the given filepath for a Chef API.
|
@@ -43,23 +47,51 @@ module Ridley
|
|
43
47
|
end
|
44
48
|
digest.hexdigest
|
45
49
|
end
|
50
|
+
|
51
|
+
def future(connection, *args)
|
52
|
+
puts connection
|
53
|
+
connection.future(*args)
|
54
|
+
end
|
46
55
|
end
|
47
56
|
|
57
|
+
include Celluloid
|
58
|
+
|
48
59
|
attr_reader :sandbox_id
|
49
60
|
attr_reader :checksums
|
50
61
|
|
51
62
|
def initialize(connection, id, checksums)
|
52
63
|
@connection = connection
|
53
64
|
@sandbox_id = id
|
54
|
-
@checksums
|
65
|
+
@checksums = checksums
|
55
66
|
end
|
56
67
|
|
57
68
|
def checksum(chk_id)
|
58
69
|
checksums.fetch(chk_id.to_sym)
|
59
70
|
end
|
60
71
|
|
72
|
+
# Concurrently upload multiple files into a sandbox
|
73
|
+
#
|
74
|
+
# @param [Hash] checksums
|
75
|
+
# a hash of file checksums and file paths
|
76
|
+
#
|
77
|
+
# @example uploading multiple checksums
|
78
|
+
#
|
79
|
+
# sandbox.multi_upload(
|
80
|
+
# "e5a0f6b48d0712382295ff30bec1f9cc" => "/Users/reset/code/rbenv-cookbook/recipes/default.rb",
|
81
|
+
# "de6532a7fbe717d52020dc9f3ae47dbe" => "/Users/reset/code/rbenv-cookbook/recipes/ohai_plugin.rb"
|
82
|
+
# )
|
83
|
+
def multi_upload(checksums)
|
84
|
+
checksums.collect do |chk_id, path|
|
85
|
+
future.upload(chk_id, path)
|
86
|
+
end.map(&:value)
|
87
|
+
end
|
88
|
+
|
89
|
+
# Upload one file into the sandbox for the given checksum id
|
90
|
+
#
|
61
91
|
# @param [String] chk_id
|
92
|
+
# checksum of the file being uploaded
|
62
93
|
# @param [String] path
|
94
|
+
# path to the file to upload
|
63
95
|
#
|
64
96
|
# @return [Hash, nil]
|
65
97
|
def upload(chk_id, path)
|
@@ -85,9 +117,9 @@ module Ridley
|
|
85
117
|
# value of the given checksum.
|
86
118
|
conn = connection.send(:conn).dup
|
87
119
|
|
88
|
-
url
|
120
|
+
url = URI(checksum[:url])
|
89
121
|
upload_path = url.path
|
90
|
-
url.path
|
122
|
+
url.path = ""
|
91
123
|
|
92
124
|
conn.url_prefix = url.to_s
|
93
125
|
|
@@ -95,7 +127,7 @@ module Ridley
|
|
95
127
|
end
|
96
128
|
|
97
129
|
def commit
|
98
|
-
connection.put("sandboxes/#{sandbox_id}",
|
130
|
+
connection.put("sandboxes/#{sandbox_id}", MultiJson.encode(is_completed: true)).body
|
99
131
|
end
|
100
132
|
|
101
133
|
def to_s
|
data/lib/ridley/ssh/response.rb
CHANGED
@@ -1,7 +1,22 @@
|
|
1
1
|
module Ridley
|
2
2
|
class SSH
|
3
3
|
# @author Jamie Winsor <jamie@vialstudios.com>
|
4
|
-
class Response
|
4
|
+
class Response
|
5
|
+
attr_reader :host
|
6
|
+
|
7
|
+
attr_accessor :stdout
|
8
|
+
attr_accessor :stderr
|
9
|
+
attr_accessor :exit_code
|
10
|
+
attr_accessor :exit_signal
|
11
|
+
|
12
|
+
def initialize(host, options = {})
|
13
|
+
@host = host
|
14
|
+
@stdout = options[:stdout] || String.new
|
15
|
+
@stderr = options[:stderr] || String.new
|
16
|
+
@exit_code = options[:exit_code] || -1
|
17
|
+
@exit_signal = options[:exit_signal] || nil
|
18
|
+
end
|
19
|
+
|
5
20
|
# Return true if the response was not successful
|
6
21
|
#
|
7
22
|
# @return [Boolean]
|