chef-zero 2.0.2 → 2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/lib/chef_zero/data_normalizer.rb +6 -2
  3. data/lib/chef_zero/data_store/interface_v1.rb +49 -0
  4. data/lib/chef_zero/data_store/interface_v2.rb +18 -0
  5. data/lib/chef_zero/data_store/memory_store.rb +6 -141
  6. data/lib/chef_zero/data_store/memory_store_v2.rb +188 -0
  7. data/lib/chef_zero/data_store/v1_to_v2_adapter.rb +190 -0
  8. data/lib/chef_zero/data_store/v2_to_v1_adapter.rb +107 -0
  9. data/lib/chef_zero/endpoints/actor_endpoint.rb +6 -12
  10. data/lib/chef_zero/endpoints/authenticate_user_endpoint.rb +1 -1
  11. data/lib/chef_zero/endpoints/cookbook_endpoint.rb +5 -5
  12. data/lib/chef_zero/endpoints/cookbook_version_endpoint.rb +16 -16
  13. data/lib/chef_zero/endpoints/cookbooks_base.rb +5 -5
  14. data/lib/chef_zero/endpoints/cookbooks_endpoint.rb +1 -1
  15. data/lib/chef_zero/endpoints/data_bag_endpoint.rb +2 -2
  16. data/lib/chef_zero/endpoints/data_bag_item_endpoint.rb +1 -1
  17. data/lib/chef_zero/endpoints/data_bags_endpoint.rb +2 -2
  18. data/lib/chef_zero/endpoints/environment_cookbook_endpoint.rb +3 -3
  19. data/lib/chef_zero/endpoints/environment_cookbook_versions_endpoint.rb +9 -9
  20. data/lib/chef_zero/endpoints/environment_cookbooks_endpoint.rb +2 -2
  21. data/lib/chef_zero/endpoints/environment_endpoint.rb +3 -3
  22. data/lib/chef_zero/endpoints/environment_nodes_endpoint.rb +5 -5
  23. data/lib/chef_zero/endpoints/environment_recipes_endpoint.rb +3 -3
  24. data/lib/chef_zero/endpoints/environment_role_endpoint.rb +6 -6
  25. data/lib/chef_zero/endpoints/node_endpoint.rb +1 -1
  26. data/lib/chef_zero/endpoints/principal_endpoint.rb +2 -2
  27. data/lib/chef_zero/endpoints/rest_object_endpoint.rb +3 -3
  28. data/lib/chef_zero/endpoints/role_endpoint.rb +1 -1
  29. data/lib/chef_zero/endpoints/role_environments_endpoint.rb +1 -1
  30. data/lib/chef_zero/endpoints/sandbox_endpoint.rb +3 -3
  31. data/lib/chef_zero/endpoints/sandboxes_endpoint.rb +2 -3
  32. data/lib/chef_zero/endpoints/search_endpoint.rb +13 -9
  33. data/lib/chef_zero/endpoints/searches_endpoint.rb +1 -1
  34. data/lib/chef_zero/rest_base.rb +10 -2
  35. data/lib/chef_zero/rest_request.rb +4 -3
  36. data/lib/chef_zero/server.rb +83 -52
  37. data/lib/chef_zero/version.rb +1 -1
  38. data/spec/run.rb +72 -25
  39. data/spec/support/pedant.rb +4 -0
  40. metadata +10 -5
