ridley 0.7.0.beta → 0.7.0.rc1
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.md +51 -54
- data/lib/ridley.rb +7 -13
- data/lib/ridley/client.rb +251 -0
- data/lib/ridley/connection.rb +32 -188
- data/lib/ridley/middleware/chef_auth.rb +4 -1
- data/lib/ridley/resource.rb +36 -42
- data/lib/ridley/resources.rb +3 -0
- data/lib/ridley/resources/{client.rb → client_resource.rb} +7 -20
- data/lib/ridley/resources/cookbook_resource.rb +121 -0
- data/lib/ridley/resources/{data_bag_item.rb → data_bag_item_resource.rb} +52 -63
- data/lib/ridley/resources/data_bag_resource.rb +74 -0
- data/lib/ridley/resources/encrypted_data_bag_item_resource.rb +55 -0
- data/lib/ridley/resources/{environment.rb → environment_resource.rb} +8 -21
- data/lib/ridley/resources/{node.rb → node_resource.rb} +24 -37
- data/lib/ridley/resources/{role.rb → role_resource.rb} +1 -14
- data/lib/ridley/resources/sandbox_resource.rb +86 -0
- data/lib/ridley/resources/search.rb +24 -55
- data/lib/ridley/sandbox_uploader.rb +118 -0
- data/lib/ridley/ssh.rb +2 -2
- data/lib/ridley/ssh/worker.rb +2 -1
- data/lib/ridley/version.rb +1 -1
- data/ridley.gemspec +1 -1
- data/spec/acceptance/bootstrapping_spec.rb +1 -1
- data/spec/acceptance/client_resource_spec.rb +18 -20
- data/spec/acceptance/cookbook_resource_spec.rb +4 -22
- data/spec/acceptance/data_bag_item_resource_spec.rb +5 -7
- data/spec/acceptance/data_bag_resource_spec.rb +4 -6
- data/spec/acceptance/environment_resource_spec.rb +14 -16
- data/spec/acceptance/node_resource_spec.rb +12 -14
- data/spec/acceptance/role_resource_spec.rb +13 -15
- data/spec/acceptance/sandbox_resource_spec.rb +7 -9
- data/spec/acceptance/search_resource_spec.rb +6 -8
- data/spec/support/shared_examples/ridley_resource.rb +23 -22
- data/spec/unit/ridley/client_spec.rb +153 -0
- data/spec/unit/ridley/connection_spec.rb +8 -221
- data/spec/unit/ridley/resources/{client_spec.rb → client_resource_spec.rb} +4 -4
- data/spec/unit/ridley/resources/cookbook_resource_spec.rb +5 -0
- data/spec/unit/ridley/resources/{data_bag_item_spec.rb → data_bag_item_resource_spec.rb} +2 -2
- data/spec/unit/ridley/resources/{data_bag_spec.rb → data_bag_resource_spec.rb} +3 -3
- data/spec/unit/ridley/resources/{environment_spec.rb → environment_resource_spec.rb} +4 -4
- data/spec/unit/ridley/resources/{node_spec.rb → node_resource_spec.rb} +4 -4
- data/spec/unit/ridley/resources/{role_spec.rb → role_resource_spec.rb} +3 -3
- data/spec/unit/ridley/resources/sandbox_resource_spec.rb +172 -0
- data/spec/unit/ridley/resources/search_spec.rb +34 -30
- data/spec/unit/ridley/sandbox_uploader_spec.rb +99 -0
- data/spec/unit/ridley/ssh_spec.rb +2 -2
- data/spec/unit/ridley_spec.rb +4 -12
- metadata +36 -28
- data/lib/ridley/dsl.rb +0 -58
- data/lib/ridley/resources/cookbook.rb +0 -51
- data/lib/ridley/resources/data_bag.rb +0 -81
- data/lib/ridley/resources/encrypted_data_bag_item.rb +0 -54
- data/lib/ridley/resources/sandbox.rb +0 -154
- data/spec/unit/ridley/resources/cookbook_spec.rb +0 -5
data/README.md
CHANGED
@@ -21,9 +21,9 @@ Require Ridley into your application
|
|
21
21
|
|
22
22
|
require 'ridley'
|
23
23
|
|
24
|
-
## Creating a new
|
24
|
+
## Creating a new Ridley client
|
25
25
|
|
26
|
-
conn = Ridley
|
26
|
+
conn = Ridley.new(
|
27
27
|
server_url: "https://api.opscode.com",
|
28
28
|
client_name: "reset",
|
29
29
|
client_key: "/Users/reset/.chef/reset.pem",
|
@@ -38,15 +38,12 @@ Creating a new connection requires you to specify at minimum:
|
|
38
38
|
|
39
39
|
An optional organization option can be specified if you are working with Hosted or Private Chef (OHC/OPC). For a full list of available options see the [yard documentation](http://rubydoc.info/gems/ridley).
|
40
40
|
|
41
|
-
|
41
|
+
Connections can also be instantiated by a helper function: `Ridley.new`
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
Ridley.connection(
|
43
|
+
Ridley.new(
|
46
44
|
server_url: "https://api.opscode.com",
|
47
45
|
client_name: "reset",
|
48
|
-
client_key: "/Users/reset/.chef/reset.pem"
|
49
|
-
organization: "ridley"
|
46
|
+
client_key: "/Users/reset/.chef/reset.pem"
|
50
47
|
)
|
51
48
|
|
52
49
|
Using a connection object you can interact with collections of resources on a Chef server. Resources are:
|
@@ -60,7 +57,7 @@ Using a connection object you can interact with collections of resources on a Ch
|
|
60
57
|
|
61
58
|
Here is a simple example of instantiating a new connection and listing all of the roles on a Chef server.
|
62
59
|
|
63
|
-
conn = Ridley.
|
60
|
+
conn = Ridley.new(...)
|
64
61
|
conn.role.all => []
|
65
62
|
|
66
63
|
For more information scroll down to the Manipulating Chef Resources section of this README.
|
@@ -69,7 +66,7 @@ For more information scroll down to the Manipulating Chef Resources section of t
|
|
69
66
|
|
70
67
|
An alternative syntax is provided if you want to perform multiple requests, in order, on a connection.
|
71
68
|
|
72
|
-
conn = Ridley.
|
69
|
+
conn = Ridley.new(...)
|
73
70
|
|
74
71
|
conn.sync do
|
75
72
|
role.all
|
@@ -104,18 +101,18 @@ All resource can be listed, created, retrieved, updated, or destroyed. Some reso
|
|
104
101
|
|
105
102
|
You use a connection to interact with the resources on the remote Chef server it is pointing to. For example, if you wanted to get a list of all of the roles on your Chef server:
|
106
103
|
|
107
|
-
conn = Ridley.
|
104
|
+
conn = Ridley.new(...)
|
108
105
|
conn.role.all => []
|
109
106
|
|
110
|
-
Calling `role.all` on the connection object will return an array of Ridley::
|
107
|
+
Calling `role.all` on the connection object will return an array of Ridley::RoleResource objects. All of the resources can be listed, not just Roles:
|
111
108
|
|
112
|
-
conn = Ridley.
|
113
|
-
conn.node.all => [<#Ridley::
|
114
|
-
conn.role.all => [<#Ridley::
|
115
|
-
conn.environment.all => [<#Ridley::
|
116
|
-
conn.client.all => [<#Ridley::
|
117
|
-
conn.cookbook.all => [<#Ridley::
|
118
|
-
conn.data_bag.all => [<#Ridley::
|
109
|
+
conn = Ridley.new(...)
|
110
|
+
conn.node.all => [<#Ridley::NodeResource>]
|
111
|
+
conn.role.all => [<#Ridley::RoleResource>]
|
112
|
+
conn.environment.all => [<#Ridley::EnvironmentResource>]
|
113
|
+
conn.client.all => [<#Ridley::ClientResource>]
|
114
|
+
conn.cookbook.all => [<#Ridley::CookbookResource>]
|
115
|
+
conn.data_bag.all => [<#Ridley::DataBagResource>]
|
119
116
|
|
120
117
|
### Creating a resource
|
121
118
|
|
@@ -123,24 +120,24 @@ A new resource can be created in a few ways
|
|
123
120
|
|
124
121
|
_Create by instantiate and save_
|
125
122
|
|
126
|
-
conn = Ridley.
|
123
|
+
conn = Ridley.new(...)
|
127
124
|
obj = conn.role.new
|
128
125
|
|
129
126
|
obj.name = "reset"
|
130
|
-
obj.save => <#Ridley::
|
127
|
+
obj.save => <#Ridley::RoleResource: @name="reset">
|
131
128
|
|
132
129
|
_Create by the `create` function with attribute hash_
|
133
130
|
|
134
|
-
conn = Ridley.
|
135
|
-
conn.role.create(name: "reset") => <#Ridley::
|
131
|
+
conn = Ridley.new(...)
|
132
|
+
conn.role.create(name: "reset") => <#Ridley::RoleResource: @name="reset">
|
136
133
|
|
137
134
|
_Create by the `create` function with a resource object_
|
138
135
|
|
139
|
-
conn = Ridley.
|
136
|
+
conn = Ridley.new(...)
|
140
137
|
obj = conn.role.new
|
141
138
|
|
142
139
|
obj.name = "reset"
|
143
|
-
conn.role.create(obj) => <#Ridley::
|
140
|
+
conn.role.create(obj) => <#Ridley::RoleResource: @name="reset">
|
144
141
|
|
145
142
|
Each of these methods is identical, it is up to you on how you'd like to create new resources.
|
146
143
|
|
@@ -152,14 +149,14 @@ Both `find` and `find!` will return a resource but if the resource is not found
|
|
152
149
|
|
153
150
|
If you were following allong in the previous section we created a role named `reset`. We'll assume that role has been created in this next example.
|
154
151
|
|
155
|
-
conn = Ridley.
|
152
|
+
conn = Ridley.new(...)
|
156
153
|
|
157
|
-
conn.role.find("reset") => <#Ridley::
|
158
|
-
conn.role.find!("reset") => <#Ridley::
|
154
|
+
conn.role.find("reset") => <#Ridley::RoleResource: @name="reset">
|
155
|
+
conn.role.find!("reset") => <#Ridley::RoleResource: @name="reset">
|
159
156
|
|
160
157
|
Now if we attempt to find a role that does not exist on the Chef server
|
161
158
|
|
162
|
-
conn = Ridley.
|
159
|
+
conn = Ridley.new(...)
|
163
160
|
|
164
161
|
conn.role.find("not_there") => nil
|
165
162
|
conn.role.find!("not_there") =>
|
@@ -182,24 +179,24 @@ Like creating a resource, updating a resource can also be expressed a few differ
|
|
182
179
|
|
183
180
|
_Update by the `update` function with an id and attribute hash_
|
184
181
|
|
185
|
-
conn = Ridley.
|
186
|
-
conn.role.update("reset", description: "testing updates!") => <#Ridley::
|
182
|
+
conn = Ridley.new(...)
|
183
|
+
conn.role.update("reset", description: "testing updates!") => <#Ridley::RoleResource: @name="reset", @description="testing updates!">
|
187
184
|
|
188
185
|
_Update by the `update` function with a resource object_
|
189
186
|
|
190
|
-
conn = Ridley.
|
187
|
+
conn = Ridley.new(...)
|
191
188
|
obj = conn.role.find("reset")
|
192
189
|
obj.description = "resource object!"
|
193
190
|
|
194
|
-
conn.role.update(obj) => <#Ridley::
|
191
|
+
conn.role.update(obj) => <#Ridley::RoleResource: @name="reset", @description="resource object!">
|
195
192
|
|
196
193
|
_Update by saving a resource object_
|
197
194
|
|
198
|
-
conn = Ridley.
|
195
|
+
conn = Ridley.new(...)
|
199
196
|
obj = conn.role.find("reset")
|
200
197
|
|
201
198
|
obj.description = "saving an object!"
|
202
|
-
obj.save => <#Ridley::
|
199
|
+
obj.save => <#Ridley::RoleResource: @name="reset", @description="saving an object!">
|
203
200
|
|
204
201
|
### Deleting a resource
|
205
202
|
|
@@ -207,19 +204,19 @@ Like creating or updating a resource, there are a few ways deleting a resource c
|
|
207
204
|
|
208
205
|
_Delete by the `delete` function with an id_
|
209
206
|
|
210
|
-
conn = Ridley.
|
211
|
-
conn.role.delete("reset") => <#Ridley::
|
207
|
+
conn = Ridley.new(...)
|
208
|
+
conn.role.delete("reset") => <#Ridley::RoleResource: @name="reset">
|
212
209
|
|
213
210
|
_Delete by the `delete` function with a resource object_
|
214
211
|
|
215
|
-
conn = Ridley.
|
212
|
+
conn = Ridley.new(...)
|
216
213
|
obj = conn.role.find("reset")
|
217
214
|
|
218
|
-
conn.role.delete(obj) => <#Ridley::
|
215
|
+
conn.role.delete(obj) => <#Ridley::RoleResource: @name="reset">
|
219
216
|
|
220
217
|
_Delete by the `destroy` function on a resource object_
|
221
218
|
|
222
|
-
conn = Ridley.
|
219
|
+
conn = Ridley.new(...)
|
223
220
|
obj = conn.role.find("reset")
|
224
221
|
|
225
222
|
obj.destroy => true
|
@@ -228,21 +225,21 @@ _Delete by the `destroy` function on a resource object_
|
|
228
225
|
|
229
226
|
_Regenerate function on a context with an id_
|
230
227
|
|
231
|
-
conn = Ridley.
|
232
|
-
conn.client.regenerate_key("jwinsor") => <#Ridley::
|
228
|
+
conn = Ridley.new(...)
|
229
|
+
conn.client.regenerate_key("jwinsor") => <#Ridley::ClientResource: @name="jwinsor", @private_key="HIDDEN">
|
233
230
|
|
234
231
|
_Regenerate function on an instantiated resource object_
|
235
232
|
|
236
|
-
conn = Ridley.
|
233
|
+
conn = Ridley.new(...)
|
237
234
|
obj = conn.client.find("jwinsor")
|
238
235
|
|
239
|
-
obj.regenerate_key => <#Ridley::
|
236
|
+
obj.regenerate_key => <#Ridley::ClientResource: @name="jwinsor", @private_key="HIDDEN">
|
240
237
|
|
241
238
|
## Manipulating Data Bags and Data Bag Items
|
242
239
|
|
243
240
|
A data bag is managed exactly the same as any other Chef resource
|
244
241
|
|
245
|
-
conn = Ridley.
|
242
|
+
conn = Ridley.new(...)
|
246
243
|
conn.data_bag.create("ridley-test")
|
247
244
|
|
248
245
|
You can create, delete, update, or retrieve a data bag exactly how you would expect if you read through the
|
@@ -252,15 +249,15 @@ Unlike a role, node, client, or environment, a data bag is a container for other
|
|
252
249
|
|
253
250
|
### Creating a Data Bag Item
|
254
251
|
|
255
|
-
conn = Ridley.
|
252
|
+
conn = Ridley.new(...)
|
256
253
|
data_bag = conn.data_bag.create("ridley-test")
|
257
254
|
|
258
255
|
data_bag.item.create(id: "appconfig", host: "reset.local", user: "jwinsor") =>
|
259
|
-
<#Ridley::
|
256
|
+
<#Ridley::DataBagItemResource: @id="appconfig", @host="reset.local", @user="jwinsor">
|
260
257
|
|
261
258
|
### Saving a Data Bag Item
|
262
259
|
|
263
|
-
conn = Ridley.
|
260
|
+
conn = Ridley.new(...)
|
264
261
|
data_bag = conn.data_bag.create("ridley-test")
|
265
262
|
|
266
263
|
dbi = data_bag.item.new
|
@@ -270,7 +267,7 @@ Unlike a role, node, client, or environment, a data bag is a container for other
|
|
270
267
|
|
271
268
|
## Searching
|
272
269
|
|
273
|
-
conn = Ridley.
|
270
|
+
conn = Ridley.new(...)
|
274
271
|
conn.search(:node)
|
275
272
|
conn.search(:node, "name:ridley-test.local")
|
276
273
|
|
@@ -293,7 +290,7 @@ Given the previous example you could set the default node attribute with the `se
|
|
293
290
|
|
294
291
|
Setting the `node[:my_app][:billing][:enabled]` node level attribute on the node "jwinsor-1"
|
295
292
|
|
296
|
-
conn = Ridley.
|
293
|
+
conn = Ridley.new
|
297
294
|
conn.sync do
|
298
295
|
obj = node.find("jwinsor-1")
|
299
296
|
obj.set_attribute("my_app.billing.enabled", false)
|
@@ -304,7 +301,7 @@ Setting the `node[:my_app][:billing][:enabled]` node level attribute on the node
|
|
304
301
|
|
305
302
|
Setting a default environment attribute is just like setting a node level default attribute
|
306
303
|
|
307
|
-
conn = Ridley.
|
304
|
+
conn = Ridley.new
|
308
305
|
conn.sync do
|
309
306
|
obj = environment.find("production")
|
310
307
|
obj.set_default_attribute("my_app.proxy.enabled", false)
|
@@ -313,7 +310,7 @@ Setting a default environment attribute is just like setting a node level defaul
|
|
313
310
|
|
314
311
|
And the same goes for setting an environment level override attribute
|
315
312
|
|
316
|
-
conn = Ridley.
|
313
|
+
conn = Ridley.new
|
317
314
|
conn.sync do
|
318
315
|
obj = environment.find("production")
|
319
316
|
obj.set_override_attribute("my_app.webapp.enabled", false)
|
@@ -322,7 +319,7 @@ And the same goes for setting an environment level override attribute
|
|
322
319
|
|
323
320
|
### Role Attributes
|
324
321
|
|
325
|
-
conn = Ridley.
|
322
|
+
conn = Ridley.new
|
326
323
|
conn.sync do
|
327
324
|
obj = role.find("why_god_why")
|
328
325
|
obj.set_default_attribute("my_app.proxy.enabled", false)
|
@@ -337,7 +334,7 @@ And the same goes for setting an environment level override attribute
|
|
337
334
|
|
338
335
|
## Bootstrapping nodes
|
339
336
|
|
340
|
-
conn = Ridley.
|
337
|
+
conn = Ridley.new(
|
341
338
|
server_url: "https://api.opscode.com",
|
342
339
|
organization: "vialstudios",
|
343
340
|
validator_client: "vialstudios-validator",
|
data/lib/ridley.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'chozo'
|
2
|
-
require 'active_support/core_ext'
|
3
2
|
require 'celluloid'
|
4
3
|
require 'faraday'
|
5
4
|
require 'addressable/uri'
|
@@ -25,19 +24,13 @@ module Ridley
|
|
25
24
|
CHEF_VERSION = '10.16.4'.freeze
|
26
25
|
|
27
26
|
autoload :Bootstrapper, 'ridley/bootstrapper'
|
28
|
-
autoload :Client, 'ridley/
|
27
|
+
autoload :Client, 'ridley/client'
|
29
28
|
autoload :Connection, 'ridley/connection'
|
30
29
|
autoload :ChainLink, 'ridley/chain_link'
|
31
|
-
autoload :Cookbook, 'ridley/resources/cookbook'
|
32
|
-
autoload :DataBag, 'ridley/resources/data_bag'
|
33
|
-
autoload :DataBagItem, 'ridley/resources/data_bag_item'
|
34
30
|
autoload :DSL, 'ridley/dsl'
|
35
|
-
autoload :Environment, 'ridley/resources/environment'
|
36
31
|
autoload :Logging, 'ridley/logging'
|
37
|
-
autoload :Node, 'ridley/resources/node'
|
38
32
|
autoload :Resource, 'ridley/resource'
|
39
|
-
autoload :
|
40
|
-
autoload :Search, 'ridley/resources/search'
|
33
|
+
autoload :SandboxUploader, 'ridley/sandbox_uploader'
|
41
34
|
autoload :SSH, 'ridley/ssh'
|
42
35
|
|
43
36
|
class << self
|
@@ -49,12 +42,12 @@ module Ridley
|
|
49
42
|
def_delegator "Ridley::Logging", :logger=
|
50
43
|
def_delegator "Ridley::Logging", :set_logger
|
51
44
|
|
52
|
-
def
|
53
|
-
|
45
|
+
def new(*args)
|
46
|
+
Client.new(*args)
|
54
47
|
end
|
55
48
|
|
56
|
-
def
|
57
|
-
|
49
|
+
def open(*args, &block)
|
50
|
+
Client.open(*args, &block)
|
58
51
|
end
|
59
52
|
|
60
53
|
# @return [Pathname]
|
@@ -67,3 +60,4 @@ end
|
|
67
60
|
Celluloid.logger = Ridley.logger
|
68
61
|
|
69
62
|
require 'ridley/middleware'
|
63
|
+
require 'ridley/resources'
|
@@ -0,0 +1,251 @@
|
|
1
|
+
module Ridley
|
2
|
+
# @author Jamie Winsor <jamie@vialstudios.com>
|
3
|
+
#
|
4
|
+
# @example
|
5
|
+
# connection = Ridley::Client.new
|
6
|
+
# connection.role.all
|
7
|
+
#
|
8
|
+
# connection.role.find("reset") => Ridley::RoleResource.find(connection, "reset")
|
9
|
+
#
|
10
|
+
# @example instantiating new resources
|
11
|
+
# connection = Ridley::Connection.new
|
12
|
+
# connection.role.new(name: "hello") => <#Ridley::RoleResource: @name="hello">
|
13
|
+
#
|
14
|
+
# New instances of resources can be instantiated by calling new on the Ridley::Context. These messages
|
15
|
+
# will be send to the Chef resource's class in Ridley and can be treated as a normal Ruby object. Each
|
16
|
+
# instantiated object will have the connection information contained within so you can do things like
|
17
|
+
# save a role after changing it's attributes.
|
18
|
+
#
|
19
|
+
# r = connection.role.new(name: "new-role")
|
20
|
+
# r.name => "new-role"
|
21
|
+
# r.name = "other-name"
|
22
|
+
# r.save
|
23
|
+
#
|
24
|
+
# connection.role.find("new-role") => <#Ridley::RoleResource: @name="new-role">
|
25
|
+
class Client < Celluloid::SupervisionGroup
|
26
|
+
class << self
|
27
|
+
def open(options = {}, &block)
|
28
|
+
cli = new(options)
|
29
|
+
cli.evaluate(&block)
|
30
|
+
ensure
|
31
|
+
cli.terminate if cli && cli.alive?
|
32
|
+
end
|
33
|
+
|
34
|
+
# @raise [ArgumentError]
|
35
|
+
#
|
36
|
+
# @return [Boolean]
|
37
|
+
def validate_options(options)
|
38
|
+
missing = (REQUIRED_OPTIONS - options.keys)
|
39
|
+
|
40
|
+
unless missing.empty?
|
41
|
+
missing.collect! { |opt| "'#{opt}'" }
|
42
|
+
raise ArgumentError, "Missing required option(s): #{missing.join(', ')}"
|
43
|
+
end
|
44
|
+
|
45
|
+
missing_values = options.slice(*REQUIRED_OPTIONS).select { |key, value| !value.present? }
|
46
|
+
unless missing_values.empty?
|
47
|
+
values = missing_values.keys.collect { |opt| "'#{opt}'" }
|
48
|
+
raise ArgumentError, "Missing value for required option(s): '#{values.join(', ')}'"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
REQUIRED_OPTIONS = [
|
54
|
+
:server_url,
|
55
|
+
:client_name,
|
56
|
+
:client_key
|
57
|
+
].freeze
|
58
|
+
|
59
|
+
extend Forwardable
|
60
|
+
include Ridley::Logging
|
61
|
+
|
62
|
+
def_delegator :connection, :build_url
|
63
|
+
def_delegator :connection, :scheme
|
64
|
+
def_delegator :connection, :host
|
65
|
+
def_delegator :connection, :port
|
66
|
+
def_delegator :connection, :path_prefix
|
67
|
+
def_delegator :connection, :url_prefix
|
68
|
+
|
69
|
+
def_delegator :connection, :client_key
|
70
|
+
def_delegator :connection, :client_key=
|
71
|
+
def_delegator :connection, :client_name
|
72
|
+
def_delegator :connection, :client_name=
|
73
|
+
|
74
|
+
attr_accessor :validator_client
|
75
|
+
attr_accessor :validator_path
|
76
|
+
attr_accessor :encrypted_data_bag_secret_path
|
77
|
+
attr_accessor :ssh
|
78
|
+
|
79
|
+
# @option options [String] :server_url
|
80
|
+
# URL to the Chef API
|
81
|
+
# @option options [String] :client_name
|
82
|
+
# name of the client used to authenticate with the Chef API
|
83
|
+
# @option options [String] :client_key
|
84
|
+
# filepath to the client's private key used to authenticate with the Chef API
|
85
|
+
# @option options [String] :validator_client (nil)
|
86
|
+
# @option options [String] :validator_path (nil)
|
87
|
+
# @option options [String] :encrypted_data_bag_secret_path (nil)
|
88
|
+
# @option options [Hash] :ssh (Hash.new)
|
89
|
+
# * :user (String) a shell user that will login to each node and perform the bootstrap command on (required)
|
90
|
+
# * :password (String) the password for the shell user that will perform the bootstrap
|
91
|
+
# * :keys (Array, String) an array of keys (or a single key) to authenticate the ssh user with instead of a password
|
92
|
+
# * :timeout (Float) [5.0] timeout value for SSH bootstrap
|
93
|
+
# * :sudo (Boolean) [true] bootstrap with sudo
|
94
|
+
# @option options [Hash] :params
|
95
|
+
# URI query unencoded key/value pairs
|
96
|
+
# @option options [Hash] :headers
|
97
|
+
# unencoded HTTP header key/value pairs
|
98
|
+
# @option options [Hash] :request
|
99
|
+
# request options
|
100
|
+
# @option options [Hash] :ssl
|
101
|
+
# * :verify (Boolean) [true] set to false to disable SSL verification
|
102
|
+
# @option options [URI, String, Hash] :proxy
|
103
|
+
# URI, String, or Hash of HTTP proxy options
|
104
|
+
def initialize(options = {})
|
105
|
+
log.info { "Ridley starting..." }
|
106
|
+
options = options.reverse_merge(
|
107
|
+
ssh: Hash.new
|
108
|
+
).deep_symbolize_keys
|
109
|
+
self.class.validate_options(options)
|
110
|
+
|
111
|
+
@ssh = options[:ssh]
|
112
|
+
@validator_client = options[:validator_client]
|
113
|
+
|
114
|
+
options[:client_key] = File.expand_path(options[:client_key])
|
115
|
+
|
116
|
+
if options[:validator_path]
|
117
|
+
@validator_path = File.expand_path(options[:validator_path])
|
118
|
+
end
|
119
|
+
|
120
|
+
if options[:encrypted_data_bag_secret_path]
|
121
|
+
@encrypted_data_bag_secret_path = File.expand_path(options[:encrypted_data_bag_secret_path])
|
122
|
+
end
|
123
|
+
|
124
|
+
unless options[:client_key].present? && File.exist?(options[:client_key])
|
125
|
+
raise Errors::ClientKeyFileNotFound, "client key not found at: '#{options[:client_key]}'"
|
126
|
+
end
|
127
|
+
|
128
|
+
super(Celluloid::Registry.new)
|
129
|
+
pool(Ridley::Connection, size: 4, args: [
|
130
|
+
options[:server_url],
|
131
|
+
options[:client_name],
|
132
|
+
options[:client_key],
|
133
|
+
options.slice(*Connection::VALID_OPTIONS)
|
134
|
+
], as: :connection_pool)
|
135
|
+
end
|
136
|
+
|
137
|
+
# @return [Ridley::ChainLink]
|
138
|
+
def client
|
139
|
+
ChainLink.new(Actor.current, Ridley::ClientResource)
|
140
|
+
end
|
141
|
+
|
142
|
+
# @return [Ridley::ChainLink]
|
143
|
+
def cookbook
|
144
|
+
ChainLink.new(Actor.current, Ridley::CookbookResource)
|
145
|
+
end
|
146
|
+
|
147
|
+
# @return [Ridley::ChainLink]
|
148
|
+
def data_bag
|
149
|
+
ChainLink.new(Actor.current, Ridley::DataBagResource)
|
150
|
+
end
|
151
|
+
|
152
|
+
# @return [Ridley::ChainLink]
|
153
|
+
def environment
|
154
|
+
ChainLink.new(Actor.current, Ridley::EnvironmentResource)
|
155
|
+
end
|
156
|
+
|
157
|
+
# @return [Ridley::ChainLink]
|
158
|
+
def node
|
159
|
+
ChainLink.new(Actor.current, Ridley::NodeResource)
|
160
|
+
end
|
161
|
+
|
162
|
+
# @return [Ridley::ChainLink]
|
163
|
+
def role
|
164
|
+
ChainLink.new(Actor.current, Ridley::RoleResource)
|
165
|
+
end
|
166
|
+
|
167
|
+
# @return [Ridley::ChainLink]
|
168
|
+
def sandbox
|
169
|
+
ChainLink.new(Actor.current, Ridley::SandboxResource)
|
170
|
+
end
|
171
|
+
|
172
|
+
# Creates an runs a new Ridley::Search
|
173
|
+
#
|
174
|
+
# @see Ridley::Search#run
|
175
|
+
#
|
176
|
+
# @param [String, Symbol] index
|
177
|
+
# @param [String, nil] query
|
178
|
+
#
|
179
|
+
# @option options [String] :sort
|
180
|
+
# @option options [Integer] :rows
|
181
|
+
# @option options [Integer] :start
|
182
|
+
#
|
183
|
+
# @return [Hash]
|
184
|
+
def search(index, query = nil, options = {})
|
185
|
+
Ridley::Search.new(Actor.current, index, query, options).run
|
186
|
+
end
|
187
|
+
|
188
|
+
# Return the array of all possible search indexes for the including connection
|
189
|
+
#
|
190
|
+
# @example
|
191
|
+
# conn = Ridley.new(...)
|
192
|
+
# conn.search_indexes =>
|
193
|
+
# [:client, :environment, :node, :role, :"ridley-two", :"ridley-one"]
|
194
|
+
#
|
195
|
+
# @return [Array<Symbol, String>]
|
196
|
+
def search_indexes
|
197
|
+
Ridley::Search.indexes(Actor.current)
|
198
|
+
end
|
199
|
+
|
200
|
+
# The encrypted data bag secret for this connection.
|
201
|
+
#
|
202
|
+
# @raise [Ridley::Errors::EncryptedDataBagSecretNotFound]
|
203
|
+
#
|
204
|
+
# @return [String, nil]
|
205
|
+
def encrypted_data_bag_secret
|
206
|
+
return nil if encrypted_data_bag_secret_path.nil?
|
207
|
+
|
208
|
+
IO.read(encrypted_data_bag_secret_path).chomp
|
209
|
+
rescue Errno::ENOENT => e
|
210
|
+
raise Errors::EncryptedDataBagSecretNotFound, "Encrypted data bag secret provided but not found at '#{encrypted_data_bag_secret_path}'"
|
211
|
+
end
|
212
|
+
|
213
|
+
def server_url
|
214
|
+
self.url_prefix.to_s
|
215
|
+
end
|
216
|
+
|
217
|
+
def evaluate(&block)
|
218
|
+
unless block_given?
|
219
|
+
raise LocalJumpError, "no block given (yield)"
|
220
|
+
end
|
221
|
+
|
222
|
+
@self_before_instance_eval = eval("self", block.binding)
|
223
|
+
instance_eval(&block)
|
224
|
+
end
|
225
|
+
alias_method :sync, :evaluate
|
226
|
+
|
227
|
+
def finalize
|
228
|
+
connection.terminate if connection.alive?
|
229
|
+
end
|
230
|
+
|
231
|
+
def connection
|
232
|
+
registry[:connection_pool]
|
233
|
+
end
|
234
|
+
|
235
|
+
private
|
236
|
+
|
237
|
+
attr_reader :registry
|
238
|
+
|
239
|
+
def method_missing(method, *args, &block)
|
240
|
+
if block_given?
|
241
|
+
@self_before_instance_eval ||= eval("self", block.binding)
|
242
|
+
end
|
243
|
+
|
244
|
+
if @self_before_instance_eval.nil?
|
245
|
+
super
|
246
|
+
end
|
247
|
+
|
248
|
+
@self_before_instance_eval.send(method, *args, &block)
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|