ridley 0.10.2 → 0.11.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.
Files changed (85) hide show
  1. data/README.md +147 -216
  2. data/lib/ridley.rb +2 -0
  3. data/lib/ridley/bootstrap_bindings/unix_template_binding.rb +21 -25
  4. data/lib/ridley/bootstrap_bindings/windows_template_binding.rb +29 -34
  5. data/lib/ridley/bootstrapper.rb +2 -2
  6. data/lib/ridley/bootstrapper/context.rb +5 -5
  7. data/lib/ridley/chef.rb +0 -1
  8. data/lib/ridley/chef/cookbook.rb +0 -9
  9. data/lib/ridley/chef_object.rb +128 -0
  10. data/lib/ridley/chef_objects.rb +3 -0
  11. data/lib/ridley/chef_objects/client_object.rb +55 -0
  12. data/lib/ridley/chef_objects/cookbook_object.rb +190 -0
  13. data/lib/ridley/chef_objects/data_bag_item_obect.rb +104 -0
  14. data/lib/ridley/chef_objects/data_bag_object.rb +31 -0
  15. data/lib/ridley/chef_objects/environment_object.rb +59 -0
  16. data/lib/ridley/chef_objects/node_object.rb +161 -0
  17. data/lib/ridley/chef_objects/role_object.rb +62 -0
  18. data/lib/ridley/chef_objects/sandbox_object.rb +58 -0
  19. data/lib/ridley/client.rb +76 -45
  20. data/lib/ridley/connection.rb +1 -1
  21. data/lib/ridley/errors.rb +8 -1
  22. data/lib/ridley/host_connector.rb +26 -6
  23. data/lib/ridley/host_connector/ssh.rb +3 -3
  24. data/lib/ridley/host_connector/ssh/worker.rb +7 -9
  25. data/lib/ridley/host_connector/winrm/worker.rb +4 -5
  26. data/lib/ridley/mixin/bootstrap_binding.rb +1 -12
  27. data/lib/ridley/resource.rb +51 -171
  28. data/lib/ridley/resources/client_resource.rb +18 -68
  29. data/lib/ridley/resources/cookbook_resource.rb +181 -381
  30. data/lib/ridley/resources/data_bag_item_resource.rb +55 -161
  31. data/lib/ridley/resources/data_bag_resource.rb +20 -61
  32. data/lib/ridley/resources/environment_resource.rb +9 -64
  33. data/lib/ridley/resources/node_resource.rb +135 -311
  34. data/lib/ridley/resources/role_resource.rb +1 -57
  35. data/lib/ridley/resources/sandbox_resource.rb +80 -65
  36. data/lib/ridley/resources/search_resource.rb +99 -0
  37. data/lib/ridley/sandbox_uploader.rb +12 -52
  38. data/lib/ridley/version.rb +1 -1
  39. data/spec/acceptance/bootstrapping_spec.rb +1 -1
  40. data/spec/acceptance/client_resource_spec.rb +15 -37
  41. data/spec/acceptance/data_bag_item_resource_spec.rb +8 -14
  42. data/spec/acceptance/data_bag_resource_spec.rb +1 -1
  43. data/spec/acceptance/environment_resource_spec.rb +13 -22
  44. data/spec/acceptance/node_resource_spec.rb +10 -29
  45. data/spec/acceptance/role_resource_spec.rb +14 -13
  46. data/spec/acceptance/sandbox_resource_spec.rb +2 -2
  47. data/spec/support/shared_examples/ridley_resource.rb +2 -23
  48. data/spec/unit/ridley/bootstrap_bindings/unix_template_binding_spec.rb +3 -4
  49. data/spec/unit/ridley/bootstrap_bindings/windows_template_binding_spec.rb +3 -5
  50. data/spec/unit/ridley/bootstrapper/context_spec.rb +2 -3
  51. data/spec/unit/ridley/bootstrapper_spec.rb +1 -1
  52. data/spec/unit/ridley/chef_object_spec.rb +240 -0
  53. data/spec/unit/ridley/chef_objects/client_object_spec.rb +11 -0
  54. data/spec/unit/ridley/chef_objects/cookbook_object_spec.rb +93 -0
  55. data/spec/unit/ridley/chef_objects/data_bag_item_object_spec.rb +74 -0
  56. data/spec/unit/ridley/chef_objects/data_bag_object_spec.rb +9 -0
  57. data/spec/unit/ridley/chef_objects/environment_object_spec.rb +57 -0
  58. data/spec/unit/ridley/chef_objects/node_object_spec.rb +252 -0
  59. data/spec/unit/ridley/chef_objects/role_object_spec.rb +57 -0
  60. data/spec/unit/ridley/chef_objects/sandbox_object_spec.rb +66 -0
  61. data/spec/unit/ridley/client_spec.rb +51 -51
  62. data/spec/unit/ridley/host_connector/ssh/worker_spec.rb +4 -4
  63. data/spec/unit/ridley/host_connector/ssh_spec.rb +26 -24
  64. data/spec/unit/ridley/host_connector/winrm/worker_spec.rb +3 -4
  65. data/spec/unit/ridley/host_connector/winrm_spec.rb +4 -4
  66. data/spec/unit/ridley/host_connector_spec.rb +40 -3
  67. data/spec/unit/ridley/mixin/bootstrap_binding_spec.rb +1 -1
  68. data/spec/unit/ridley/resource_spec.rb +81 -109
  69. data/spec/unit/ridley/resources/client_resource_spec.rb +18 -33
  70. data/spec/unit/ridley/resources/cookbook_resource_spec.rb +56 -230
  71. data/spec/unit/ridley/resources/data_bag_item_resource_spec.rb +2 -57
  72. data/spec/unit/ridley/resources/data_bag_resource_spec.rb +12 -7
  73. data/spec/unit/ridley/resources/environment_resource_spec.rb +10 -118
  74. data/spec/unit/ridley/resources/node_resource_spec.rb +83 -394
  75. data/spec/unit/ridley/resources/role_resource_spec.rb +2 -56
  76. data/spec/unit/ridley/resources/sandbox_resource_spec.rb +139 -136
  77. data/spec/unit/ridley/resources/search_resource_spec.rb +234 -0
  78. data/spec/unit/ridley/sandbox_uploader_spec.rb +13 -58
  79. metadata +36 -17
  80. data/lib/ridley/chef/chefignore.rb +0 -76
  81. data/lib/ridley/resources/encrypted_data_bag_item_resource.rb +0 -55
  82. data/lib/ridley/resources/search.rb +0 -101
  83. data/spec/fixtures/chefignore +0 -8
  84. data/spec/unit/ridley/chef/chefignore_spec.rb +0 -40
  85. data/spec/unit/ridley/resources/search_spec.rb +0 -221