@@ -0,0 +1,190 @@
1
+ require 'chef_zero/data_store/interface_v2'
2
+
3
+ module ChefZero
4
+ module DataStore
5
+ class V1ToV2Adapter < ChefZero::DataStore::InterfaceV2
6
+ def initialize(real_store, single_org)
7
+ @real_store = real_store
8
+ @single_org = single_org
9
+ # Handle defaults per V2 specification
10
+ @defaults = {
11
+ 'organizations' => {
12
+ single_org => {
13
+ 'clients' => {
14
+ 'chef-validator' => '{ "validator": true }',
15
+ 'chef-webui' => '{ "admin": true }'
16
+ },
17
+ 'environments' => {
18
+ '_default' => '{ "description": "The default Chef environment" }'
19
+ },
20
+ 'users' => {
21
+ 'admin' => '{ "admin": "true" }'
22
+ }
23
+ }
24
+ }
25
+ }
26
+ end
27
+
28
+ attr_reader :real_store
29
+ attr_reader :single_org
30
+
31
+ def clear
32
+ real_store.clear
33
+ end
34
+
35
+ def create_dir(path, name, *options)
36
+ return nil if skip_organizations?(path, name)
37
+ if using_default?(path, name)
38
+ raise DataAlreadyExistsError.new(path + [name])
39
+ end
40
+ fix_exceptions do
41
+ real_store.create_dir(path[2..-1], name, *options)
42
+ end
43
+ end
44
+
45
+ def create(path, name, data, *options)
46
+ return nil if skip_organizations?(path, name)
47
+ if using_default?(path, name)
48
+ raise DataAlreadyExistsError.new(path + [name])
49
+ end
50
+ remove_default(path, name)
51
+
52
+ fix_exceptions do
53
+ real_store.create(path[2..-1], name, data, *options)
54
+ end
55
+ end
56
+
57
+ def get(path, request=nil)
58
+ return nil if skip_organizations?(path)
59
+ if using_default?(path)
60
+ get_default(path)
61
+ else
62
+ fix_exceptions do
63
+ real_store.get(path[2..-1], request)
64
+ end
65
+ end
66
+ end
67
+
68
+ def set(path, data, *options)
69
+ return nil if skip_organizations?(path)
70
+ remove_default(path)
71
+ fix_exceptions do
72
+ real_store.set(path[2..-1], data, *options)
73
+ end
74
+ end
75
+
76
+ def delete(path)
77
+ return nil if skip_organizations?(path)
78
+ remove_default(path)
79
+ fix_exceptions do
80
+ real_store.delete(path[2..-1])
81
+ end
82
+ end
83
+
84
+ def delete_dir(path, *options)
85
+ return nil if skip_organizations?(path)
86
+ fix_exceptions do
87
+ real_store.delete_dir(path[2..-1], *options)
88
+ end
89
+ end
90
+
91
+ def list(path)
92
+ return nil if skip_organizations?(path)
93
+ fix_exceptions do
94
+ result = real_store.list(path[2..-1])
95
+ if using_default?(path)
96
+ result ||= []
97
+ get_default(path).keys.each do |value|
98
+ result << value if !result.include?(value)
99
+ end
100
+ end
101
+ result
102
+ end
103
+ end
104
+
105
+ def exists?(path)
106
+ return nil if skip_organizations?(path)
107
+ if using_default?(path)
108
+ true
109
+ else
110
+ fix_exceptions do
111
+ real_store.exists?(path[2..-1])
112
+ end
113
+ end
114
+ end
115
+
116
+ def exists_dir?(path)
117
+ return nil if skip_organizations?(path)
118
+ if using_default?(path)
119
+ true
120
+ else
121
+ fix_exceptions do
122
+ real_store.exists_dir?(path[2..-1])
123
+ end
124
+ end
125
+ end
126
+
127
+ private
128
+
129
+ def using_default?(path, name = nil)
130
+ path = path + [name] if name
131
+ result = @defaults
132
+ path.each do |part|
133
+ return false if !result.has_key?(part)
134
+ result = result[part]
135
+ end
136
+ !result.nil?
137
+ end
138
+
139
+ def get_default(path, name = nil)
140
+ path = path + [name] if name
141
+ result = @defaults
142
+ path.each do |part|
143
+ return nil if !result.has_key?(part)
144
+ result = result[part]
145
+ end
146
+ result
147
+ end
148
+
149
+ def remove_default(path, name = nil)
150
+ dir = name ? path[0..-2] : path
151
+ default = @defaults
152
+ dir.each do |part|
153
+ return if !default.has_key?(part)
154
+ default = default[part]
155
+ end
156
+
157
+ name = name || path.last
158
+ if name
159
+ default.delete(name)
160
+ end
161
+ end
162
+
163
+ def fix_exceptions
164
+ begin
165
+ yield
166
+ rescue DataAlreadyExistsError => e
167
+ raise DataAlreadyExistsError.new([ 'organizations', single_org ] + e.path, e)
168
+ rescue DataNotFoundError => e
169
+ raise DataNotFoundError.new([ 'organizations', single_org ] + e.path, e)
170
+ end
171
+ end
172
+
173
+ def skip_organizations?(path, name = nil)
174
+ if path == []
175
+ raise "" if name == nil || name != 'organizations'
176
+ true
177
+ elsif path == ['organizations']
178
+ raise "" if name == nil || name != single_org
179
+ true
180
+ else
181
+ raise "Path #{path} must start with /organizations/#{single_org}" if path[0..1] != [ 'organizations', single_org ]
182
+ if !name
183
+ raise "Path #{path} must start with /organizations/#{single_org}/<something>" if path.size <= 2
184
+ end
185
+ false
186
+ end
187
+ end
188
+ end
189
+ end
190
+ end
@@ -0,0 +1,107 @@
1
+ #
2
+ # Author:: John Keiser (<jkeiser@opscode.com>)
3
+ # Copyright:: Copyright (c) 2014 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'chef_zero/data_store/interface_v1'
20
+
21
+ module ChefZero
22
+ module DataStore
23
+ class V2ToV1Adapter < ChefZero::DataStore::InterfaceV1
24
+ def initialize
25
+ @single_org = 'chef'
26
+ end
27
+
28
+ attr_reader :real_store
29
+ attr_reader :single_org
30
+
31
+ def clear
32
+ real_store.clear
33
+ real_store.create_dir([ 'organizations' ], single_org)
34
+ end
35
+
36
+ def create_dir(path, name, *options)
37
+ fix_exceptions do
38
+ real_store.create_dir(fix_path(path), name, *options)
39
+ end
40
+ end
41
+
42
+ def create(path, name, data, *options)
43
+ fix_exceptions do
44
+ real_store.create(fix_path(path), name, data, *options)
45
+ end
46
+ end
47
+
48
+ def get(path, request=nil)
49
+ fix_exceptions do
50
+ real_store.get(fix_path(path), request)
51
+ end
52
+ end
53
+
54
+ def set(path, data, *options)
55
+ fix_exceptions do
56
+ real_store.set(fix_path(path), data, *options)
57
+ end
58
+ end
59
+
60
+ def delete(path)
61
+ fix_exceptions do
62
+ real_store.delete(fix_path(path))
63
+ end
64
+ end
65
+
66
+ def delete_dir(path, *options)
67
+ fix_exceptions do
68
+ real_store.delete_dir(fix_path(path), *options)
69
+ end
70
+ end
71
+
72
+ def list(path)
73
+ fix_exceptions do
74
+ real_store.list(fix_path(path))
75
+ end
76
+ end
77
+
78
+ def exists?(path)
79
+ fix_exceptions do
80
+ real_store.exists?(fix_path(path))
81
+ end
82
+ end
83
+
84
+ def exists_dir?(path)
85
+ fix_exceptions do
86
+ real_store.exists_dir?(fix_path(path))
87
+ end
88
+ end
89
+
90
+ protected
91
+
92
+ def fix_exceptions
93
+ begin
94
+ yield
95
+ rescue DataAlreadyExistsError => e
96
+ raise DataAlreadyExistsError.new(e.path[2..-1], e)
97
+ rescue DataNotFoundError => e
98
+ raise DataNotFoundError.new(e.path[2..-1], e)
99
+ end
100
+ end
101
+
102
+ def fix_path(path)
103
+ [ 'organizations', single_org ] + path
104
+ end
105
+ end
106
+ end
107
+ end
@@ -37,17 +37,12 @@ module ChefZero
37
37
  result = super(request)
