cheffish 1.4.1 → 1.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +201 -201
  3. data/README.md +120 -120
  4. data/Rakefile +23 -23
  5. data/lib/chef/provider/chef_acl.rb +439 -439
  6. data/lib/chef/provider/chef_client.rb +53 -53
  7. data/lib/chef/provider/chef_container.rb +55 -55
  8. data/lib/chef/provider/chef_data_bag.rb +55 -55
  9. data/lib/chef/provider/chef_data_bag_item.rb +278 -278
  10. data/lib/chef/provider/chef_environment.rb +83 -83
  11. data/lib/chef/provider/chef_group.rb +83 -83
  12. data/lib/chef/provider/chef_mirror.rb +169 -169
  13. data/lib/chef/provider/chef_node.rb +87 -87
  14. data/lib/chef/provider/chef_organization.rb +155 -155
  15. data/lib/chef/provider/chef_resolved_cookbooks.rb +46 -46
  16. data/lib/chef/provider/chef_role.rb +84 -84
  17. data/lib/chef/provider/chef_user.rb +59 -59
  18. data/lib/chef/provider/private_key.rb +225 -225
  19. data/lib/chef/provider/public_key.rb +88 -88
  20. data/lib/chef/resource/chef_acl.rb +69 -69
  21. data/lib/chef/resource/chef_client.rb +48 -48
  22. data/lib/chef/resource/chef_container.rb +22 -22
  23. data/lib/chef/resource/chef_data_bag.rb +22 -22
  24. data/lib/chef/resource/chef_data_bag_item.rb +121 -121
  25. data/lib/chef/resource/chef_environment.rb +77 -77
  26. data/lib/chef/resource/chef_group.rb +53 -53
  27. data/lib/chef/resource/chef_mirror.rb +52 -52
  28. data/lib/chef/resource/chef_node.rb +22 -22
  29. data/lib/chef/resource/chef_organization.rb +69 -69
  30. data/lib/chef/resource/chef_resolved_cookbooks.rb +35 -35
  31. data/lib/chef/resource/chef_role.rb +110 -110
  32. data/lib/chef/resource/chef_user.rb +56 -56
  33. data/lib/chef/resource/private_key.rb +48 -48
  34. data/lib/chef/resource/public_key.rb +25 -25
  35. data/lib/cheffish/actor_provider_base.rb +131 -131
  36. data/lib/cheffish/basic_chef_client.rb +184 -184
  37. data/lib/cheffish/chef_provider_base.rb +246 -246
  38. data/lib/cheffish/chef_run.rb +162 -162
  39. data/lib/cheffish/chef_run_data.rb +19 -19
  40. data/lib/cheffish/chef_run_listener.rb +30 -30
  41. data/lib/cheffish/key_formatter.rb +113 -113
  42. data/lib/cheffish/merged_config.rb +94 -94
  43. data/lib/cheffish/recipe_dsl.rb +157 -157
  44. data/lib/cheffish/rspec/chef_run_support.rb +83 -83
  45. data/lib/cheffish/rspec/matchers/be_idempotent.rb +16 -16
  46. data/lib/cheffish/rspec/matchers/emit_no_warnings_or_errors.rb +15 -15
  47. data/lib/cheffish/rspec/matchers/have_updated.rb +37 -37
  48. data/lib/cheffish/rspec/matchers/partially_match.rb +63 -63
  49. data/lib/cheffish/rspec/matchers.rb +4 -4
  50. data/lib/cheffish/rspec/recipe_run_wrapper.rb +78 -59
  51. data/lib/cheffish/rspec/repository_support.rb +108 -108
  52. data/lib/cheffish/rspec.rb +8 -8
  53. data/lib/cheffish/server_api.rb +52 -52
  54. data/lib/cheffish/version.rb +3 -3
  55. data/lib/cheffish/with_pattern.rb +21 -21
  56. data/lib/cheffish.rb +235 -235
  57. data/spec/functional/fingerprint_spec.rb +64 -64
  58. data/spec/functional/merged_config_spec.rb +19 -19
  59. data/spec/functional/server_api_spec.rb +13 -13
  60. data/spec/integration/chef_acl_spec.rb +879 -879
  61. data/spec/integration/chef_client_spec.rb +105 -105
  62. data/spec/integration/chef_container_spec.rb +33 -33
  63. data/spec/integration/chef_group_spec.rb +309 -309
  64. data/spec/integration/chef_mirror_spec.rb +491 -491
  65. data/spec/integration/chef_node_spec.rb +786 -786
  66. data/spec/integration/chef_organization_spec.rb +226 -226
  67. data/spec/integration/chef_role_spec.rb +78 -78
  68. data/spec/integration/chef_user_spec.rb +85 -85
  69. data/spec/integration/private_key_spec.rb +399 -399
  70. data/spec/integration/recipe_dsl_spec.rb +28 -28
  71. data/spec/integration/rspec/converge_spec.rb +183 -183
  72. data/spec/support/key_support.rb +29 -29
  73. data/spec/support/spec_support.rb +15 -15
  74. data/spec/unit/get_private_key_spec.rb +131 -131
  75. data/spec/unit/recipe_run_wrapper_spec.rb +37 -37
  76. metadata +3 -2