@@ -7,7 +7,7 @@ module Ridley
7
7
  autoload :Worker, 'ridley/host_connector/ssh/worker'
8
8
 
9
9
  class << self
10
- # @param [Ridley::NodeResource, Array<Ridley::NodeResource>] nodes
10
+ # @param [Ridley::NodeObject, Array<Ridley::NodeObject>] nodes
11
11
  # @param [Hash] options
12
12
  def start(nodes, options = {}, &block)
13
13
  runner = new(nodes, options)
@@ -16,7 +16,7 @@ module Ridley
16
16
 
17
17
  result
18
18
  ensure
19
- runner.terminate if runner && runner.alive?
19
+ runner.terminate if runner && runner.alive?
20
20
  end
21
21
  end
22
22
 
@@ -26,7 +26,7 @@ module Ridley
26
26
  attr_reader :nodes
27
27
  attr_reader :options
28
28
 
29
- # @param [Ridley::NodeResource, Array<Ridley::NodeResource>] nodes
29
+ # @param [Ridley::NodeObject, Array<Ridley::NodeObject>] nodes
30
30
  # @param [Hash] options
31
31
  # @see Net::SSH
32
32
  def initialize(nodes, options = {})
@@ -14,7 +14,7 @@ module Ridley
14
14
  attr_reader :options