38
38
 
39
39
  # Inject private_key into response, delete public_key/password if applicable
40
- if result[0] == 200
40
+ if result[0] == 200 || result[0] == 201
41
41
  response = JSON.parse(result[2], :create_additions => false)
42
42
  response['private_key'] = private_key if private_key
43
- response.delete('public_key') if !updating_public_key && request.rest_path[0] == 'users'
43
+ response.delete('public_key') if !updating_public_key && request.rest_path[2] == 'users'
44
44
  response.delete('password')
45
- # For PUT /clients, a rename returns 201.
46
- if request_body['name'] && request.rest_path[1] != request_body['name']
47
- json_response(201, response)
48
- else
49
- json_response(200, response)
50
- end
45
+ json_response(result[0], response)
51
46
  else
52
47
  result
53
48
  end
@@ -55,14 +50,13 @@ module ChefZero
55
50
 
56
51
  def populate_defaults(request, response_json)
57
52
  response = JSON.parse(response_json, :create_additions => false)
58
- if request.rest_path[0] == 'clients'
59
- response = DataNormalizer.normalize_client(response, request.rest_path[1])
53
+ if request.rest_path[2] == 'clients'
54
+ response = DataNormalizer.normalize_client(response, request.rest_path[3])
60
55
  else
61
- response = DataNormalizer.normalize_user(response, request.rest_path[1])
56
+ response = DataNormalizer.normalize_user(response, request.rest_path[3])
62
57
  end
