chef-zero 15.0.17 → 15.0.21

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 (122) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +36 -31
  3. data/LICENSE +201 -201
  4. data/Rakefile +73 -68
  5. data/bin/chef-zero +111 -111
  6. data/chef-zero.gemspec +34 -33
  7. data/lib/chef_zero/chef_data/acl_path.rb +140 -140
  8. data/lib/chef_zero/chef_data/cookbook_data.rb +237 -237
  9. data/lib/chef_zero/chef_data/data_normalizer.rb +276 -276
  10. data/lib/chef_zero/chef_data/default_creator.rb +476 -476
  11. data/lib/chef_zero/data_store/data_already_exists_error.rb +29 -29
  12. data/lib/chef_zero/data_store/data_error.rb +32 -32
  13. data/lib/chef_zero/data_store/data_not_found_error.rb +29 -29
  14. data/lib/chef_zero/data_store/default_facade.rb +143 -147
  15. data/lib/chef_zero/data_store/interface_v1.rb +67 -67
  16. data/lib/chef_zero/data_store/interface_v2.rb +18 -18
  17. data/lib/chef_zero/data_store/memory_store.rb +33 -33
  18. data/lib/chef_zero/data_store/memory_store_v2.rb +159 -159
  19. data/lib/chef_zero/data_store/raw_file_store.rb +143 -143
  20. data/lib/chef_zero/data_store/v1_to_v2_adapter.rb +150 -150
  21. data/lib/chef_zero/data_store/v2_to_v1_adapter.rb +105 -105
  22. data/lib/chef_zero/dist.rb +9 -9
  23. data/lib/chef_zero/endpoints/acl_endpoint.rb +39 -39
  24. data/lib/chef_zero/endpoints/acls_endpoint.rb +41 -41
  25. data/lib/chef_zero/endpoints/actor_default_key_endpoint.rb +78 -78
  26. data/lib/chef_zero/endpoints/actor_endpoint.rb +184 -184
  27. data/lib/chef_zero/endpoints/actor_key_endpoint.rb +62 -62
  28. data/lib/chef_zero/endpoints/actor_keys_endpoint.rb +129 -129
  29. data/lib/chef_zero/endpoints/actors_endpoint.rb +104 -104
  30. data/lib/chef_zero/endpoints/authenticate_user_endpoint.rb +32 -32
  31. data/lib/chef_zero/endpoints/container_endpoint.rb +22 -22
  32. data/lib/chef_zero/endpoints/containers_endpoint.rb +25 -25
  33. data/lib/chef_zero/endpoints/controls_endpoint.rb +16 -16
  34. data/lib/chef_zero/endpoints/cookbook_artifact_endpoint.rb +24 -24
  35. data/lib/chef_zero/endpoints/cookbook_artifact_identifier_endpoint.rb +68 -68
  36. data/lib/chef_zero/endpoints/cookbook_artifacts_endpoint.rb +34 -34
  37. data/lib/chef_zero/endpoints/cookbook_endpoint.rb +39 -39
  38. data/lib/chef_zero/endpoints/cookbook_version_endpoint.rb +136 -136
  39. data/lib/chef_zero/endpoints/cookbooks_base.rb +80 -80
  40. data/lib/chef_zero/endpoints/cookbooks_endpoint.rb +19 -19
  41. data/lib/chef_zero/endpoints/data_bag_endpoint.rb +45 -45
  42. data/lib/chef_zero/endpoints/data_bag_item_endpoint.rb +25 -25
  43. data/lib/chef_zero/endpoints/data_bags_endpoint.rb +23 -23
  44. data/lib/chef_zero/endpoints/dummy_endpoint.rb +29 -29
  45. data/lib/chef_zero/endpoints/environment_cookbook_endpoint.rb +24 -24
  46. data/lib/chef_zero/endpoints/environment_cookbook_versions_endpoint.rb +126 -126
  47. data/lib/chef_zero/endpoints/environment_cookbooks_endpoint.rb +22 -22
  48. data/lib/chef_zero/endpoints/environment_endpoint.rb +33 -33
  49. data/lib/chef_zero/endpoints/environment_nodes_endpoint.rb +23 -23
  50. data/lib/chef_zero/endpoints/environment_recipes_endpoint.rb +22 -22
  51. data/lib/chef_zero/endpoints/environment_role_endpoint.rb +36 -36
  52. data/lib/chef_zero/endpoints/file_store_file_endpoint.rb +22 -22
  53. data/lib/chef_zero/endpoints/group_endpoint.rb +20 -20
  54. data/lib/chef_zero/endpoints/groups_endpoint.rb +13 -13
  55. data/lib/chef_zero/endpoints/license_endpoint.rb +25 -25
  56. data/lib/chef_zero/endpoints/node_endpoint.rb +34 -34
  57. data/lib/chef_zero/endpoints/node_identifiers_endpoint.rb +22 -22
  58. data/lib/chef_zero/endpoints/nodes_endpoint.rb +34 -34
  59. data/lib/chef_zero/endpoints/not_found_endpoint.rb +11 -11
  60. data/lib/chef_zero/endpoints/organization_association_request_endpoint.rb +22 -22
  61. data/lib/chef_zero/endpoints/organization_association_requests_endpoint.rb +30 -30
  62. data/lib/chef_zero/endpoints/organization_authenticate_user_endpoint.rb +26 -26
  63. data/lib/chef_zero/endpoints/organization_endpoint.rb +47 -47
  64. data/lib/chef_zero/endpoints/organization_user_base.rb +15 -15
  65. data/lib/chef_zero/endpoints/organization_user_default_key_endpoint.rb +16 -16
  66. data/lib/chef_zero/endpoints/organization_user_endpoint.rb +26 -26
  67. data/lib/chef_zero/endpoints/organization_user_key_endpoint.rb +17 -17
  68. data/lib/chef_zero/endpoints/organization_user_keys_endpoint.rb +17 -17
  69. data/lib/chef_zero/endpoints/organization_users_endpoint.rb +43 -43
  70. data/lib/chef_zero/endpoints/organization_validator_key_endpoint.rb +20 -20
  71. data/lib/chef_zero/endpoints/organizations_endpoint.rb +61 -61
  72. data/lib/chef_zero/endpoints/policies_endpoint.rb +26 -26
  73. data/lib/chef_zero/endpoints/policy_endpoint.rb +24 -24
  74. data/lib/chef_zero/endpoints/policy_group_endpoint.rb +46 -46
  75. data/lib/chef_zero/endpoints/policy_group_policy_endpoint.rb +83 -83
  76. data/lib/chef_zero/endpoints/policy_groups_endpoint.rb +38 -38
  77. data/lib/chef_zero/endpoints/policy_revision_endpoint.rb +66 -66
  78. data/lib/chef_zero/endpoints/policy_revisions_endpoint.rb +15 -15
  79. data/lib/chef_zero/endpoints/principal_endpoint.rb +55 -55
  80. data/lib/chef_zero/endpoints/rest_list_endpoint.rb +42 -42
  81. data/lib/chef_zero/endpoints/rest_object_endpoint.rb +78 -78
  82. data/lib/chef_zero/endpoints/role_endpoint.rb +16 -16
  83. data/lib/chef_zero/endpoints/role_environments_endpoint.rb +14 -14
  84. data/lib/chef_zero/endpoints/sandbox_endpoint.rb +27 -27
  85. data/lib/chef_zero/endpoints/sandboxes_endpoint.rb +51 -51
  86. data/lib/chef_zero/endpoints/search_endpoint.rb +208 -208
  87. data/lib/chef_zero/endpoints/searches_endpoint.rb +18 -18
  88. data/lib/chef_zero/endpoints/server_api_version_endpoint.rb +14 -14
  89. data/lib/chef_zero/endpoints/system_recovery_endpoint.rb +30 -30
  90. data/lib/chef_zero/endpoints/universe_endpoint.rb +15 -15
  91. data/lib/chef_zero/endpoints/user_association_request_endpoint.rb +41 -41
  92. data/lib/chef_zero/endpoints/user_association_requests_count_endpoint.rb +19 -19
  93. data/lib/chef_zero/endpoints/user_association_requests_endpoint.rb +19 -19
  94. data/lib/chef_zero/endpoints/user_organizations_endpoint.rb +22 -22
  95. data/lib/chef_zero/endpoints/version_endpoint.rb +13 -13
  96. data/lib/chef_zero/log.rb +7 -7
  97. data/lib/chef_zero/rest_base.rb +332 -332
  98. data/lib/chef_zero/rest_error_response.rb +11 -11
  99. data/lib/chef_zero/rest_request.rb +84 -88
  100. data/lib/chef_zero/rest_router.rb +72 -72
  101. data/lib/chef_zero/rspec.rb +355 -355
  102. data/lib/chef_zero/server.rb +730 -730
  103. data/lib/chef_zero/socketless_server_map.rb +92 -93
  104. data/lib/chef_zero/solr/query/binary_operator.rb +52 -52
  105. data/lib/chef_zero/solr/query/phrase.rb +23 -23
  106. data/lib/chef_zero/solr/query/range_query.rb +46 -46
  107. data/lib/chef_zero/solr/query/regexpable_query.rb +30 -30
  108. data/lib/chef_zero/solr/query/subquery.rb +37 -37
  109. data/lib/chef_zero/solr/query/term.rb +45 -45
  110. data/lib/chef_zero/solr/query/unary_operator.rb +41 -41
  111. data/lib/chef_zero/solr/solr_doc.rb +53 -53
  112. data/lib/chef_zero/solr/solr_parser.rb +208 -208
  113. data/lib/chef_zero/version.rb +3 -3
  114. data/lib/chef_zero.rb +10 -10
  115. data/spec/run_oc_pedant.rb +226 -226
  116. data/spec/search_spec.rb +36 -36
  117. data/spec/server_spec.rb +96 -96
  118. data/spec/socketless_server_map_spec.rb +74 -74
  119. data/spec/support/oc_pedant.rb +149 -149
  120. data/spec/support/secrets.json +6 -6
  121. data/spec/support/stickywicket.pem +27 -27
  122. metadata +35 -18