15
15
 
16
16
  EMBEDDED_RUBY_PATH = '/opt/chef/embedded/bin/ruby'.freeze
17
-
17
+
18
18
  # @param [Hash] options
19
19
  def initialize(host, options = {})
20
20
  options = options.deep_symbolize_keys
@@ -104,16 +104,14 @@ module Ridley
104
104
  run(command)
105
105
  end
106
106
 
107
- # Executes a copy of the encrypted_data_bag_secret to the nodes
107
+ # Writes the given encrypted data bag secret to the node
108
+ #
109
+ # @param [String] secret
110
+ # your organization's encrypted data bag secret
108
111
  #
109
- # @param [String] encrypted_data_bag_secret_path
110
- # the path to the encrypted_data_bag_secret
111
- #
112
112
  # @return [#run]
113
- def put_secret(encrypted_data_bag_secret_path)
114
- secret = File.read(encrypted_data_bag_secret_path).chomp
113
+ def put_secret(secret)
115
114
  command = "echo '#{secret}' > /etc/chef/encrypted_data_bag_secret; chmod 0600 /etc/chef/encrypted_data_bag_secret"
116
-
117
115
  run(command)
118
116
  end
119
117
 
@@ -121,7 +119,7 @@ module Ridley
121
119
  #
122
120
  # @param [Array<String>] command_lines
123
121
  # An Array of lines of the command to be executed
124
- #
122
+ #
125
123
  # @return [#run]
126
124
  def ruby_script(command_lines)
127
125
  command = "#{EMBEDDED_RUBY_PATH} -e \"#{command_lines.join(';')}\""
@@ -118,14 +118,13 @@ module Ridley
118
118
  run("chef-client")
119
119
  end
120
120
 
121
- # Executes a copy of the encrypted_data_bag_secret to the nodes
121
+ # Writes the given encrypted data bag secret to the node
122
122
  #
123
- # @param [String] encrypted_data_bag_secret_path
124
- # the path to the encrypted_data_bag_secret
123
+ # @param [String] secret
124
+ # your organization's encrypted data bag secret
125
125
  #
126
126
  # @return [#run]
127
- def put_secret(encrypted_data_bag_secret_path)
128
- secret = File.read(encrypted_data_bag_secret_path).chomp
127
+ def put_secret(secret)
129
128
  command = "echo #{secret} > C:\\chef\\encrypted_data_bag_secret"
130
129
  run(command)
131
130
  end
@@ -39,7 +39,7 @@ module Ridley
39
39
  attr_reader :chef_version
40
40
  attr_reader :default_options
41
41
  attr_reader :validator_path
42
- attr_reader :encrypted_data_bag_secret_path
42
+ attr_reader :encrypted_data_bag_secret
43
43
  attr_reader :server_url
44
44
  attr_reader :validator_client
45
45
  attr_reader :node_name
@@ -57,17 +57,6 @@ module Ridley
57
57
  MultiJson.encode attributes.merge(run_list: run_list)
58
58
  end
59
59
 
60
- # @raise [Ridley::Errors::EncryptedDataBagSecretNotFound]
61
- #
62
- # @return [String, nil]
63
- def encrypted_data_bag_secret
64
- return unless encrypted_data_bag_secret_path
65
-
66
- IO.read(encrypted_data_bag_secret_path).chomp
67
- rescue Errno::ENOENT
68
- raise Errors::EncryptedDataBagSecretNotFound, "Error bootstrapping: Encrypted data bag secret provided but not found at '#{encrypted_data_bag_secret_path}'"
69
- end
70
-
71
60
  # The validation key to create a new client for the node
72
61
  #
73
62
  # @raise [Ridley::Errors::ValidatorNotFound]
@@ -2,21 +2,9 @@ module Ridley
2
2
  # @author Jamie Winsor <reset@riotgames.com>