63
58
  JSON.pretty_generate(response)
64
59
  end
65
60
  end
66
61
  end
67
62
  end
68
-
@@ -10,7 +10,7 @@ module ChefZero
10
10
  name = request_json['name']
11
11
  password = request_json['password']
12
12
  begin
13
- user = data_store.get(['users', name])
13
+ user = data_store.get(request.rest_path[0..1] + ['users', name])
14
14
  verified = JSON.parse(user, :create_additions => false)['password'] == password
15
15
  rescue DataStore::DataNotFoundError
16
16
  verified = false
@@ -5,21 +5,21 @@ module ChefZero
5
5
  # /cookbooks/NAME
6
6
  class CookbookEndpoint < CookbooksBase
7
7
  def get(request)
8
- filter = request.rest_path[1]
8
+ filter = request.rest_path[3]
9
9
  case filter
10
10
  when '_latest'
11
11
  result = {}
12
- filter_cookbooks(all_cookbooks_list, {}, 1) do |name, versions|
12
+ filter_cookbooks(all_cookbooks_list(request), {}, 1) do |name, versions|
13
13
  if versions.size > 0
14
- result[name] = build_uri(request.base_uri, ['cookbooks', name, versions[0]])
14
+ result[name] = build_uri(request.base_uri, request.rest_path[0..1] + ['cookbooks', name, versions[0]])
15
15
  end
16
16
  end
17
17
  json_response(200, result)
18
18
  when '_recipes'
19
19
  result = []
20
- filter_cookbooks(all_cookbooks_list, {}, 1) do |name, versions|
20
+ filter_cookbooks(all_cookbooks_list(request), {}, 1) do |name, versions|
21
21
  if versions.size > 0
22
- cookbook = JSON.parse(get_data(request, ['cookbooks', name, versions[0]]), :create_additions => false)
22
+ cookbook = JSON.parse(get_data(request, request.rest_path[0..1] + ['cookbooks', name, versions[0]]), :create_additions => false)
23
23
  result += recipe_names(name, cookbook)
24
24
  end
25
25
  end
@@ -9,17 +9,17 @@ module ChefZero
9
9
  # /cookbooks/NAME/VERSION
10
10
  class CookbookVersionEndpoint < RestObjectEndpoint
11
11
  def get(request)
12
- if request.rest_path[2] == "_latest" || request.rest_path[2] == "latest"
13
- request.rest_path[2] = latest_version(list_data(request, request.rest_path[0..1]))
12
+ if request.rest_path[4] == "_latest" || request.rest_path[4] == "latest"
13
+ request.rest_path[4] = latest_version(list_data(request, request.rest_path[0..3]))
14
14
  end
15
15
  super(request)
16
16
  end
17
17
 
18
18
  def put(request)
19
- name = request.rest_path[1]
20
- version = request.rest_path[2]
19
+ name = request.rest_path[3]
20
+ version = request.rest_path[4]
21
21
  existing_cookbook = get_data(request, request.rest_path, :nil)