@@ -1,208 +1,208 @@
1
- require "ffi_yajl" unless defined?(FFI_Yajl)
2
- require_relative "rest_object_endpoint"
3
- require_relative "../chef_data/data_normalizer"
4
- require_relative "../rest_error_response"
5
- require_relative "../solr/solr_parser"
6
- require_relative "../solr/solr_doc"
7
-
8
- module ChefZero
9
- module Endpoints
10
- # /search/INDEX
11
- class SearchEndpoint < RestBase
12
- def get(request)
13
- orgname = request.rest_path[1]
14
- results = search(request, orgname)
15
-
16
- results["rows"] = results["rows"].map { |name, uri, value, search_value| value }
17
-
18
- json_response(200, results)
19
- rescue ChefZero::Solr::ParseError
20
- bad_search_request(request)
21
- end
22
-
23
- def post(request)
24
- orgname = request.rest_path[1]
25
- full_results = search(request, orgname)
26
- keys = FFI_Yajl::Parser.parse(request.body)
27
- partial_results = full_results["rows"].map do |name, uri, doc, search_value|
28
- data = {}
29
- keys.each_pair do |key, path|
30
- if path.size > 0
31
- value = search_value
32
- path.each do |path_part|
33
- value = value[path_part] unless value.nil?
34
- end
35
- data[key] = value
36
- else
37
- data[key] = nil
38
- end
39
- end
40
- {
41
- "url" => uri,
42
- "data" => data,
43
- }
44
- end
45
- json_response(200, {
46
- "rows" => partial_results,
47
- "start" => full_results["start"],
48
- "total" => full_results["total"],
49
- })
50
- rescue ChefZero::Solr::ParseError
51
- bad_search_request(request)
52
- end
53
-
54
- private
55
-
56
- def bad_search_request(request)
57
- query_string = request.query_params["q"]
58
- resp = { "error" => ["invalid search query: '#{query_string}'"] }
59
- json_response(400, resp)
60
- end
61
-
62
- def search_container(request, index, orgname)
63
- relative_parts, normalize_proc =
64
- case index
65
- when "client"
66
- [ ["clients"], Proc.new { |client, name| ChefData::DataNormalizer.normalize_client(client, name, orgname) } ]
67
- when "node"
68
- [ ["nodes"], Proc.new { |node, name| ChefData::DataNormalizer.normalize_node(node, name) } ]
69
- when "environment"
70
- [ ["environments"], Proc.new { |environment, name| ChefData::DataNormalizer.normalize_environment(environment, name) } ]
71
- when "role"
72
- [ ["roles"], Proc.new { |role, name| ChefData::DataNormalizer.normalize_role(role, name) } ]
73
- else
74
- [ ["data", index], Proc.new { |data_bag_item, id| ChefData::DataNormalizer.normalize_data_bag_item(data_bag_item, index, id, "DELETE") } ]
75
- end
76
-
77
- [
78
- request.rest_path[0..1] + relative_parts,
79
- normalize_proc,
80
- ]
81
- end
82
-
83
- def expand_for_indexing(value, index, id)
84
- if index == "node"
85
- result = {}
86
- deep_merge!(value["default"] || {}, result)
87
- deep_merge!(value["normal"] || {}, result)
88
- deep_merge!(value["override"] || {}, result)
89
- deep_merge!(value["automatic"] || {}, result)
90
- result["recipe"] = []
91
- result["role"] = []
92
- if value["run_list"]
93
- value["run_list"].each do |run_list_entry|
94
- if run_list_entry =~ /^(recipe|role)\[(.*)\]/
95
- result[$1] << $2
96
- end
97
- end
98
- end
99
- value.each_pair do |key, val|
100
- result[key] = val unless %w{default normal override automatic}.include?(key)
101
- end
102
- result
103
-
104
- elsif !%w{client environment role}.include?(index)
105
- ChefData::DataNormalizer.normalize_data_bag_item(value, index, id, "GET")
106
- else
107
- value
108
- end
109
- end
110
-
111
- def search(request, orgname = nil)
112
- # Extract parameters
113
- index = request.rest_path[3]
114
- query_string = request.query_params["q"] || "*:*"
115
- solr_query = ChefZero::Solr::SolrParser.new(query_string).parse
116
- sort_string = request.query_params["sort"]
117
- start = request.query_params["start"].to_i
118
- rows = request.query_params["rows"].to_i
119
-
120
- # Get the search container
121
- container, expander = search_container(request, index, orgname)
122
-
123
- # Search!
124
- result = []
125
- list_data(request, container).each do |name|
126
- value = get_data(request, container + [name])
127
- expanded = expander.call(FFI_Yajl::Parser.parse(value), name)
128
- result << [ name, build_uri(request.base_uri, container + [name]), expanded, expand_for_indexing(expanded, index, name) ]
129
- end
130
- result = result.select do |name, uri, value, search_value|
131
- solr_query.matches_doc?(ChefZero::Solr::SolrDoc.new(search_value, name))
132
- end
133
- total = result.size
134
-
135
- # Sort
136
- if sort_string
137
- sort_key, sort_order = sort_string.split(/\s+/, 2)
138
- result = result.sort_by { |name, uri, value, search_value| ChefZero::Solr::SolrDoc.new(search_value, name)[sort_key] }
139
- result = result.reverse if sort_order == "DESC"
140
- end
141
-
142
- {
143
- # Paginate
144
- #
145
- # Slice the array based on the value of the "rows" query parameter. If
146
- # this is a positive integer, we'll get the number of rows asked for.
147
- # If it's nil, we'll get -1, which gives us all of the elements.
148
- #
149
- # Do the same for "start", which will start at 0 if that value is not
150
- # given.
151
- "rows" => result[start..(rows - 1)],
152
- # Also return start and total in the object
153
- "start" => start,
154
- "total" => total,
155
- }
156
- end
157
-
158
- # Deep Merge core documentation.
159
- # deep_merge! method permits merging of arbitrary child elements. The two top level
160
- # elements must be hashes. These hashes can contain unlimited (to stack limit) levels
161
- # of child elements. These child elements to not have to be of the same types.
162
- # Where child elements are of the same type, deep_merge will attempt to merge them together.
163
- # Where child elements are not of the same type, deep_merge will skip or optionally overwrite
164
- # the destination element with the contents of the source element at that level.
165
- # So if you have two hashes like this:
166
- # source = {:x => [1,2,3], :y => 2}
167
- # dest = {:x => [4,5,'6'], :y => [7,8,9]}
168
- # dest.deep_merge!(source)
169
- # Results: {:x => [1,2,3,4,5,'6'], :y => 2}
170
- # By default, "deep_merge!" will overwrite any unmergeables and merge everything else.
171
- # To avoid this, use "deep_merge" (no bang/exclamation mark)
172
- def deep_merge!(source, dest)
173
- # if dest doesn't exist, then simply copy source to it
174
- if dest.nil?
175
- dest = source; return dest
176
- end
177
-
178
- case source
179
- when nil
180
- dest
181
- when Hash
182
- source.each do |src_key, src_value|
183
- if dest.is_a?(Hash)
184
- if dest[src_key]
185
- dest[src_key] = deep_merge!(src_value, dest[src_key])
186
- else # dest[src_key] doesn't exist so we take whatever source has
187
- dest[src_key] = src_value
188
- end
189
- else # dest isn't a hash, so we overwrite it completely
190
- dest = source
191
- end
192
- end
193
- when Array
194
- if dest.is_a?(Array)
195
- dest |= source
196
- else
197
- dest = source
198
- end
199
- when String
200
- dest = source
201
- else # src_hash is not an array or hash, so we'll have to overwrite dest
202
- dest = source
203
- end
204
- dest
205
- end # deep_merge!
206
- end
207
- end
208
- end
1
+ require "ffi_yajl" unless defined?(FFI_Yajl)
2
+ require_relative "rest_object_endpoint"
3
+ require_relative "../chef_data/data_normalizer"
4
+ require_relative "../rest_error_response"
5
+ require_relative "../solr/solr_parser"
6
+ require_relative "../solr/solr_doc"
7
+
8
+ module ChefZero
9
+ module Endpoints
10
+ # /search/INDEX
11
+ class SearchEndpoint < RestBase
12
+ def get(request)
13
+ orgname = request.rest_path[1]
14
+ results = search(request, orgname)
15
+
16
+ results["rows"] = results["rows"].map { |name, uri, value, search_value| value }
17
+
18
+ json_response(200, results)
19
+ rescue ChefZero::Solr::ParseError
20
+ bad_search_request(request)
21
+ end
22
+
23
+ def post(request)
24
+ orgname = request.rest_path[1]
25
+ full_results = search(request, orgname)
26
+ keys = FFI_Yajl::Parser.parse(request.body)
27
+ partial_results = full_results["rows"].map do |name, uri, doc, search_value|
28
+ data = {}
29
+ keys.each_pair do |key, path|
30
+ if path.size > 0
31
+ value = search_value
32
+ path.each do |path_part|
33
+ value = value[path_part] unless value.nil?
34
+ end
35
+ data[key] = value
36
+ else
37
+ data[key] = nil
38
+ end
39
+ end
40
+ {
41
+ "url" => uri,
42
+ "data" => data,
43
+ }
44
+ end
45
+ json_response(200, {
46
+ "rows" => partial_results,
47
+ "start" => full_results["start"],
48
+ "total" => full_results["total"],
49
+ })
50
+ rescue ChefZero::Solr::ParseError
51
+ bad_search_request(request)
52
+ end
53
+
54
+ private
55
+
56
+ def bad_search_request(request)
57
+ query_string = request.query_params["q"]
58
+ resp = { "error" => ["invalid search query: '#{query_string}'"] }
59
+ json_response(400, resp)
60
+ end
61
+
62
+ def search_container(request, index, orgname)
63
+ relative_parts, normalize_proc =
64
+ case index
65
+ when "client"
66
+ [ ["clients"], Proc.new { |client, name| ChefData::DataNormalizer.normalize_client(client, name, orgname) } ]
67
+ when "node"
68
+ [ ["nodes"], Proc.new { |node, name| ChefData::DataNormalizer.normalize_node(node, name) } ]
69
+ when "environment"
70
+ [ ["environments"], Proc.new { |environment, name| ChefData::DataNormalizer.normalize_environment(environment, name) } ]
71
+ when "role"
72
+ [ ["roles"], Proc.new { |role, name| ChefData::DataNormalizer.normalize_role(role, name) } ]
73
+ else
74
+ [ ["data", index], Proc.new { |data_bag_item, id| ChefData::DataNormalizer.normalize_data_bag_item(data_bag_item, index, id, "DELETE") } ]
75
+ end
76
+
77
+ [
78
+ request.rest_path[0..1] + relative_parts,
79
+ normalize_proc,
80
+ ]
81
+ end
82
+
83
+ def expand_for_indexing(value, index, id)
84
+ if index == "node"
85
+ result = {}
86
+ deep_merge!(value["default"] || {}, result)
87
+ deep_merge!(value["normal"] || {}, result)
88
+ deep_merge!(value["override"] || {}, result)
89
+ deep_merge!(value["automatic"] || {}, result)
90
+ result["recipe"] = []
91
+ result["role"] = []
92
+ if value["run_list"]
93
+ value["run_list"].each do |run_list_entry|
94
+ if run_list_entry =~ /^(recipe|role)\[(.*)\]/
95
+ result[$1] << $2
96
+ end
97
+ end
98
+ end
99
+ value.each_pair do |key, val|
100
+ result[key] = val unless %w{default normal override automatic}.include?(key)
101
+ end
102
+ result
103
+
104
+ elsif !%w{client environment role}.include?(index)
105
+ ChefData::DataNormalizer.normalize_data_bag_item(value, index, id, "GET")
106
+ else
107
+ value
108
+ end
109
+ end
110
+
111
+ def search(request, orgname = nil)
112
+ # Extract parameters
113
+ index = request.rest_path[3]
114
+ query_string = request.query_params["q"] || "*:*"
115
+ solr_query = ChefZero::Solr::SolrParser.new(query_string).parse
116
+ sort_string = request.query_params["sort"]
117
+ start = request.query_params["start"].to_i
118
+ rows = request.query_params["rows"].to_i
119
+
120
+ # Get the search container
121
+ container, expander = search_container(request, index, orgname)
122
+
123
+ # Search!
124
+ result = []
125
+ list_data(request, container).each do |name|
126
+ value = get_data(request, container + [name])
127
+ expanded = expander.call(FFI_Yajl::Parser.parse(value), name)
128
+ result << [ name, build_uri(request.base_uri, container + [name]), expanded, expand_for_indexing(expanded, index, name) ]
129
+ end
130
+ result = result.select do |name, uri, value, search_value|
131
+ solr_query.matches_doc?(ChefZero::Solr::SolrDoc.new(search_value, name))
132
+ end
133
+ total = result.size
134
+
135
+ # Sort
136
+ if sort_string
137
+ sort_key, sort_order = sort_string.split(/\s+/, 2)
138
+ result = result.sort_by { |name, uri, value, search_value| ChefZero::Solr::SolrDoc.new(search_value, name)[sort_key] }
139
+ result = result.reverse if sort_order == "DESC"
140
+ end
141
+
142
+ {
143
+ # Paginate
144
+ #
145
+ # Slice the array based on the value of the "rows" query parameter. If
146
+ # this is a positive integer, we'll get the number of rows asked for.
147
+ # If it's nil, we'll get -1, which gives us all of the elements.
148
+ #
149
+ # Do the same for "start", which will start at 0 if that value is not
150
+ # given.
151
+ "rows" => result[start..(rows - 1)],
152
+ # Also return start and total in the object
153
+ "start" => start,
154
+ "total" => total,
155
+ }
156
+ end
157
+
158
+ # Deep Merge core documentation.
159
+ # deep_merge! method permits merging of arbitrary child elements. The two top level
160
+ # elements must be hashes. These hashes can contain unlimited (to stack limit) levels
161
+ # of child elements. These child elements to not have to be of the same types.
162
+ # Where child elements are of the same type, deep_merge will attempt to merge them together.
163
+ # Where child elements are not of the same type, deep_merge will skip or optionally overwrite
164
+ # the destination element with the contents of the source element at that level.
165
+ # So if you have two hashes like this:
166
+ # source = {:x => [1,2,3], :y => 2}
167
+ # dest = {:x => [4,5,'6'], :y => [7,8,9]}
168
+ # dest.deep_merge!(source)
169
+ # Results: {:x => [1,2,3,4,5,'6'], :y => 2}
170
+ # By default, "deep_merge!" will overwrite any unmergeables and merge everything else.
171
+ # To avoid this, use "deep_merge" (no bang/exclamation mark)
172
+ def deep_merge!(source, dest)
173
+ # if dest doesn't exist, then simply copy source to it
174
+ if dest.nil?
175
+ dest = source; return dest
176
+ end
177
+
178
+ case source
179
+ when nil
180
+ dest
181
+ when Hash
182
+ source.each do |src_key, src_value|
183
+ if dest.is_a?(Hash)
184
+ if dest[src_key]
185
+ dest[src_key] = deep_merge!(src_value, dest[src_key])
186
+ else # dest[src_key] doesn't exist so we take whatever source has
187
+ dest[src_key] = src_value
188
+ end
189
+ else # dest isn't a hash, so we overwrite it completely
190
+ dest = source
191
+ end
192
+ end
193
+ when Array
194
+ if dest.is_a?(Array)
195
+ dest |= source
196
+ else
197
+ dest = source
198
+ end
199
+ when String
200
+ dest = source
201
+ else # src_hash is not an array or hash, so we'll have to overwrite dest
202
+ dest = source
203
+ end
204
+ dest
205
+ end # deep_merge!
206
+ end
207
+ end
208
+ end
@@ -1,18 +1,18 @@
1
- require_relative "../rest_base"
2
-
3
- module ChefZero
4
- module Endpoints
5
- # /search
6
- class SearchesEndpoint < RestBase
7
- def get(request)
8
- # Get the result
9
- result_hash = {}
10
- indices = (%w{client environment node role} + data_store.list(request.rest_path[0..1] + ["data"])).sort
11
- indices.each do |index|
12
- result_hash[index] = build_uri(request.base_uri, request.rest_path + [index])
13
- end
14
- json_response(200, result_hash)
15
- end
16
- end
17
- end
18
- end
1
+ require_relative "../rest_base"
2
+
3
+ module ChefZero
4
+ module Endpoints
5
+ # /search
6
+ class SearchesEndpoint < RestBase
7
+ def get(request)
8
+ # Get the result
9
+ result_hash = {}
10
+ indices = (%w{client environment node role} + data_store.list(request.rest_path[0..1] + ["data"])).sort
11
+ indices.each do |index|
12
+ result_hash[index] = build_uri(request.base_uri, request.rest_path + [index])
13
+ end
14
+ json_response(200, result_hash)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,14 +1,14 @@
1
- require_relative "../rest_base"
2
-
3
- module ChefZero
4
- module Endpoints
5
- # /server_api_version
6
- class ServerAPIVersionEndpoint < RestBase
7
- API_VERSION = 2
8
- def get(request)
9
- json_response(200, { "min_api_version" => MIN_API_VERSION, "max_api_version" => MAX_API_VERSION },
10
- request_version: request.api_version, response_version: API_VERSION)
11
- end
12
- end
13
- end
14
- end
1
+ require_relative "../rest_base"
2
+
3
+ module ChefZero
4
+ module Endpoints
5
+ # /server_api_version
6
+ class ServerAPIVersionEndpoint < RestBase
7
+ API_VERSION = 2
8
+ def get(request)
9
+ json_response(200, { "min_api_version" => MIN_API_VERSION, "max_api_version" => MAX_API_VERSION },
10
+ request_version: request.api_version, response_version: API_VERSION)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,30 +1,30 @@
1
- require "ffi_yajl" unless defined?(FFI_Yajl)
2
- require_relative "../rest_base"
3
-
4
- module ChefZero
5
- module Endpoints
6
- # /system_recovery
7
- class SystemRecoveryEndpoint < RestBase
8
- def post(request)
9
- request_json = FFI_Yajl::Parser.parse(request.body)
10
- name = request_json["username"]
11
- password = request_json["password"]
12
- user = get_data(request, request.rest_path[0..-2] + ["users", name], :nil)
13
- unless user
14
- raise RestErrorResponse.new(403, "Nonexistent user")
15
- end
16
-
17
- user = FFI_Yajl::Parser.parse(user)
18
- user = ChefData::DataNormalizer.normalize_user(user, name, [ "username" ], server.options[:osc_compat])
19
- unless user["recovery_authentication_enabled"]
20
- raise RestErrorResponse.new(403, "Only users with recovery_authentication_enabled=true may use /system_recovery to log in")
21
- end
22
- if user["password"] != password
23
- raise RestErrorResponse.new(401, "Incorrect password")
24
- end
25
-
26
- json_response(200, user)
27
- end
28
- end
29
- end
30
- end
1
+ require "ffi_yajl" unless defined?(FFI_Yajl)
2
+ require_relative "../rest_base"
3
+
4
+ module ChefZero
5
+ module Endpoints
6
+ # /system_recovery
7
+ class SystemRecoveryEndpoint < RestBase
8
+ def post(request)
9
+ request_json = FFI_Yajl::Parser.parse(request.body)
10
+ name = request_json["username"]
11
+ password = request_json["password"]
12
+ user = get_data(request, request.rest_path[0..-2] + ["users", name], :nil)
13
+ unless user
14
+ raise RestErrorResponse.new(403, "Nonexistent user")
15
+ end
16
+
17
+ user = FFI_Yajl::Parser.parse(user)
18
+ user = ChefData::DataNormalizer.normalize_user(user, name, [ "username" ], server.options[:osc_compat])
19
+ unless user["recovery_authentication_enabled"]
20
+ raise RestErrorResponse.new(403, "Only users with recovery_authentication_enabled=true may use /system_recovery to log in")
21
+ end
22
+ if user["password"] != password
23
+ raise RestErrorResponse.new(401, "Incorrect password")
24
+ end
25
+
26
+ json_response(200, user)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,15 +1,15 @@
1
- require "ffi_yajl" unless defined?(FFI_Yajl)
2
- require_relative "rest_object_endpoint"
3
- require_relative "../chef_data/data_normalizer"
4
-
5
- module ChefZero
6
- module Endpoints
7
- # /universe
8
- class UniverseEndpoint < CookbooksBase
9
-
10
- def get(request)
11
- json_response(200, format_universe_list(request, all_cookbooks_list(request)))
12
- end
13
- end
14
- end
15
- end
1
+ require "ffi_yajl" unless defined?(FFI_Yajl)
2
+ require_relative "rest_object_endpoint"
3
+ require_relative "../chef_data/data_normalizer"
4
+
5
+ module ChefZero
6
+ module Endpoints
7
+ # /universe
8
+ class UniverseEndpoint < CookbooksBase
9
+
10
+ def get(request)
11
+ json_response(200, format_universe_list(request, all_cookbooks_list(request)))
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,41 +1,41 @@
1
- require "ffi_yajl" unless defined?(FFI_Yajl)
2
- require_relative "../rest_base"
3
-
4
- module ChefZero
5
- module Endpoints
6
- # /users/USER/association_requests/ID
7
- class UserAssociationRequestEndpoint < RestBase
8
- def put(request)
9
- username = request.rest_path[1]
10
- id = request.rest_path[3]
11
- if id !~ /^#{username}-(.+)/
12
- raise RestErrorResponse.new(400, "Association request #{id} is invalid. Must be #{username}-orgname.")
13
- end
14
-
15
- orgname = $1
16
-
17
- json = FFI_Yajl::Parser.parse(request.body)
18
- association_request_path = [ "organizations", orgname, "association_requests", username ]
19
- if json["response"] == "accept"
20
- users = get_data(request, [ "organizations", orgname, "groups", "users" ])
21
- users = FFI_Yajl::Parser.parse(users)
22
-
23
- delete_data(request, association_request_path)
24
- create_data(request, [ "organizations", orgname, "users" ], username, "{}")
25
-
26
- # Add the user to the users group if it isn't already there
27
- if !users["users"] || !users["users"].include?(username)
28
- users["users"] ||= []
29
- users["users"] |= [ username ]
30
- set_data(request, [ "organizations", orgname, "groups", "users" ], FFI_Yajl::Encoder.encode(users, pretty: true))
31
- end
32
- elsif json["response"] == "reject"
33
- delete_data(request, association_request_path)
34
- else
35
- raise RestErrorResponse.new(400, "response parameter was missing or set to the wrong value (must be accept or reject)")
36
- end
37
- json_response(200, { "organization" => { "name" => orgname } })
38
- end
39
- end
40
- end
41
- end
1
+ require "ffi_yajl" unless defined?(FFI_Yajl)
2
+ require_relative "../rest_base"
3
+
4
+ module ChefZero
5
+ module Endpoints
6
+ # /users/USER/association_requests/ID
7
+ class UserAssociationRequestEndpoint < RestBase
8
+ def put(request)
9
+ username = request.rest_path[1]
10
+ id = request.rest_path[3]
11
+ if id !~ /^#{username}-(.+)/
12
+ raise RestErrorResponse.new(400, "Association request #{id} is invalid. Must be #{username}-orgname.")
13
+ end
14
+
15
+ orgname = $1
16
+
17
+ json = FFI_Yajl::Parser.parse(request.body)
18
+ association_request_path = [ "organizations", orgname, "association_requests", username ]
19
+ if json["response"] == "accept"
20
+ users = get_data(request, [ "organizations", orgname, "groups", "users" ])
21
+ users = FFI_Yajl::Parser.parse(users)
22
+
23
+ delete_data(request, association_request_path)
24
+ create_data(request, [ "organizations", orgname, "users" ], username, "{}")
25
+
26
+ # Add the user to the users group if it isn't already there
27
+ if !users["users"] || !users["users"].include?(username)
28
+ users["users"] ||= []
29
+ users["users"] |= [ username ]
30
+ set_data(request, [ "organizations", orgname, "groups", "users" ], FFI_Yajl::Encoder.encode(users, pretty: true))
31
+ end
32
+ elsif json["response"] == "reject"
33
+ delete_data(request, association_request_path)
34
+ else
35
+ raise RestErrorResponse.new(400, "response parameter was missing or set to the wrong value (must be accept or reject)")
36
+ end
37
+ json_response(200, { "organization" => { "name" => orgname } })
38
+ end
39
+ end
40
+ end
41
+ end