3
3
  class Resource
4
4
  class << self
5
- # @return [String, nil]
6
- def chef_id
7
- @chef_id
8
- end
9
-
10
- # @param [String, Symbol] identifier
11
- #
12
- # @return [String]
13
- def set_chef_id(identifier)
14
- @chef_id = identifier.to_sym
15
- end
16
-
17
5
  # @return [String]
18
6
  def resource_path
19
- @resource_path ||= self.chef_type.pluralize
7
+ @resource_path ||= representation.chef_type.pluralize
20
8
  end
21
9
 
22
10
  # @param [String] path
@@ -26,191 +14,83 @@ module Ridley
26
14
  @resource_path = path
27
15
  end
28
16
 
29
- # @return [String]
30
- def chef_type
31
- @chef_type ||= self.class.name.underscore
32
- end
33
-
34
- # @param [String, Symbol] type
35
- #
36
- # @return [String]
37
- def set_chef_type(type)
38
- @chef_type = type.to_s
39
- attribute(:chef_type, default: type)
40
- end
41
-
42
- # @return [String, nil]
43
- def chef_json_class
44
- @chef_json_class
45
- end
46
-
47
- # @param [String, Symbol] klass
48
- #
49
- # @return [String]
50
- def set_chef_json_class(klass)
51
- @chef_json_class = klass
52
- attribute(:json_class, default: klass)
53
- end
54
-
55
- # @param [Ridley::Client] client
56
- #
57
- # @return [Array<Object>]
58
- def all(client)
59
- client.connection.get(self.resource_path).body.collect do |identity, location|
60
- new(client, self.chef_id => identity)
61
- end
62
- end
63
-
64
- # @param [Ridley::Client] client
65
- # @param [String, #chef_id] object
66
- #
67
- # @return [nil, Object]
68
- def find(client, object)
69
- find!(client, object)
70
- rescue Errors::ResourceNotFound
71
- nil
72
- end
73
-
74
- # @param [Ridley::Client] client
75
- # @param [String, #chef_id] object
76
- #
77
- # @raise [Errors::HTTPNotFound]
78
- # if a resource with the given chef_id is not found
79
- #
80
- # @return [Object]
81
- def find!(client, object)
82
- chef_id = object.respond_to?(:chef_id) ? object.chef_id : object
83
- new(client, client.connection.get("#{self.resource_path}/#{chef_id}").body)
84
- rescue Errors::HTTPNotFound => ex
85
- raise Errors::ResourceNotFound, ex
86
- end
87
-
88
- # @param [Ridley::Client] client
89
- # @param [#to_hash] object
90
- #
91
- # @return [Object]
92
- def create(client, object)
93
- resource = new(client, object.to_hash)
94
- new_attributes = client.connection.post(self.resource_path, resource.to_json).body
95
- resource.mass_assign(resource._attributes_.deep_merge(new_attributes))
96
- resource
97
- end
98
-
99
- # @param [Ridley::Client] client
100
- # @param [String, #chef_id] object
101
- #
102
- # @return [Object]
103
- def delete(client, object)
104
- chef_id = object.respond_to?(:chef_id) ? object.chef_id : object
105
- new(client, client.connection.delete("#{self.resource_path}/#{chef_id}").body)
106
- end
107
-
108
- # @param [Ridley::Client] client
109
- #
110
- # @return [Array<Object>]
111
- def delete_all(client)
112
- mutex = Mutex.new
113
- deleted = []
114
-
115
- all(client).collect do |resource|
116
- Celluloid::Future.new {
117
- delete(client, resource)
118
- }
119
- end.map(&:value)
17
+ def representation
18
+ return @representation if @representation
19
+ raise RuntimeError.new("no representation set")
120
20
  end
121
21
 
122
- # @param [Ridley::Client] client
123
- # @param [#to_hash] object
124
- #
125
- # @return [Object]
126
- def update(client, object)
127
- resource = new(client, object.to_hash)
128
- new(client, client.connection.put("#{self.resource_path}/#{resource.chef_id}", resource.to_json).body)
22
+ def represented_by(klass)
23
+ @representation = klass
129
24
  end
