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.
- checksums.yaml +4 -4
- data/Gemfile +36 -31
- data/LICENSE +201 -201
- data/Rakefile +73 -68
- data/bin/chef-zero +111 -111
- data/chef-zero.gemspec +34 -33
- data/lib/chef_zero/chef_data/acl_path.rb +140 -140
- data/lib/chef_zero/chef_data/cookbook_data.rb +237 -237
- data/lib/chef_zero/chef_data/data_normalizer.rb +276 -276
- data/lib/chef_zero/chef_data/default_creator.rb +476 -476
- data/lib/chef_zero/data_store/data_already_exists_error.rb +29 -29
- data/lib/chef_zero/data_store/data_error.rb +32 -32
- data/lib/chef_zero/data_store/data_not_found_error.rb +29 -29
- data/lib/chef_zero/data_store/default_facade.rb +143 -147
- data/lib/chef_zero/data_store/interface_v1.rb +67 -67
- data/lib/chef_zero/data_store/interface_v2.rb +18 -18
- data/lib/chef_zero/data_store/memory_store.rb +33 -33
- data/lib/chef_zero/data_store/memory_store_v2.rb +159 -159
- data/lib/chef_zero/data_store/raw_file_store.rb +143 -143
- data/lib/chef_zero/data_store/v1_to_v2_adapter.rb +150 -150
- data/lib/chef_zero/data_store/v2_to_v1_adapter.rb +105 -105
- data/lib/chef_zero/dist.rb +9 -9
- data/lib/chef_zero/endpoints/acl_endpoint.rb +39 -39
- data/lib/chef_zero/endpoints/acls_endpoint.rb +41 -41
- data/lib/chef_zero/endpoints/actor_default_key_endpoint.rb +78 -78
- data/lib/chef_zero/endpoints/actor_endpoint.rb +184 -184
- data/lib/chef_zero/endpoints/actor_key_endpoint.rb +62 -62
- data/lib/chef_zero/endpoints/actor_keys_endpoint.rb +129 -129
- data/lib/chef_zero/endpoints/actors_endpoint.rb +104 -104
- data/lib/chef_zero/endpoints/authenticate_user_endpoint.rb +32 -32
- data/lib/chef_zero/endpoints/container_endpoint.rb +22 -22
- data/lib/chef_zero/endpoints/containers_endpoint.rb +25 -25
- data/lib/chef_zero/endpoints/controls_endpoint.rb +16 -16
- data/lib/chef_zero/endpoints/cookbook_artifact_endpoint.rb +24 -24
- data/lib/chef_zero/endpoints/cookbook_artifact_identifier_endpoint.rb +68 -68
- data/lib/chef_zero/endpoints/cookbook_artifacts_endpoint.rb +34 -34
- data/lib/chef_zero/endpoints/cookbook_endpoint.rb +39 -39
- data/lib/chef_zero/endpoints/cookbook_version_endpoint.rb +136 -136
- data/lib/chef_zero/endpoints/cookbooks_base.rb +80 -80
- data/lib/chef_zero/endpoints/cookbooks_endpoint.rb +19 -19
- data/lib/chef_zero/endpoints/data_bag_endpoint.rb +45 -45
- data/lib/chef_zero/endpoints/data_bag_item_endpoint.rb +25 -25
- data/lib/chef_zero/endpoints/data_bags_endpoint.rb +23 -23
- data/lib/chef_zero/endpoints/dummy_endpoint.rb +29 -29
- data/lib/chef_zero/endpoints/environment_cookbook_endpoint.rb +24 -24
- data/lib/chef_zero/endpoints/environment_cookbook_versions_endpoint.rb +126 -126
- data/lib/chef_zero/endpoints/environment_cookbooks_endpoint.rb +22 -22
- data/lib/chef_zero/endpoints/environment_endpoint.rb +33 -33
- data/lib/chef_zero/endpoints/environment_nodes_endpoint.rb +23 -23
- data/lib/chef_zero/endpoints/environment_recipes_endpoint.rb +22 -22
- data/lib/chef_zero/endpoints/environment_role_endpoint.rb +36 -36
- data/lib/chef_zero/endpoints/file_store_file_endpoint.rb +22 -22
- data/lib/chef_zero/endpoints/group_endpoint.rb +20 -20
- data/lib/chef_zero/endpoints/groups_endpoint.rb +13 -13
- data/lib/chef_zero/endpoints/license_endpoint.rb +25 -25
- data/lib/chef_zero/endpoints/node_endpoint.rb +34 -34
- data/lib/chef_zero/endpoints/node_identifiers_endpoint.rb +22 -22
- data/lib/chef_zero/endpoints/nodes_endpoint.rb +34 -34
- data/lib/chef_zero/endpoints/not_found_endpoint.rb +11 -11
- data/lib/chef_zero/endpoints/organization_association_request_endpoint.rb +22 -22
- data/lib/chef_zero/endpoints/organization_association_requests_endpoint.rb +30 -30
- data/lib/chef_zero/endpoints/organization_authenticate_user_endpoint.rb +26 -26
- data/lib/chef_zero/endpoints/organization_endpoint.rb +47 -47
- data/lib/chef_zero/endpoints/organization_user_base.rb +15 -15
- data/lib/chef_zero/endpoints/organization_user_default_key_endpoint.rb +16 -16
- data/lib/chef_zero/endpoints/organization_user_endpoint.rb +26 -26
- data/lib/chef_zero/endpoints/organization_user_key_endpoint.rb +17 -17
- data/lib/chef_zero/endpoints/organization_user_keys_endpoint.rb +17 -17
- data/lib/chef_zero/endpoints/organization_users_endpoint.rb +43 -43
- data/lib/chef_zero/endpoints/organization_validator_key_endpoint.rb +20 -20
- data/lib/chef_zero/endpoints/organizations_endpoint.rb +61 -61
- data/lib/chef_zero/endpoints/policies_endpoint.rb +26 -26
- data/lib/chef_zero/endpoints/policy_endpoint.rb +24 -24
- data/lib/chef_zero/endpoints/policy_group_endpoint.rb +46 -46
- data/lib/chef_zero/endpoints/policy_group_policy_endpoint.rb +83 -83
- data/lib/chef_zero/endpoints/policy_groups_endpoint.rb +38 -38
- data/lib/chef_zero/endpoints/policy_revision_endpoint.rb +66 -66
- data/lib/chef_zero/endpoints/policy_revisions_endpoint.rb +15 -15
- data/lib/chef_zero/endpoints/principal_endpoint.rb +55 -55
- data/lib/chef_zero/endpoints/rest_list_endpoint.rb +42 -42
- data/lib/chef_zero/endpoints/rest_object_endpoint.rb +78 -78
- data/lib/chef_zero/endpoints/role_endpoint.rb +16 -16
- data/lib/chef_zero/endpoints/role_environments_endpoint.rb +14 -14
- data/lib/chef_zero/endpoints/sandbox_endpoint.rb +27 -27
- data/lib/chef_zero/endpoints/sandboxes_endpoint.rb +51 -51
- data/lib/chef_zero/endpoints/search_endpoint.rb +208 -208
- data/lib/chef_zero/endpoints/searches_endpoint.rb +18 -18
- data/lib/chef_zero/endpoints/server_api_version_endpoint.rb +14 -14
- data/lib/chef_zero/endpoints/system_recovery_endpoint.rb +30 -30
- data/lib/chef_zero/endpoints/universe_endpoint.rb +15 -15
- data/lib/chef_zero/endpoints/user_association_request_endpoint.rb +41 -41
- data/lib/chef_zero/endpoints/user_association_requests_count_endpoint.rb +19 -19
- data/lib/chef_zero/endpoints/user_association_requests_endpoint.rb +19 -19
- data/lib/chef_zero/endpoints/user_organizations_endpoint.rb +22 -22
- data/lib/chef_zero/endpoints/version_endpoint.rb +13 -13
- data/lib/chef_zero/log.rb +7 -7
- data/lib/chef_zero/rest_base.rb +332 -332
- data/lib/chef_zero/rest_error_response.rb +11 -11
- data/lib/chef_zero/rest_request.rb +84 -88
- data/lib/chef_zero/rest_router.rb +72 -72
- data/lib/chef_zero/rspec.rb +355 -355
- data/lib/chef_zero/server.rb +730 -730
- data/lib/chef_zero/socketless_server_map.rb +92 -93
- data/lib/chef_zero/solr/query/binary_operator.rb +52 -52
- data/lib/chef_zero/solr/query/phrase.rb +23 -23
- data/lib/chef_zero/solr/query/range_query.rb +46 -46
- data/lib/chef_zero/solr/query/regexpable_query.rb +30 -30
- data/lib/chef_zero/solr/query/subquery.rb +37 -37
- data/lib/chef_zero/solr/query/term.rb +45 -45
- data/lib/chef_zero/solr/query/unary_operator.rb +41 -41
- data/lib/chef_zero/solr/solr_doc.rb +53 -53
- data/lib/chef_zero/solr/solr_parser.rb +208 -208
- data/lib/chef_zero/version.rb +3 -3
- data/lib/chef_zero.rb +10 -10
- data/spec/run_oc_pedant.rb +226 -226
- data/spec/search_spec.rb +36 -36
- data/spec/server_spec.rb +96 -96
- data/spec/socketless_server_map_spec.rb +74 -74
- data/spec/support/oc_pedant.rb +149 -149
- data/spec/support/secrets.json +6 -6
- data/spec/support/stickywicket.pem +27 -27
- metadata +35 -18
@@ -1,136 +1,136 @@
|
|
1
|
-
require "ffi_yajl" unless defined?(FFI_Yajl)
|
2
|
-
require_relative "rest_object_endpoint"
|
3
|
-
require_relative "../rest_error_response"
|
4
|
-
require_relative "../chef_data/data_normalizer"
|
5
|
-
require_relative "../data_store/data_not_found_error"
|
6
|
-
|
7
|
-
module ChefZero
|
8
|
-
module Endpoints
|
9
|
-
# /organizations/ORG/cookbooks/NAME/VERSION
|
10
|
-
class CookbookVersionEndpoint < RestObjectEndpoint
|
11
|
-
def get(request)
|
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
|
-
end
|
15
|
-
super(request)
|
16
|
-
end
|
17
|
-
|
18
|
-
def put(request)
|
19
|
-
name = request.rest_path[3]
|
20
|
-
version = request.rest_path[4]
|
21
|
-
existing_cookbook = get_data(request, request.rest_path, :nil)
|
22
|
-
|
23
|
-
# Honor frozen
|
24
|
-
if existing_cookbook
|
25
|
-
existing_cookbook_json = FFI_Yajl::Parser.parse(existing_cookbook)
|
26
|
-
if existing_cookbook_json["frozen?"]
|
27
|
-
if request.query_params["force"] != "true"
|
28
|
-
raise RestErrorResponse.new(409, "The cookbook #{name} at version #{version} is frozen. Use the 'force' option to override.")
|
29
|
-
end
|
30
|
-
|
31
|
-
# For some reason, you are forever unable to modify "frozen?" on a frozen cookbook.
|
32
|
-
request_body = FFI_Yajl::Parser.parse(request.body)
|
33
|
-
unless request_body["frozen?"]
|
34
|
-
request_body["frozen?"] = true
|
35
|
-
request.body = FFI_Yajl::Encoder.encode(request_body, pretty: true)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
# Set the cookbook
|
41
|
-
set_data(request, request.rest_path, populate_defaults(request, request.body), :create_dir, :create)
|
42
|
-
|
43
|
-
# If the cookbook was updated, check for deleted files and clean them up
|
44
|
-
if existing_cookbook
|
45
|
-
missing_checksums = get_checksums(existing_cookbook) - get_checksums(request.body)
|
46
|
-
if missing_checksums.size > 0
|
47
|
-
hoover_unused_checksums(missing_checksums, request)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
already_json_response(existing_cookbook ? 200 : 201, populate_defaults(request, request.body, normalize: false))
|
52
|
-
end
|
53
|
-
|
54
|
-
def delete(request)
|
55
|
-
if request.rest_path[4] == "_latest" || request.rest_path[4] == "latest"
|
56
|
-
request.rest_path[4] = latest_version(list_data(request, request.rest_path[0..3]))
|
57
|
-
end
|
58
|
-
|
59
|
-
deleted_cookbook = get_data(request)
|
60
|
-
|
61
|
-
response = super(request)
|
62
|
-
# Last one out turns out the lights: delete /organizations/ORG/cookbooks/NAME if it no longer has versions
|
63
|
-
cookbook_path = request.rest_path[0..3]
|
64
|
-
if exists_data_dir?(request, cookbook_path) && list_data(request, cookbook_path).size == 0
|
65
|
-
delete_data_dir(request, cookbook_path)
|
66
|
-
end
|
67
|
-
|
68
|
-
# Hoover deleted files, if they exist
|
69
|
-
hoover_unused_checksums(get_checksums(deleted_cookbook), request)
|
70
|
-
response
|
71
|
-
end
|
72
|
-
|
73
|
-
def get_checksums(cookbook)
|
74
|
-
result = []
|
75
|
-
FFI_Yajl::Parser.parse(cookbook).each_pair do |key, value|
|
76
|
-
if value.is_a?(Array)
|
77
|
-
value.each do |file|
|
78
|
-
if file.is_a?(Hash) && file.key?("checksum")
|
79
|
-
result << file["checksum"]
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
result.uniq
|
85
|
-
end
|
86
|
-
|
87
|
-
private
|
88
|
-
|
89
|
-
def hoover_unused_checksums(deleted_checksums, request)
|
90
|
-
%w{cookbooks cookbook_artifacts}.each do |cookbook_type|
|
91
|
-
begin
|
92
|
-
cookbooks = data_store.list(request.rest_path[0..1] + [cookbook_type])
|
93
|
-
rescue ChefZero::DataStore::DataNotFoundError
|
94
|
-
# Not all chef versions support cookbook_artifacts
|
95
|
-
raise unless cookbook_type == "cookbook_artifacts"
|
96
|
-
|
97
|
-
cookbooks = []
|
98
|
-
end
|
99
|
-
cookbooks.each do |cookbook_name|
|
100
|
-
# as below, this can be racy.
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
end
|
109
|
-
end
|
110
|
-
deleted_checksums.each do |checksum|
|
111
|
-
# There can be a race here if multiple cookbooks are uploading.
|
112
|
-
# This deals with an exception on delete, but things can still get deleted
|
113
|
-
# that shouldn't be.
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
def populate_defaults(request, response_json, normalize: true)
|
122
|
-
# Inject URIs into each cookbook file
|
123
|
-
cookbook = FFI_Yajl::Parser.parse(response_json)
|
124
|
-
cookbook["chef_type"] ||= "cookbook_version"
|
125
|
-
cookbook["json_class"] ||= "Chef::CookbookVersion"
|
126
|
-
cookbook = ChefData::DataNormalizer.normalize_cookbook(self, request.rest_path[0..1], cookbook, request.rest_path[3], request.rest_path[4], request.base_uri, request.method, false, api_version: request.api_version) if normalize
|
127
|
-
FFI_Yajl::Encoder.encode(cookbook, pretty: true)
|
128
|
-
end
|
129
|
-
|
130
|
-
def latest_version(versions)
|
131
|
-
sorted = versions.sort_by { |version| Gem::Version.new(version.dup) }
|
132
|
-
sorted[-1]
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
1
|
+
require "ffi_yajl" unless defined?(FFI_Yajl)
|
2
|
+
require_relative "rest_object_endpoint"
|
3
|
+
require_relative "../rest_error_response"
|
4
|
+
require_relative "../chef_data/data_normalizer"
|
5
|
+
require_relative "../data_store/data_not_found_error"
|
6
|
+
|
7
|
+
module ChefZero
|
8
|
+
module Endpoints
|
9
|
+
# /organizations/ORG/cookbooks/NAME/VERSION
|
10
|
+
class CookbookVersionEndpoint < RestObjectEndpoint
|
11
|
+
def get(request)
|
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
|
+
end
|
15
|
+
super(request)
|
16
|
+
end
|
17
|
+
|
18
|
+
def put(request)
|
19
|
+
name = request.rest_path[3]
|
20
|
+
version = request.rest_path[4]
|
21
|
+
existing_cookbook = get_data(request, request.rest_path, :nil)
|
22
|
+
|
23
|
+
# Honor frozen
|
24
|
+
if existing_cookbook
|
25
|
+
existing_cookbook_json = FFI_Yajl::Parser.parse(existing_cookbook)
|
26
|
+
if existing_cookbook_json["frozen?"]
|
27
|
+
if request.query_params["force"] != "true"
|
28
|
+
raise RestErrorResponse.new(409, "The cookbook #{name} at version #{version} is frozen. Use the 'force' option to override.")
|
29
|
+
end
|
30
|
+
|
31
|
+
# For some reason, you are forever unable to modify "frozen?" on a frozen cookbook.
|
32
|
+
request_body = FFI_Yajl::Parser.parse(request.body)
|
33
|
+
unless request_body["frozen?"]
|
34
|
+
request_body["frozen?"] = true
|
35
|
+
request.body = FFI_Yajl::Encoder.encode(request_body, pretty: true)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Set the cookbook
|
41
|
+
set_data(request, request.rest_path, populate_defaults(request, request.body), :create_dir, :create)
|
42
|
+
|
43
|
+
# If the cookbook was updated, check for deleted files and clean them up
|
44
|
+
if existing_cookbook
|
45
|
+
missing_checksums = get_checksums(existing_cookbook) - get_checksums(request.body)
|
46
|
+
if missing_checksums.size > 0
|
47
|
+
hoover_unused_checksums(missing_checksums, request)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
already_json_response(existing_cookbook ? 200 : 201, populate_defaults(request, request.body, normalize: false))
|
52
|
+
end
|
53
|
+
|
54
|
+
def delete(request)
|
55
|
+
if request.rest_path[4] == "_latest" || request.rest_path[4] == "latest"
|
56
|
+
request.rest_path[4] = latest_version(list_data(request, request.rest_path[0..3]))
|
57
|
+
end
|
58
|
+
|
59
|
+
deleted_cookbook = get_data(request)
|
60
|
+
|
61
|
+
response = super(request)
|
62
|
+
# Last one out turns out the lights: delete /organizations/ORG/cookbooks/NAME if it no longer has versions
|
63
|
+
cookbook_path = request.rest_path[0..3]
|
64
|
+
if exists_data_dir?(request, cookbook_path) && list_data(request, cookbook_path).size == 0
|
65
|
+
delete_data_dir(request, cookbook_path)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Hoover deleted files, if they exist
|
69
|
+
hoover_unused_checksums(get_checksums(deleted_cookbook), request)
|
70
|
+
response
|
71
|
+
end
|
72
|
+
|
73
|
+
def get_checksums(cookbook)
|
74
|
+
result = []
|
75
|
+
FFI_Yajl::Parser.parse(cookbook).each_pair do |key, value|
|
76
|
+
if value.is_a?(Array)
|
77
|
+
value.each do |file|
|
78
|
+
if file.is_a?(Hash) && file.key?("checksum")
|
79
|
+
result << file["checksum"]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
result.uniq
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def hoover_unused_checksums(deleted_checksums, request)
|
90
|
+
%w{cookbooks cookbook_artifacts}.each do |cookbook_type|
|
91
|
+
begin
|
92
|
+
cookbooks = data_store.list(request.rest_path[0..1] + [cookbook_type])
|
93
|
+
rescue ChefZero::DataStore::DataNotFoundError
|
94
|
+
# Not all chef versions support cookbook_artifacts
|
95
|
+
raise unless cookbook_type == "cookbook_artifacts"
|
96
|
+
|
97
|
+
cookbooks = []
|
98
|
+
end
|
99
|
+
cookbooks.each do |cookbook_name|
|
100
|
+
# as below, this can be racy.
|
101
|
+
|
102
|
+
data_store.list(request.rest_path[0..1] + [cookbook_type, cookbook_name]).each do |version|
|
103
|
+
cookbook = data_store.get(request.rest_path[0..1] + [cookbook_type, cookbook_name, version], request)
|
104
|
+
deleted_checksums -= get_checksums(cookbook)
|
105
|
+
end
|
106
|
+
rescue ChefZero::DataStore::DataNotFoundError
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
110
|
+
deleted_checksums.each do |checksum|
|
111
|
+
# There can be a race here if multiple cookbooks are uploading.
|
112
|
+
# This deals with an exception on delete, but things can still get deleted
|
113
|
+
# that shouldn't be.
|
114
|
+
|
115
|
+
delete_data(request, request.rest_path[0..1] + ["file_store", "checksums", checksum], :data_store_exceptions)
|
116
|
+
rescue ChefZero::DataStore::DataNotFoundError
|
117
|
+
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def populate_defaults(request, response_json, normalize: true)
|
122
|
+
# Inject URIs into each cookbook file
|
123
|
+
cookbook = FFI_Yajl::Parser.parse(response_json)
|
124
|
+
cookbook["chef_type"] ||= "cookbook_version"
|
125
|
+
cookbook["json_class"] ||= "Chef::CookbookVersion"
|
126
|
+
cookbook = ChefData::DataNormalizer.normalize_cookbook(self, request.rest_path[0..1], cookbook, request.rest_path[3], request.rest_path[4], request.base_uri, request.method, false, api_version: request.api_version) if normalize
|
127
|
+
FFI_Yajl::Encoder.encode(cookbook, pretty: true)
|
128
|
+
end
|
129
|
+
|
130
|
+
def latest_version(versions)
|
131
|
+
sorted = versions.sort_by { |version| Gem::Version.new(version.dup) }
|
132
|
+
sorted[-1]
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -1,80 +1,80 @@
|
|
1
|
-
require "ffi_yajl" unless defined?(FFI_Yajl)
|
2
|
-
require_relative "../rest_base"
|
3
|
-
require_relative "../chef_data/data_normalizer"
|
4
|
-
|
5
|
-
module ChefZero
|
6
|
-
module Endpoints
|
7
|
-
# Common code for endpoints that return cookbook lists
|
8
|
-
class CookbooksBase < RestBase
|
9
|
-
def format_cookbooks_list(request, cookbooks_list, constraints = {}, num_versions = nil)
|
10
|
-
results = {}
|
11
|
-
filter_cookbooks(cookbooks_list, constraints, num_versions) do |name, versions|
|
12
|
-
versions_list = versions.map do |version|
|
13
|
-
{
|
14
|
-
"url" => build_uri(request.base_uri, request.rest_path[0..1] + ["cookbooks", name, version]),
|
15
|
-
"version" => version,
|
16
|
-
}
|
17
|
-
end
|
18
|
-
results[name] = {
|
19
|
-
"url" => build_uri(request.base_uri, request.rest_path[0..1] + ["cookbooks", name]),
|
20
|
-
"versions" => versions_list,
|
21
|
-
}
|
22
|
-
end
|
23
|
-
results
|
24
|
-
end
|
25
|
-
|
26
|
-
def format_universe_list(request, cookbooks_list)
|
27
|
-
results = {}
|
28
|
-
cookbooks_list.each do |name, versions|
|
29
|
-
results[name] ||= {}
|
30
|
-
versions.each do |version|
|
31
|
-
cookbook_data = FFI_Yajl::Parser.parse(get_data(request, request.rest_path[0..1] + [ "cookbooks", name, version ], :nil))
|
32
|
-
results[name][version] ||= {
|
33
|
-
"dependencies" => cookbook_data["metadata"]["dependencies"],
|
34
|
-
"location_path" => build_uri(request.base_uri, request.rest_path[0..1] + ["cookbooks", name, version]),
|
35
|
-
"location_type" => "chef_server",
|
36
|
-
}
|
37
|
-
end
|
38
|
-
end
|
39
|
-
results
|
40
|
-
end
|
41
|
-
|
42
|
-
def all_cookbooks_list(request)
|
43
|
-
result = {}
|
44
|
-
# Race conditions exist here (if someone deletes while listing). I don't care.
|
45
|
-
data_store.list(request.rest_path[0..1] + ["cookbooks"]).each do |name|
|
46
|
-
result[name] = data_store.list(request.rest_path[0..1] + ["cookbooks", name])
|
47
|
-
end
|
48
|
-
result
|
49
|
-
end
|
50
|
-
|
51
|
-
def filter_cookbooks(cookbooks_list, constraints = {}, num_versions = nil)
|
52
|
-
cookbooks_list.keys.sort.each do |name|
|
53
|
-
constraint = Gem::Requirement.new(constraints[name])
|
54
|
-
versions = []
|
55
|
-
cookbooks_list[name].sort_by { |version| Gem::Version.new(version.dup) }.reverse_each do |version|
|
56
|
-
break if num_versions && versions.size >= num_versions
|
57
|
-
|
58
|
-
if constraint.satisfied_by?(Gem::Version.new(version.dup))
|
59
|
-
versions << version
|
60
|
-
end
|
61
|
-
end
|
62
|
-
yield [name, versions]
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def recipe_names(cookbook_name, cookbook)
|
67
|
-
cookbook["all_files"].inject([]) do |acc, file|
|
68
|
-
part, name = file["name"].split("/")
|
69
|
-
next acc unless part == "recipes" || File.extname(name) != ".rb"
|
70
|
-
|
71
|
-
if name == "default.rb"
|
72
|
-
acc << cookbook_name
|
73
|
-
else
|
74
|
-
acc << "#{cookbook_name}::#{File.basename(name, ".rb")}"
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
1
|
+
require "ffi_yajl" unless defined?(FFI_Yajl)
|
2
|
+
require_relative "../rest_base"
|
3
|
+
require_relative "../chef_data/data_normalizer"
|
4
|
+
|
5
|
+
module ChefZero
|
6
|
+
module Endpoints
|
7
|
+
# Common code for endpoints that return cookbook lists
|
8
|
+
class CookbooksBase < RestBase
|
9
|
+
def format_cookbooks_list(request, cookbooks_list, constraints = {}, num_versions = nil)
|
10
|
+
results = {}
|
11
|
+
filter_cookbooks(cookbooks_list, constraints, num_versions) do |name, versions|
|
12
|
+
versions_list = versions.map do |version|
|
13
|
+
{
|
14
|
+
"url" => build_uri(request.base_uri, request.rest_path[0..1] + ["cookbooks", name, version]),
|
15
|
+
"version" => version,
|
16
|
+
}
|
17
|
+
end
|
18
|
+
results[name] = {
|
19
|
+
"url" => build_uri(request.base_uri, request.rest_path[0..1] + ["cookbooks", name]),
|
20
|
+
"versions" => versions_list,
|
21
|
+
}
|
22
|
+
end
|
23
|
+
results
|
24
|
+
end
|
25
|
+
|
26
|
+
def format_universe_list(request, cookbooks_list)
|
27
|
+
results = {}
|
28
|
+
cookbooks_list.each do |name, versions|
|
29
|
+
results[name] ||= {}
|
30
|
+
versions.each do |version|
|
31
|
+
cookbook_data = FFI_Yajl::Parser.parse(get_data(request, request.rest_path[0..1] + [ "cookbooks", name, version ], :nil))
|
32
|
+
results[name][version] ||= {
|
33
|
+
"dependencies" => cookbook_data["metadata"]["dependencies"],
|
34
|
+
"location_path" => build_uri(request.base_uri, request.rest_path[0..1] + ["cookbooks", name, version]),
|
35
|
+
"location_type" => "chef_server",
|
36
|
+
}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
results
|
40
|
+
end
|
41
|
+
|
42
|
+
def all_cookbooks_list(request)
|
43
|
+
result = {}
|
44
|
+
# Race conditions exist here (if someone deletes while listing). I don't care.
|
45
|
+
data_store.list(request.rest_path[0..1] + ["cookbooks"]).each do |name|
|
46
|
+
result[name] = data_store.list(request.rest_path[0..1] + ["cookbooks", name])
|
47
|
+
end
|
48
|
+
result
|
49
|
+
end
|
50
|
+
|
51
|
+
def filter_cookbooks(cookbooks_list, constraints = {}, num_versions = nil)
|
52
|
+
cookbooks_list.keys.sort.each do |name|
|
53
|
+
constraint = Gem::Requirement.new(constraints[name])
|
54
|
+
versions = []
|
55
|
+
cookbooks_list[name].sort_by { |version| Gem::Version.new(version.dup) }.reverse_each do |version|
|
56
|
+
break if num_versions && versions.size >= num_versions
|
57
|
+
|
58
|
+
if constraint.satisfied_by?(Gem::Version.new(version.dup))
|
59
|
+
versions << version
|
60
|
+
end
|
61
|
+
end
|
62
|
+
yield [name, versions]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def recipe_names(cookbook_name, cookbook)
|
67
|
+
cookbook["all_files"].inject([]) do |acc, file|
|
68
|
+
part, name = file["name"].split("/")
|
69
|
+
next acc unless part == "recipes" || File.extname(name) != ".rb"
|
70
|
+
|
71
|
+
if name == "default.rb"
|
72
|
+
acc << cookbook_name
|
73
|
+
else
|
74
|
+
acc << "#{cookbook_name}::#{File.basename(name, ".rb")}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -1,19 +1,19 @@
|
|
1
|
-
require_relative "cookbooks_base"
|
2
|
-
|
3
|
-
module ChefZero
|
4
|
-
module Endpoints
|
5
|
-
# /cookbooks
|
6
|
-
class CookbooksEndpoint < CookbooksBase
|
7
|
-
def get(request)
|
8
|
-
if request.query_params["num_versions"] == "all"
|
9
|
-
num_versions = nil
|
10
|
-
elsif request.query_params["num_versions"]
|
11
|
-
num_versions = request.query_params["num_versions"].to_i
|
12
|
-
else
|
13
|
-
num_versions = 1
|
14
|
-
end
|
15
|
-
json_response(200, format_cookbooks_list(request, all_cookbooks_list(request), {}, num_versions))
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
1
|
+
require_relative "cookbooks_base"
|
2
|
+
|
3
|
+
module ChefZero
|
4
|
+
module Endpoints
|
5
|
+
# /cookbooks
|
6
|
+
class CookbooksEndpoint < CookbooksBase
|
7
|
+
def get(request)
|
8
|
+
if request.query_params["num_versions"] == "all"
|
9
|
+
num_versions = nil
|
10
|
+
elsif request.query_params["num_versions"]
|
11
|
+
num_versions = request.query_params["num_versions"].to_i
|
12
|
+
else
|
13
|
+
num_versions = 1
|
14
|
+
end
|
15
|
+
json_response(200, format_cookbooks_list(request, all_cookbooks_list(request), {}, num_versions))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,45 +1,45 @@
|
|
1
|
-
require "ffi_yajl" unless defined?(FFI_Yajl)
|
2
|
-
require_relative "rest_list_endpoint"
|
3
|
-
require_relative "data_bag_item_endpoint"
|
4
|
-
require_relative "../rest_error_response"
|
5
|
-
|
6
|
-
module ChefZero
|
7
|
-
module Endpoints
|
8
|
-
# /data/NAME
|
9
|
-
class DataBagEndpoint < RestListEndpoint
|
10
|
-
def initialize(server)
|
11
|
-
super(server, "id")
|
12
|
-
end
|
13
|
-
|
14
|
-
def post(request)
|
15
|
-
json = FFI_Yajl::Parser.parse(request.body)
|
16
|
-
key = identity_keys.map { |k| json[k] }.select { |v| v }.first
|
17
|
-
response = super(request)
|
18
|
-
if response[0] == 201
|
19
|
-
already_json_response(201, DataBagItemEndpoint.populate_defaults(request, request.body, request.rest_path[3], key))
|
20
|
-
else
|
21
|
-
response
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def get_key(contents)
|
26
|
-
data_bag_item = FFI_Yajl::Parser.parse(contents)
|
27
|
-
if data_bag_item["json_class"] == "Chef::DataBagItem" && data_bag_item["raw_data"]
|
28
|
-
data_bag_item["raw_data"]["id"]
|
29
|
-
else
|
30
|
-
data_bag_item["id"]
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def delete(request)
|
35
|
-
key = request.rest_path[3]
|
36
|
-
delete_data_dir(request, request.rest_path, :recursive)
|
37
|
-
json_response(200, {
|
38
|
-
"chef_type" => "data_bag",
|
39
|
-
"json_class" => "Chef::DataBag",
|
40
|
-
"name" => key,
|
41
|
-
})
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
1
|
+
require "ffi_yajl" unless defined?(FFI_Yajl)
|
2
|
+
require_relative "rest_list_endpoint"
|
3
|
+
require_relative "data_bag_item_endpoint"
|
4
|
+
require_relative "../rest_error_response"
|
5
|
+
|
6
|
+
module ChefZero
|
7
|
+
module Endpoints
|
8
|
+
# /data/NAME
|
9
|
+
class DataBagEndpoint < RestListEndpoint
|
10
|
+
def initialize(server)
|
11
|
+
super(server, "id")
|
12
|
+
end
|
13
|
+
|
14
|
+
def post(request)
|
15
|
+
json = FFI_Yajl::Parser.parse(request.body)
|
16
|
+
key = identity_keys.map { |k| json[k] }.select { |v| v }.first
|
17
|
+
response = super(request)
|
18
|
+
if response[0] == 201
|
19
|
+
already_json_response(201, DataBagItemEndpoint.populate_defaults(request, request.body, request.rest_path[3], key))
|
20
|
+
else
|
21
|
+
response
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_key(contents)
|
26
|
+
data_bag_item = FFI_Yajl::Parser.parse(contents)
|
27
|
+
if data_bag_item["json_class"] == "Chef::DataBagItem" && data_bag_item["raw_data"]
|
28
|
+
data_bag_item["raw_data"]["id"]
|
29
|
+
else
|
30
|
+
data_bag_item["id"]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def delete(request)
|
35
|
+
key = request.rest_path[3]
|
36
|
+
delete_data_dir(request, request.rest_path, :recursive)
|
37
|
+
json_response(200, {
|
38
|
+
"chef_type" => "data_bag",
|
39
|
+
"json_class" => "Chef::DataBag",
|
40
|
+
"name" => key,
|
41
|
+
})
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -1,25 +1,25 @@
|
|
1
|
-
require "ffi_yajl" unless defined?(FFI_Yajl)
|
2
|
-
require_relative "rest_object_endpoint"
|
3
|
-
require_relative "data_bag_item_endpoint"
|
4
|
-
require_relative "../chef_data/data_normalizer"
|
5
|
-
|
6
|
-
module ChefZero
|
7
|
-
module Endpoints
|
8
|
-
# /data/NAME/NAME
|
9
|
-
class DataBagItemEndpoint < RestObjectEndpoint
|
10
|
-
def initialize(server)
|
11
|
-
super(server, "id")
|
12
|
-
end
|
13
|
-
|
14
|
-
def populate_defaults(request, response_json)
|
15
|
-
DataBagItemEndpoint.populate_defaults(request, response_json, request.rest_path[3], request.rest_path[4])
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.populate_defaults(request, response_json, data_bag, data_bag_item)
|
19
|
-
response = FFI_Yajl::Parser.parse(response_json)
|
20
|
-
response = ChefData::DataNormalizer.normalize_data_bag_item(response, data_bag, data_bag_item, request.method)
|
21
|
-
FFI_Yajl::Encoder.encode(response, pretty: true)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
1
|
+
require "ffi_yajl" unless defined?(FFI_Yajl)
|
2
|
+
require_relative "rest_object_endpoint"
|
3
|
+
require_relative "data_bag_item_endpoint"
|
4
|
+
require_relative "../chef_data/data_normalizer"
|
5
|
+
|
6
|
+
module ChefZero
|
7
|
+
module Endpoints
|
8
|
+
# /data/NAME/NAME
|
9
|
+
class DataBagItemEndpoint < RestObjectEndpoint
|
10
|
+
def initialize(server)
|
11
|
+
super(server, "id")
|
12
|
+
end
|
13
|
+
|
14
|
+
def populate_defaults(request, response_json)
|
15
|
+
DataBagItemEndpoint.populate_defaults(request, response_json, request.rest_path[3], request.rest_path[4])
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.populate_defaults(request, response_json, data_bag, data_bag_item)
|
19
|
+
response = FFI_Yajl::Parser.parse(response_json)
|
20
|
+
response = ChefData::DataNormalizer.normalize_data_bag_item(response, data_bag, data_bag_item, request.method)
|
21
|
+
FFI_Yajl::Encoder.encode(response, pretty: true)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -1,23 +1,23 @@
|
|
1
|
-
require "ffi_yajl" unless defined?(FFI_Yajl)
|
2
|
-
require_relative "rest_list_endpoint"
|
3
|
-
|
4
|
-
module ChefZero
|
5
|
-
module Endpoints
|
6
|
-
# /data
|
7
|
-
class DataBagsEndpoint < RestListEndpoint
|
8
|
-
def post(request)
|
9
|
-
contents = request.body
|
10
|
-
json = FFI_Yajl::Parser.parse(contents)
|
11
|
-
name = identity_keys.map { |k| json[k] }.select { |v| v }.first
|
12
|
-
if name.nil?
|
13
|
-
error(400, "Must specify #{identity_keys.map(&:inspect).join(" or ")} in JSON")
|
14
|
-
elsif exists_data_dir?(request, request.rest_path[0..1] + ["data", name])
|
15
|
-
error(409, "Object already exists")
|
16
|
-
else
|
17
|
-
create_data_dir(request, request.rest_path[0..1] + ["data"], name, :recursive)
|
18
|
-
json_response(201, { "uri" => (build_uri(request.base_uri, request.rest_path + [name])).to_s })
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
1
|
+
require "ffi_yajl" unless defined?(FFI_Yajl)
|
2
|
+
require_relative "rest_list_endpoint"
|
3
|
+
|
4
|
+
module ChefZero
|
5
|
+
module Endpoints
|
6
|
+
# /data
|
7
|
+
class DataBagsEndpoint < RestListEndpoint
|
8
|
+
def post(request)
|
9
|
+
contents = request.body
|
10
|
+
json = FFI_Yajl::Parser.parse(contents)
|
11
|
+
name = identity_keys.map { |k| json[k] }.select { |v| v }.first
|
12
|
+
if name.nil?
|
13
|
+
error(400, "Must specify #{identity_keys.map(&:inspect).join(" or ")} in JSON")
|
14
|
+
elsif exists_data_dir?(request, request.rest_path[0..1] + ["data", name])
|
15
|
+
error(409, "Object already exists")
|
16
|
+
else
|
17
|
+
create_data_dir(request, request.rest_path[0..1] + ["data"], name, :recursive)
|
18
|
+
json_response(201, { "uri" => (build_uri(request.base_uri, request.rest_path + [name])).to_s })
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|