@@ -1,246 +1,246 @@
1
- require 'chef/config'
2
- require 'chef/run_list'
3
- require 'chef/provider/lwrp_base'
4
-
5
- module Cheffish
6
- class ChefProviderBase < Chef::Provider::LWRPBase
7
- def rest
8
- @rest ||= Cheffish.chef_server_api(new_resource.chef_server)
9
- end
10
-
11
- def current_resource_exists?
12
- Array(current_resource.action) != [ :delete ]
13
- end
14
-
15
- def not_found_resource
16
- resource = resource_class.new(new_resource.name, run_context)
17
- resource.action :delete
18
- resource
19
- end
20
-
21
- def normalize_for_put(json)
22
- data_handler.normalize_for_put(json, fake_entry)
23
- end
24
-
25
- def normalize_for_post(json)
26
- data_handler.normalize_for_post(json, fake_entry)
27
- end
28
-
29
- def new_json
30
- @new_json ||= begin
31
- if new_resource.complete
32
- result = normalize(resource_to_json(new_resource))
33
- else
34
- # If the resource is incomplete, we use the current json to fill any holes
35
- result = current_json.merge(resource_to_json(new_resource))
36
- end
37
- augment_new_json(result)
38
- end
39
- end
40
-
41
- # Meant to be overridden
42
- def augment_new_json(json)
43
- json
44
- end
45
-
46
- def current_json
47
- @current_json ||= begin
48
- result = normalize(resource_to_json(current_resource))
49
- result = augment_current_json(result)
50
- result
51
- end
52
- end
53
-
54
- # Meant to be overridden
55
- def augment_current_json(json)
56
- json
57
- end
58
-
59
- def resource_to_json(resource)
60
- json = resource.raw_json || {}
61
- keys.each do |json_key, resource_key|
62
- value = resource.send(resource_key)
63
- # This takes care of Chef ImmutableMash and ImmutableArray
64
- value = value.to_hash if value.is_a?(Hash)
65
- value = value.to_a if value.is_a?(Array)
66
- json[json_key] = value if value
67
- end
68
- json
69
- end
70
-
71
- def json_to_resource(json)
72
- resource = resource_class.new(new_resource.name, run_context)
73
- keys.each do |json_key, resource_key|
74
- resource.send(resource_key, json.delete(json_key))
75
- end
76
- # Set the leftover to raw_json
77
- resource.raw_json json
78
- resource
79
- end
80
-
81
- def normalize(json)
82
- data_handler.normalize(json, fake_entry)
83
- end
84
-
85
- def json_differences(old_json, new_json, print_values=true, name = '', result = nil)
86
- result ||= []
87
- json_differences_internal(old_json, new_json, print_values, name, result)
88
- result
89
- end
90
-
91
- def json_differences_internal(old_json, new_json, print_values, name, result)
92
- if old_json.kind_of?(Hash) && new_json.kind_of?(Hash)
93
- removed_keys = old_json.keys.inject({}) { |hash, key| hash[key] = true; hash }
94
- new_json.each_pair do |new_key, new_value|
95
- if old_json.has_key?(new_key)
96
- removed_keys.delete(new_key)
97
- if new_value != old_json[new_key]
98
- json_differences_internal(old_json[new_key], new_value, print_values, name == '' ? new_key : "#{name}.#{new_key}", result)
99
- end
100
- else
101
- if print_values
102
- result << " add #{name == '' ? new_key : "#{name}.#{new_key}"} = #{new_value.inspect}"
103
- else
104
- result << " add #{name == '' ? new_key : "#{name}.#{new_key}"}"
105
- end
106
- end
107
- end
108
- removed_keys.keys.each do |removed_key|
109
- result << " remove #{name == '' ? removed_key : "#{name}.#{removed_key}"}"
110
- end
111
- else
112
- old_json = old_json.to_s if old_json.kind_of?(Symbol)
113
- new_json = new_json.to_s if new_json.kind_of?(Symbol)
114
- if old_json != new_json
115
- if print_values
116
- result << " update #{name} from #{old_json.inspect} to #{new_json.inspect}"
117
- else
118
- result << " update #{name}"
119
- end
120
- end
121
- end
122
- end
123
-
124
- def apply_modifiers(modifiers, json)
125
- return json if !modifiers || modifiers.size == 0
126
-
127
- # If the attributes have nothing, set them to {} so we have something to add to
128
- if json
129
- json = Marshal.load(Marshal.dump(json)) # Deep copy
130
- else
131
- json = {}
132
- end
133
-
134
- modifiers.each do |path, value|
135
- path = [path] if !path.kind_of?(Array)
136
- path = path.map { |path_part| path_part.to_s }
137
- parent = 0.upto(path.size-2).inject(json) do |hash, index|
138
- if hash.nil?
139
- nil
140
- elsif !hash.is_a?(Hash)
141
- raise "Attempt to set #{path} to #{value} when #{path[0..index-1]} is not a hash"
142
- else
143
- hash[path[index]]
144
- end
145
- end
146
- if !parent.nil? && !parent.is_a?(Hash)
147
- raise "Attempt to set #{path} to #{value} when #{path[0..-2]} is not a hash"
148
- end
149
- existing_value = parent ? parent[path[-1]] : nil
150
-
151
- if value.is_a?(Proc)
152
- value = value.call(existing_value)
153
- end
154
- if value == :delete
155
- parent.delete(path[-1]) if parent
156
- else
157
- # Create parent if necessary, overwriting values
158
- parent = path[0..-2].inject(json) do |hash, path_part|
159
- hash[path_part] = {} if !hash[path_part]
160
- hash[path_part]
161
- end
162
- if path.size > 0
163
- parent[path[-1]] = value
164
- else
165
- json = value
166
- end
167
- end
168
- end
169
- json
170
- end
171
-
172
- def apply_run_list_modifiers(add_to_run_list, delete_from_run_list, run_list)
173
- return run_list if (!add_to_run_list || add_to_run_list.size == 0) && (!delete_from_run_list || !delete_from_run_list.size)
174
- delete_from_run_list ||= []
175
- add_to_run_list ||= []
176
-
177
- run_list = Chef::RunList.new(*run_list)
178
-
179
- result = []
180
- add_to_run_list_index = 0
181
- run_list_index = 0
182
- while run_list_index < run_list.run_list_items.size do
183
- # See if the desired run list has this item
184
- found_desired = add_to_run_list.index { |item| same_run_list_item(item, run_list[run_list_index]) }
185
- if found_desired
186
- # If so, copy all items up to that desired run list (to preserve order).
187
- # If a run list item is out of order (run_list = X, B, Y, A, Z and desired = A, B)
188
- # then this will give us X, A, B. When A is found later, nothing will be copied
189
- # because found_desired will be less than add_to_run_list_index. The result will
190
- # be X, A, B, Y, Z.
191
- if found_desired >= add_to_run_list_index
192
- result += add_to_run_list[add_to_run_list_index..found_desired].map { |item| item.to_s }
193
- add_to_run_list_index = found_desired+1
194
- end
195
- else
196
- # If not, just copy it in
197
- unless delete_from_run_list.index { |item| same_run_list_item(item, run_list[run_list_index]) }
198
- result << run_list[run_list_index].to_s
199
- end
200
- end
201
- run_list_index += 1
202
- end
203
-
204
- # Copy any remaining desired items at the end
205
- result += add_to_run_list[add_to_run_list_index..-1].map { |item| item.to_s }
206
- result
207
- end
208
-
209
- def same_run_list_item(a, b)
210
- a_name = a.name
211
- b_name = b.name
212
- # Handle "a::default" being the same as "a"
213
- if a.type == :recipe && a_name =~ /(.+)::default$/
214
- a_name = $1
215
- elsif b.type == :recipe && b_name =~ /(.+)::default$/
216
- b_name = $1
217
- end
218
-
219
- a_name == b_name && a.type == b.type # We want to replace things with same name and different version
220
- end
221
-
222
- private
223
-
224
- # Needed to be able to use DataHandler classes
225
- def fake_entry
226
- FakeEntry.new("#{new_resource.send(keys.values.first)}.json")
227
- end
228
-
229
- class FakeEntry
230
- def initialize(name, parent = nil)
231
- @name = name
232
- @parent = parent
233
- @org = nil
234
- end
235
-
236
- attr_reader :name
237
- attr_reader :parent
238
- attr_reader :org
239
- end
240
- end
241
-
242
- # We are not interested in Chef's cloning behavior here.
243
- def load_prior_resource(*args)
244
- Chef::Log.debug("Overloading #{resource_name}.load_prior_resource with NOOP")
245
- end
246
- end
1
+ require 'chef/config'
2
+ require 'chef/run_list'
3
+ require 'chef/provider/lwrp_base'
4
+
5
+ module Cheffish
6
+ class ChefProviderBase < Chef::Provider::LWRPBase
7
+ def rest
8
+ @rest ||= Cheffish.chef_server_api(new_resource.chef_server)
9
+ end
10
+
11
+ def current_resource_exists?
12
+ Array(current_resource.action) != [ :delete ]
13
+ end
14
+
15
+ def not_found_resource
16
+ resource = resource_class.new(new_resource.name, run_context)
17
+ resource.action :delete
18
+ resource
19
+ end
20
+
21
+ def normalize_for_put(json)
22
+ data_handler.normalize_for_put(json, fake_entry)
23
+ end
24
+
25
+ def normalize_for_post(json)
26
+ data_handler.normalize_for_post(json, fake_entry)
27
+ end
28
+
29
+ def new_json
30
+ @new_json ||= begin
31
+ if new_resource.complete
32
+ result = normalize(resource_to_json(new_resource))
33
+ else
34
+ # If the resource is incomplete, we use the current json to fill any holes
35
+ result = current_json.merge(resource_to_json(new_resource))
36
+ end
37
+ augment_new_json(result)
38
+ end
39
+ end
40
+
41
+ # Meant to be overridden
42
+ def augment_new_json(json)
43
+ json
44
+ end
45
+
46
+ def current_json
47
+ @current_json ||= begin
48
+ result = normalize(resource_to_json(current_resource))
49
+ result = augment_current_json(result)
50
+ result
51
+ end
52
+ end
53
+
54
+ # Meant to be overridden
55
+ def augment_current_json(json)
56
+ json
57
+ end
58
+
59
+ def resource_to_json(resource)
60
+ json = resource.raw_json || {}
61
+ keys.each do |json_key, resource_key|
62
+ value = resource.send(resource_key)
63
+ # This takes care of Chef ImmutableMash and ImmutableArray
64
+ value = value.to_hash if value.is_a?(Hash)
65
+ value = value.to_a if value.is_a?(Array)
66
+ json[json_key] = value if value
67
+ end
68
+ json
69
+ end
70
+
71
+ def json_to_resource(json)
72
+ resource = resource_class.new(new_resource.name, run_context)
73
+ keys.each do |json_key, resource_key|
74
+ resource.send(resource_key, json.delete(json_key))
75
+ end
76
+ # Set the leftover to raw_json
77
+ resource.raw_json json
78
+ resource
79
+ end
80
+
81
+ def normalize(json)
82
+ data_handler.normalize(json, fake_entry)
83
+ end
84
+
85
+ def json_differences(old_json, new_json, print_values=true, name = '', result = nil)
86
+ result ||= []
87
+ json_differences_internal(old_json, new_json, print_values, name, result)
88
+ result
89
+ end
90
+
91
+ def json_differences_internal(old_json, new_json, print_values, name, result)
92
+ if old_json.kind_of?(Hash) && new_json.kind_of?(Hash)
93
+ removed_keys = old_json.keys.inject({}) { |hash, key| hash[key] = true; hash }
94
+ new_json.each_pair do |new_key, new_value|
95
+ if old_json.has_key?(new_key)
96
+ removed_keys.delete(new_key)
97
+ if new_value != old_json[new_key]
98
+ json_differences_internal(old_json[new_key], new_value, print_values, name == '' ? new_key : "#{name}.#{new_key}", result)
99
+ end
100
+ else
101
+ if print_values
102
+ result << " add #{name == '' ? new_key : "#{name}.#{new_key}"} = #{new_value.inspect}"
103
+ else
104
+ result << " add #{name == '' ? new_key : "#{name}.#{new_key}"}"
105
+ end
106
+ end
107
+ end
108
+ removed_keys.keys.each do |removed_key|
109
+ result << " remove #{name == '' ? removed_key : "#{name}.#{removed_key}"}"
110
+ end
111
+ else
112
+ old_json = old_json.to_s if old_json.kind_of?(Symbol)
113
+ new_json = new_json.to_s if new_json.kind_of?(Symbol)
114
+ if old_json != new_json
115
+ if print_values
116
+ result << " update #{name} from #{old_json.inspect} to #{new_json.inspect}"
117
+ else
118
+ result << " update #{name}"
119
+ end
120
+ end
121
+ end
122
+ end
123
+
124
+ def apply_modifiers(modifiers, json)
125
+ return json if !modifiers || modifiers.size == 0
126
+
127
+ # If the attributes have nothing, set them to {} so we have something to add to
128
+ if json
129
+ json = Marshal.load(Marshal.dump(json)) # Deep copy
130
+ else
131
+ json = {}
132
+ end
133
+
134
+ modifiers.each do |path, value|
135
+ path = [path] if !path.kind_of?(Array)
136
+ path = path.map { |path_part| path_part.to_s }
137
+ parent = 0.upto(path.size-2).inject(json) do |hash, index|
138
+ if hash.nil?
139
+ nil
140
+ elsif !hash.is_a?(Hash)
141
+ raise "Attempt to set #{path} to #{value} when #{path[0..index-1]} is not a hash"
142
+ else
143
+ hash[path[index]]
144
+ end
145
+ end
146
+ if !parent.nil? && !parent.is_a?(Hash)
147
+ raise "Attempt to set #{path} to #{value} when #{path[0..-2]} is not a hash"
148
+ end
149
+ existing_value = parent ? parent[path[-1]] : nil
150
+
151
+ if value.is_a?(Proc)
152
+ value = value.call(existing_value)
153
+ end
154
+ if value == :delete
155
+ parent.delete(path[-1]) if parent
156
+ else
157
+ # Create parent if necessary, overwriting values
158
+ parent = path[0..-2].inject(json) do |hash, path_part|
159
+ hash[path_part] = {} if !hash[path_part]
160
+ hash[path_part]
161
+ end
162
+ if path.size > 0
163
+ parent[path[-1]] = value
164
+ else
165
+ json = value
166
+ end
167
+ end
168
+ end
169
+ json
170
+ end
171
+
172
+ def apply_run_list_modifiers(add_to_run_list, delete_from_run_list, run_list)
173
+ return run_list if (!add_to_run_list || add_to_run_list.size == 0) && (!delete_from_run_list || !delete_from_run_list.size)
174
+ delete_from_run_list ||= []
175
+ add_to_run_list ||= []
176
+
177
+ run_list = Chef::RunList.new(*run_list)
178
+
179
+ result = []
180
+ add_to_run_list_index = 0
181
+ run_list_index = 0
182
+ while run_list_index < run_list.run_list_items.size do
183
+ # See if the desired run list has this item
184
+ found_desired = add_to_run_list.index { |item| same_run_list_item(item, run_list[run_list_index]) }
185
+ if found_desired
186
+ # If so, copy all items up to that desired run list (to preserve order).
187
+ # If a run list item is out of order (run_list = X, B, Y, A, Z and desired = A, B)
188
+ # then this will give us X, A, B. When A is found later, nothing will be copied
189
+ # because found_desired will be less than add_to_run_list_index. The result will
190
+ # be X, A, B, Y, Z.
191
+ if found_desired >= add_to_run_list_index
192
+ result += add_to_run_list[add_to_run_list_index..found_desired].map { |item| item.to_s }
193
+ add_to_run_list_index = found_desired+1
194
+ end
195
+ else
196
+ # If not, just copy it in
197
+ unless delete_from_run_list.index { |item| same_run_list_item(item, run_list[run_list_index]) }
198
+ result << run_list[run_list_index].to_s
199
+ end
200
+ end
201
+ run_list_index += 1
202
+ end
203
+
204
+ # Copy any remaining desired items at the end
205
+ result += add_to_run_list[add_to_run_list_index..-1].map { |item| item.to_s }
206
+ result
207
+ end
208
+
209
+ def same_run_list_item(a, b)
210
+ a_name = a.name
211
+ b_name = b.name
212
+ # Handle "a::default" being the same as "a"
213
+ if a.type == :recipe && a_name =~ /(.+)::default$/
214
+ a_name = $1
215
+ elsif b.type == :recipe && b_name =~ /(.+)::default$/
216
+ b_name = $1
217
+ end
218
+
219
+ a_name == b_name && a.type == b.type # We want to replace things with same name and different version
220
+ end
221
+
222
+ private
223
+
224
+ # Needed to be able to use DataHandler classes
225
+ def fake_entry
226
+ FakeEntry.new("#{new_resource.send(keys.values.first)}.json")
227
+ end
228
+
229
+ class FakeEntry
230
+ def initialize(name, parent = nil)
231
+ @name = name
232
+ @parent = parent
233
+ @org = nil
234
+ end
235
+
236
+ attr_reader :name
237
+ attr_reader :parent
238
+ attr_reader :org
239
+ end
240
+ end
241
+
242
+ # We are not interested in Chef's cloning behavior here.
243
+ def load_prior_resource(*args)
244
+ Chef::Log.debug("Overloading #{resource_name}.load_prior_resource with NOOP")
245
+ end
246
+ end