130
25
  end
131
26
 
27
+ include Celluloid
132
28
  include Chozo::VariaModel
133
29
  include Comparable
134
30
 
135
- # @param [Ridley::Client] client
136
- # @param [Hash] new_attrs
137
- def initialize(client, new_attrs = {})
138
- @client = client
139
- mass_assign(new_attrs)
31
+ # @param [Celluloid::Registry] connection_registry
32
+ def initialize(connection_registry)
33
+ @connection_registry = connection_registry
140
34
  end
141
35
 
142
- # Creates a resource on the target remote or updates one if the resource
143
- # already exists.
144
- #
145
- # @raise [Errors::InvalidResource]
146
- # if the resource does not pass validations
147
- #
148
- # @return [Boolean]
149
- def save
150
- raise Errors::InvalidResource.new(self.errors) unless valid?
151
-
152
- mass_assign(self.class.create(client, self)._attributes_)
153
- true
154
- rescue Errors::HTTPConflict
155
- self.update
156
- true
36
+ def new(*args)
37
+ self.class.representation.new(Actor.current, *args)
157
38
  end
158
39
 
159
- # Updates the instantiated resource on the target remote with any changes made
160
- # to self
161
- #
162
- # @raise [Errors::InvalidResource]
163
- # if the resource does not pass validations
164
- #
165
- # @return [Boolean]
166
- def update
167
- raise Errors::InvalidResource.new(self.errors) unless valid?
168
-
169
- mass_assign(self.class.update(client, self)._attributes_)
170
- true
40
+ def connection
41
+ @connection_registry[:connection_pool]
171
42
  end
172
43
 
173
- # Reload the attributes of the instantiated resource
44
+ # @param [Ridley::Client] client
174
45
  #
175
- # @return [Object]
176
- def reload
177
- mass_assign(self.class.find(client, self)._attributes_)
178
- self
46
+ # @return [Array<Object>]
47
+ def all
48
+ connection.get(self.class.resource_path).body.collect do |identity, location|
49
+ new(self.class.representation.chef_id => identity)
50
+ end
179
51
  end
180
52
 
181
- # @return [String]
182
- def chef_id
183
- get_attribute(self.class.chef_id)
53
+ # @param [String, #chef_id] object
54
+ #
55
+ # @return [nil, Object]
56
+ def find(object)
57
+ chef_id = object.respond_to?(:chef_id) ? object.chef_id : object
58
+ new(connection.get("#{self.class.resource_path}/#{chef_id}").body)
59
+ rescue Errors::HTTPNotFound => ex
60
+ nil
184
61
  end
185
62
 
186
- def to_s
187
- "#<#{self.class} chef_id:#{self.chef_id}, attributes:#{self._attributes_}>"
63
+ # @param [#to_hash] object
64
+ #
65
+ # @return [Object]
66
+ def create(object)
67
+ resource = new(object.to_hash)
68
+ new_attributes = connection.post(self.class.resource_path, resource.to_json).body
69
+ resource.mass_assign(resource._attributes_.deep_merge(new_attributes))
70
+ resource
188
71
  end
189
72
 
190
- # @param [Object] other
73
+ # @param [String, #chef_id] object
191
74
  #
192
- # @return [Boolean]
193
- def <=>(other)
194
- self.chef_id <=> other.chef_id
75
+ # @return [Object]
76
+ def delete(object)
77
+ chef_id = object.respond_to?(:chef_id) ? object.chef_id : object
78
+ new(connection.delete("#{self.class.resource_path}/#{chef_id}").body)
195
79
  end
196
80
 
197
- def ==(other)
198
- self.chef_id == other.chef_id
81
+ # @return [Array<Object>]
82
+ def delete_all
83
+ all.collect do |resource|
84
+ future(:delete, resource)
85
+ end.map(&:value)
199
86
  end
200
87
 
