ridley 0.10.2 → 0.11.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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