chef-zero 2.0.2 → 2.1
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.
- checksums.yaml +4 -4
- data/lib/chef_zero/data_normalizer.rb +6 -2
- data/lib/chef_zero/data_store/interface_v1.rb +49 -0
- data/lib/chef_zero/data_store/interface_v2.rb +18 -0
- data/lib/chef_zero/data_store/memory_store.rb +6 -141
- data/lib/chef_zero/data_store/memory_store_v2.rb +188 -0
- data/lib/chef_zero/data_store/v1_to_v2_adapter.rb +190 -0
- data/lib/chef_zero/data_store/v2_to_v1_adapter.rb +107 -0
- data/lib/chef_zero/endpoints/actor_endpoint.rb +6 -12
- data/lib/chef_zero/endpoints/authenticate_user_endpoint.rb +1 -1
- data/lib/chef_zero/endpoints/cookbook_endpoint.rb +5 -5
- data/lib/chef_zero/endpoints/cookbook_version_endpoint.rb +16 -16
- data/lib/chef_zero/endpoints/cookbooks_base.rb +5 -5
- data/lib/chef_zero/endpoints/cookbooks_endpoint.rb +1 -1
- data/lib/chef_zero/endpoints/data_bag_endpoint.rb +2 -2
- data/lib/chef_zero/endpoints/data_bag_item_endpoint.rb +1 -1
- data/lib/chef_zero/endpoints/data_bags_endpoint.rb +2 -2
- data/lib/chef_zero/endpoints/environment_cookbook_endpoint.rb +3 -3
- data/lib/chef_zero/endpoints/environment_cookbook_versions_endpoint.rb +9 -9
- data/lib/chef_zero/endpoints/environment_cookbooks_endpoint.rb +2 -2
- data/lib/chef_zero/endpoints/environment_endpoint.rb +3 -3
- data/lib/chef_zero/endpoints/environment_nodes_endpoint.rb +5 -5
- data/lib/chef_zero/endpoints/environment_recipes_endpoint.rb +3 -3
- data/lib/chef_zero/endpoints/environment_role_endpoint.rb +6 -6
- data/lib/chef_zero/endpoints/node_endpoint.rb +1 -1
- data/lib/chef_zero/endpoints/principal_endpoint.rb +2 -2
- data/lib/chef_zero/endpoints/rest_object_endpoint.rb +3 -3
- data/lib/chef_zero/endpoints/role_endpoint.rb +1 -1
- data/lib/chef_zero/endpoints/role_environments_endpoint.rb +1 -1
- data/lib/chef_zero/endpoints/sandbox_endpoint.rb +3 -3
- data/lib/chef_zero/endpoints/sandboxes_endpoint.rb +2 -3
- data/lib/chef_zero/endpoints/search_endpoint.rb +13 -9
- data/lib/chef_zero/endpoints/searches_endpoint.rb +1 -1
- data/lib/chef_zero/rest_base.rb +10 -2
- data/lib/chef_zero/rest_request.rb +4 -3
- data/lib/chef_zero/server.rb +83 -52
- data/lib/chef_zero/version.rb +1 -1
- data/spec/run.rb +72 -25
- data/spec/support/pedant.rb +4 -0
- 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[
|
43
|
+
response.delete('public_key') if !updating_public_key && request.rest_path[2] == 'users'
|
44
44
|
response.delete('password')
|
45
|
-
|
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[
|
59
|
-
response = DataNormalizer.normalize_client(response, request.rest_path[
|
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[
|
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[
|
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[
|
13
|
-
request.rest_path[
|
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[
|
20
|
-
version = request.rest_path[
|
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[
|
55
|
-
request.rest_path[
|
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[
|
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(
|
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
|
|