22
-
22
+
23
23
  # Honor frozen
24
24
  if existing_cookbook
25
25
  existing_cookbook_json = JSON.parse(existing_cookbook, :create_additions => false)
@@ -37,7 +37,7 @@ module ChefZero
37
37
  end
38
38
 
39
39
  # Set the cookbook
40
- set_data(request, ['cookbooks', name, version], request.body, :create_dir, :create)
40
+ set_data(request, request.rest_path[0..1] + ['cookbooks', name, version], request.body, :create_dir, :create)
41
41
 
42
42
  # If the cookbook was updated, check for deleted files and clean them up
43
43
  if existing_cookbook
@@ -51,16 +51,16 @@ module ChefZero
51
51
  end
52
52
 
53
53
  def delete(request)
54
- if request.rest_path[2] == "_latest" || request.rest_path[2] == "latest"
55
- request.rest_path[2] = latest_version(list_data(request, request.rest_path[0..1]))
54
+ if request.rest_path[4] == "_latest" || request.rest_path[4] == "latest"
55
+ request.rest_path[4] = latest_version(list_data(request, request.rest_path[0..3]))
56
56
  end
57
57
 
58
58
  deleted_cookbook = get_data(request)
59
59
 
60
60
  response = super(request)
61
- cookbook_name = request.rest_path[1]
62
- if exists_data_dir?(request, [ 'cookbooks', cookbook_name ]) && list_data(request, ['cookbooks', cookbook_name]).size == 0
63
- delete_data_dir(request, ['cookbooks', cookbook_name])
61
+ cookbook_name = request.rest_path[3]
62
+ if exists_data_dir?(request, request.rest_path[0..1] + [ 'cookbooks', cookbook_name ]) && list_data(request, request.rest_path[0..1] + ['cookbooks', cookbook_name]).size == 0
63
+ delete_data_dir(request, request.rest_path[0..1] + ['cookbooks', cookbook_name])
64
64
  end
65
65
 
66
66
  # Hoover deleted files, if they exist
@@ -85,9 +85,9 @@ module ChefZero
85
85
  private
86
86
 
87
87
  def hoover_unused_checksums(deleted_checksums, request)
88
- data_store.list(['cookbooks']).each do |cookbook_name|
89
- data_store.list(['cookbooks', cookbook_name]).each do |version|
90
- cookbook = data_store.get(['cookbooks', cookbook_name, version], request)
88
+ data_store.list(request.rest_path[0..1] + ['cookbooks']).each do |cookbook_name|
89
+ data_store.list(request.rest_path[0..1] + ['cookbooks', cookbook_name]).each do |version|
90
+ cookbook = data_store.get(request.rest_path[0..1] + ['cookbooks', cookbook_name, version], request)
91
91
  deleted_checksums = deleted_checksums - get_checksums(cookbook)
92
92
  end
93
93
  end
@@ -96,7 +96,7 @@ module ChefZero
96
96
  # This deals with an exception on delete, but things can still get deleted
97
97
  # that shouldn't be.
98
98
  begin
99
- data_store.delete(['file_store', 'checksums', checksum])
99
+ data_store.delete(request.rest_path[0..1] + ['file_store', 'checksums', checksum])
100
100
  rescue ChefZero::DataStore::DataNotFoundError
101
101
  end
102
102
  end
@@ -105,7 +105,7 @@ module ChefZero
105
105
  def populate_defaults(request, response_json)
106
106
  # Inject URIs into each cookbook file
107
107
  cookbook = JSON.parse(response_json, :create_additions => false)
108
- cookbook = DataNormalizer.normalize_cookbook(cookbook, request.rest_path[1], request.rest_path[2], request.base_uri, request.method)
108
+ cookbook = DataNormalizer.normalize_cookbook(self, request.rest_path[0..1], cookbook, request.rest_path[3], request.rest_path[4], request.base_uri, request.method)
109
109
  JSON.pretty_generate(cookbook)
110
110
  end
111
111