201
- # @param [Object] other
88
+ # @param [#to_hash] object
202
89
  #
203
- # @return [Boolean]
204
- def eql?(other)
205
- self.class == other.class && self == other
206
- end
207
-
208
- def hash
209
- self.chef_id.hash
90
+ # @return [Object]
91
+ def update(object)
92
+ resource = new(object.to_hash)
93
+ new(connection.put("#{self.class.resource_path}/#{resource.chef_id}", resource.to_json).body)
210
94
  end
211
-
212
- private
213
-
214
- attr_reader :client
215
95
  end
216
96
  end
@@ -4,80 +4,30 @@ module Ridley
4
4
  # @example listing all clients
5
5
  # conn = Ridley.new(...)
6
6
  # conn.client.all #=> [
7
- # #<Ridley::ClientResource chef_id:'reset'>,
8
- # #<Ridley::ClientResource chef_id:'reset-validator'>
7
+ # #<Ridley::ClientObject chef_id:'reset'>,
8
+ # #<Ridley::ClientObject chef_id:'reset-validator'>
9
9
  # ]
10
10
  class ClientResource < Ridley::Resource
11
- class << self
12
- # Retrieves a client from the remote connection matching the given chef_id
13
- # and regenerates it's private key. An instance of the updated object will
14
- # be returned and have a value set for the 'private_key' accessor.
15
- #
16
- # @param [Ridley::Client] client
17
- # @param [String, #chef_id] chef_client
18
- #
19
- # @raise [Errors::HTTPNotFound]
20
- # if a client with the given chef_id is not found
21
- # @raise [Errors::HTTPError]
22
- #
23
- # @return [Ridley::ClientResource]
24
- def regenerate_key(client, chef_client)
25
- obj = find!(client, chef_client)
26
- obj.regenerate_key
27
- obj
28
- end
29
- end
30
-
31
- set_chef_id "name"
32
- set_chef_type "client"
33
- set_chef_json_class "Chef::ApiClient"
34
11
  set_resource_path "clients"
12
+ represented_by Ridley::ClientObject
35
13
 
36
- attribute :name,
37
- type: String,
38
- required: true
39
-
40
- attribute :admin,
41
- type: Boolean,
42
- required: true,
43
- default: false
44
-
45
- attribute :validator,
46
- type: Boolean,
47
- required: true,
48
- default: false
49
-
50
- attribute :certificate,
51
- type: String
52
-
53
- attribute :public_key,
54
- type: String
55
-
56
- attribute :private_key,
57
- type: [ String, Boolean ]
58
-
59
- attribute :orgname,
60
- type: String
61
-
62
- # Regenerates the private key of the instantiated client object. The new
63
- # private key will be set to the value of the 'private_key' accessor
64
- # of the instantiated client object.
14
+ # Retrieves a client from the remote connection matching the given chef_id
15
+ # and regenerates it's private key. An instance of the updated object will
16
+ # be returned and have a value set for the 'private_key' accessor.
65
17
  #
66
- # @return [Boolean]
67
- # true for success and false for failure
68
- def regenerate_key
69
- self.private_key = true
70
- self.save
71
- end
72
-
73
- # Override to_json to reflect to massage the returned attributes based on the type
74
- # of connection. Only OHC/OPC requires the json_class attribute is not present.
75
- def to_json
76
- if client.connection.hosted?
77
- to_hash.except(:json_class).to_json
78
- else
79
- super
18
+ # @param [String, #chef_id] chef_client
19
+ #
20
+ # @raise [Errors::ResourceNotFound]
21
+ # if a client with the given chef_id is not found
22
+ #
23
+ # @return [Ridley::ClientObject]
24
+ def regenerate_key(chef_client)
25
+ unless chef_client = find(chef_client)
26
+ abort Errors::ResourceNotFound.new("client '#{chef_client}' not found")
80
27
  end
28
+
29
+ chef_client.private_key = true
30
+ update(chef_client)
81
31
  end
82
32
  end
83
33
  end