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,29 +1,29 @@
|
|
1
|
-
|
2
|
-
# pedant makes a couple of Solr-related calls from its search_utils.rb file that we can't work around (e.g.
|
3
|
-
# with monkeypatching). the necessary Pedant::Config values are set in run_oc_pedant.rb. --cdoherty
|
4
|
-
module ChefZero
|
5
|
-
module Endpoints
|
6
|
-
class DummyEndpoint < RestBase
|
7
|
-
# called by #direct_solr_query, once each for roles, nodes, and data bag items. each RSpec example makes
|
8
|
-
# 3 calls, with the expected sequence of return values [0, 1, 0].
|
9
|
-
def get(request)
|
10
|
-
# this could be made less brittle, but if things change to have more than 3 cycles, we should really
|
11
|
-
# be notified by a spec failure.
|
12
|
-
@mock_values ||= ([0, 1, 0] * 3).map { |val| make_response(val) }
|
13
|
-
|
14
|
-
retval = @mock_values.shift
|
15
|
-
json_response(200, retval)
|
16
|
-
end
|
17
|
-
|
18
|
-
# called by #force_solr_commit in pedant's , which doesn't check the return value.
|
19
|
-
def post(request)
|
20
|
-
# sure thing!
|
21
|
-
json_response(200, { message: "This dummy POST endpoint didn't do anything." })
|
22
|
-
end
|
23
|
-
|
24
|
-
def make_response(value)
|
25
|
-
{ "response" => { "numFound" => value } }
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
1
|
+
|
2
|
+
# pedant makes a couple of Solr-related calls from its search_utils.rb file that we can't work around (e.g.
|
3
|
+
# with monkeypatching). the necessary Pedant::Config values are set in run_oc_pedant.rb. --cdoherty
|
4
|
+
module ChefZero
|
5
|
+
module Endpoints
|
6
|
+
class DummyEndpoint < RestBase
|
7
|
+
# called by #direct_solr_query, once each for roles, nodes, and data bag items. each RSpec example makes
|
8
|
+
# 3 calls, with the expected sequence of return values [0, 1, 0].
|
9
|
+
def get(request)
|
10
|
+
# this could be made less brittle, but if things change to have more than 3 cycles, we should really
|
11
|
+
# be notified by a spec failure.
|
12
|
+
@mock_values ||= ([0, 1, 0] * 3).map { |val| make_response(val) }
|
13
|
+
|
14
|
+
retval = @mock_values.shift
|
15
|
+
json_response(200, retval)
|
16
|
+
end
|
17
|
+
|
18
|
+
# called by #force_solr_commit in pedant's , which doesn't check the return value.
|
19
|
+
def post(request)
|
20
|
+
# sure thing!
|
21
|
+
json_response(200, { message: "This dummy POST endpoint didn't do anything." })
|
22
|
+
end
|
23
|
+
|
24
|
+
def make_response(value)
|
25
|
+
{ "response" => { "numFound" => value } }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -1,24 +1,24 @@
|
|
1
|
-
require "ffi_yajl" unless defined?(FFI_Yajl)
|
2
|
-
require_relative "cookbooks_base"
|
3
|
-
|
4
|
-
module ChefZero
|
5
|
-
module Endpoints
|
6
|
-
# /environments/NAME/cookbooks/NAME
|
7
|
-
class EnvironmentCookbookEndpoint < CookbooksBase
|
8
|
-
def get(request)
|
9
|
-
cookbook_name = request.rest_path[5]
|
10
|
-
environment = FFI_Yajl::Parser.parse(get_data(request, request.rest_path[0..3]))
|
11
|
-
constraints = environment["cookbook_versions"] || {}
|
12
|
-
cookbook_versions = list_data(request, request.rest_path[0..1] + request.rest_path[4..5])
|
13
|
-
if request.query_params["num_versions"] == "all"
|
14
|
-
num_versions = nil
|
15
|
-
elsif request.query_params["num_versions"]
|
16
|
-
num_versions = request.query_params["num_versions"].to_i
|
17
|
-
else
|
18
|
-
num_versions = nil
|
19
|
-
end
|
20
|
-
json_response(200, format_cookbooks_list(request, { cookbook_name => cookbook_versions }, constraints, num_versions))
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
1
|
+
require "ffi_yajl" unless defined?(FFI_Yajl)
|
2
|
+
require_relative "cookbooks_base"
|
3
|
+
|
4
|
+
module ChefZero
|
5
|
+
module Endpoints
|
6
|
+
# /environments/NAME/cookbooks/NAME
|
7
|
+
class EnvironmentCookbookEndpoint < CookbooksBase
|
8
|
+
def get(request)
|
9
|
+
cookbook_name = request.rest_path[5]
|
10
|
+
environment = FFI_Yajl::Parser.parse(get_data(request, request.rest_path[0..3]))
|
11
|
+
constraints = environment["cookbook_versions"] || {}
|
12
|
+
cookbook_versions = list_data(request, request.rest_path[0..1] + request.rest_path[4..5])
|
13
|
+
if request.query_params["num_versions"] == "all"
|
14
|
+
num_versions = nil
|
15
|
+
elsif request.query_params["num_versions"]
|
16
|
+
num_versions = request.query_params["num_versions"].to_i
|
17
|
+
else
|
18
|
+
num_versions = nil
|
19
|
+
end
|
20
|
+
json_response(200, format_cookbooks_list(request, { cookbook_name => cookbook_versions }, constraints, num_versions))
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -1,126 +1,126 @@
|
|
1
|
-
require "ffi_yajl" unless defined?(FFI_Yajl)
|
2
|
-
require_relative "../rest_base"
|
3
|
-
require_relative "../rest_error_response"
|
4
|
-
|
5
|
-
module ChefZero
|
6
|
-
module Endpoints
|
7
|
-
# /environments/NAME/cookbook_versions
|
8
|
-
class EnvironmentCookbookVersionsEndpoint < RestBase
|
9
|
-
|
10
|
-
def post(request)
|
11
|
-
cookbook_names = list_data(request, request.rest_path[0..1] + ["cookbooks"])
|
12
|
-
|
13
|
-
# Get the list of cookbooks and versions desired by the runlist
|
14
|
-
desired_versions = {}
|
15
|
-
run_list = FFI_Yajl::Parser.parse(request.body)["run_list"]
|
16
|
-
run_list.each do |run_list_entry|
|
17
|
-
if run_list_entry =~ /(.+)::.+\@(.+)/ || run_list_entry =~ /(.+)\@(.+)/
|
18
|
-
raise RestErrorResponse.new(412, "No such cookbook: #{$1}") unless cookbook_names.include?($1)
|
19
|
-
raise RestErrorResponse.new(412, "No such cookbook version for cookbook #{$1}: #{$2}") unless list_data(request, request.rest_path[0..1] + ["cookbooks", $1]).include?($2)
|
20
|
-
|
21
|
-
desired_versions[$1] = [ $2 ]
|
22
|
-
else
|
23
|
-
desired_cookbook = run_list_entry.split("::")[0]
|
24
|
-
raise RestErrorResponse.new(412, "No such cookbook: #{desired_cookbook}") unless cookbook_names.include?(desired_cookbook)
|
25
|
-
|
26
|
-
desired_versions[desired_cookbook] = list_data(request, request.rest_path[0..1] + ["cookbooks", desired_cookbook])
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
# Filter by environment constraints
|
31
|
-
environment = FFI_Yajl::Parser.parse(get_data(request, request.rest_path[0..3]))
|
32
|
-
environment_constraints = environment["cookbook_versions"] || {}
|
33
|
-
|
34
|
-
desired_versions.each_key do |name|
|
35
|
-
desired_versions = filter_by_constraint(desired_versions, name, environment_constraints[name])
|
36
|
-
end
|
37
|
-
|
38
|
-
# Depsolve!
|
39
|
-
solved = depsolve(request, desired_versions.keys, desired_versions, environment_constraints)
|
40
|
-
unless solved
|
41
|
-
if @last_missing_dep && !cookbook_names.include?(@last_missing_dep)
|
42
|
-
return raise RestErrorResponse.new(412, "No such cookbook: #{@last_missing_dep}")
|
43
|
-
elsif @last_constraint_failure
|
44
|
-
return raise RestErrorResponse.new(412, "Could not satisfy version constraints for: #{@last_constraint_failure}")
|
45
|
-
else
|
46
|
-
|
47
|
-
return raise RestErrorResponse.new(412, "Unsolvable versions!")
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
result = {}
|
52
|
-
solved.each_pair do |name, versions|
|
53
|
-
cookbook = FFI_Yajl::Parser.parse(get_data(request, request.rest_path[0..1] + ["cookbooks", name, versions[0]]))
|
54
|
-
result[name] = ChefData::DataNormalizer.normalize_cookbook(self, request.rest_path[0..1], cookbook, name, versions[0], request.base_uri, "MIN", false, api_version: request.api_version)
|
55
|
-
end
|
56
|
-
json_response(200, result)
|
57
|
-
end
|
58
|
-
|
59
|
-
def depsolve(request, unsolved, desired_versions, environment_constraints)
|
60
|
-
desired_versions.each do |cb, ver|
|
61
|
-
if ver.empty?
|
62
|
-
@last_constraint_failure = cb
|
63
|
-
return nil
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
# If everything is already
|
68
|
-
solve_for = unsolved[0]
|
69
|
-
return desired_versions unless solve_for
|
70
|
-
|
71
|
-
# Go through each desired version of this cookbook, starting with the latest,
|
72
|
-
# until we find one we can solve successfully with
|
73
|
-
sort_versions(desired_versions[solve_for]).each do |desired_version|
|
74
|
-
new_desired_versions = desired_versions.clone
|
75
|
-
new_desired_versions[solve_for] = [ desired_version ]
|
76
|
-
new_unsolved = unsolved[1..-1]
|
77
|
-
|
78
|
-
# Pick this cookbook, and add dependencies
|
79
|
-
cookbook_obj = FFI_Yajl::Parser.parse(get_data(request, request.rest_path[0..1] + ["cookbooks", solve_for, desired_version]))
|
80
|
-
cookbook_metadata = cookbook_obj["metadata"] || {}
|
81
|
-
cookbook_dependencies = cookbook_metadata["dependencies"] || {}
|
82
|
-
dep_not_found = false
|
83
|
-
cookbook_dependencies.each_pair do |dep_name, dep_constraint|
|
84
|
-
# If the dep is not already in the list, add it to the list to solve
|
85
|
-
# and bring in all environment-allowed cookbook versions to desired_versions
|
86
|
-
unless new_desired_versions.key?(dep_name)
|
87
|
-
new_unsolved += [dep_name]
|
88
|
-
# If the dep is missing, we will try other versions of the cookbook that might not have the bad dep.
|
89
|
-
unless exists_data_dir?(request, request.rest_path[0..1] + ["cookbooks", dep_name])
|
90
|
-
@last_missing_dep = dep_name.to_s
|
91
|
-
dep_not_found = true
|
92
|
-
break
|
93
|
-
end
|
94
|
-
new_desired_versions[dep_name] = list_data(request, request.rest_path[0..1] + ["cookbooks", dep_name])
|
95
|
-
new_desired_versions = filter_by_constraint(new_desired_versions, dep_name, environment_constraints[dep_name])
|
96
|
-
end
|
97
|
-
new_desired_versions = filter_by_constraint(new_desired_versions, dep_name, dep_constraint)
|
98
|
-
end
|
99
|
-
|
100
|
-
next if dep_not_found
|
101
|
-
|
102
|
-
# Depsolve children with this desired version! First solution wins.
|
103
|
-
result = depsolve(request, new_unsolved, new_desired_versions, environment_constraints)
|
104
|
-
return result if result
|
105
|
-
end
|
106
|
-
nil
|
107
|
-
end
|
108
|
-
|
109
|
-
def sort_versions(versions)
|
110
|
-
result = versions.sort_by { |version| Gem::Version.new(version.dup) }
|
111
|
-
result.reverse
|
112
|
-
end
|
113
|
-
|
114
|
-
def filter_by_constraint(versions, cookbook_name, constraint)
|
115
|
-
return versions unless constraint
|
116
|
-
|
117
|
-
constraint = Gem::Requirement.new(constraint)
|
118
|
-
new_versions = versions[cookbook_name]
|
119
|
-
new_versions = new_versions.select { |version| constraint.satisfied_by?(Gem::Version.new(version.dup)) }
|
120
|
-
result = versions.clone
|
121
|
-
result[cookbook_name] = new_versions
|
122
|
-
result
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
1
|
+
require "ffi_yajl" unless defined?(FFI_Yajl)
|
2
|
+
require_relative "../rest_base"
|
3
|
+
require_relative "../rest_error_response"
|
4
|
+
|
5
|
+
module ChefZero
|
6
|
+
module Endpoints
|
7
|
+
# /environments/NAME/cookbook_versions
|
8
|
+
class EnvironmentCookbookVersionsEndpoint < RestBase
|
9
|
+
|
10
|
+
def post(request)
|
11
|
+
cookbook_names = list_data(request, request.rest_path[0..1] + ["cookbooks"])
|
12
|
+
|
13
|
+
# Get the list of cookbooks and versions desired by the runlist
|
14
|
+
desired_versions = {}
|
15
|
+
run_list = FFI_Yajl::Parser.parse(request.body)["run_list"]
|
16
|
+
run_list.each do |run_list_entry|
|
17
|
+
if run_list_entry =~ /(.+)::.+\@(.+)/ || run_list_entry =~ /(.+)\@(.+)/
|
18
|
+
raise RestErrorResponse.new(412, "No such cookbook: #{$1}") unless cookbook_names.include?($1)
|
19
|
+
raise RestErrorResponse.new(412, "No such cookbook version for cookbook #{$1}: #{$2}") unless list_data(request, request.rest_path[0..1] + ["cookbooks", $1]).include?($2)
|
20
|
+
|
21
|
+
desired_versions[$1] = [ $2 ]
|
22
|
+
else
|
23
|
+
desired_cookbook = run_list_entry.split("::")[0]
|
24
|
+
raise RestErrorResponse.new(412, "No such cookbook: #{desired_cookbook}") unless cookbook_names.include?(desired_cookbook)
|
25
|
+
|
26
|
+
desired_versions[desired_cookbook] = list_data(request, request.rest_path[0..1] + ["cookbooks", desired_cookbook])
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Filter by environment constraints
|
31
|
+
environment = FFI_Yajl::Parser.parse(get_data(request, request.rest_path[0..3]))
|
32
|
+
environment_constraints = environment["cookbook_versions"] || {}
|
33
|
+
|
34
|
+
desired_versions.each_key do |name|
|
35
|
+
desired_versions = filter_by_constraint(desired_versions, name, environment_constraints[name])
|
36
|
+
end
|
37
|
+
|
38
|
+
# Depsolve!
|
39
|
+
solved = depsolve(request, desired_versions.keys, desired_versions, environment_constraints)
|
40
|
+
unless solved
|
41
|
+
if @last_missing_dep && !cookbook_names.include?(@last_missing_dep)
|
42
|
+
return raise RestErrorResponse.new(412, "No such cookbook: #{@last_missing_dep}")
|
43
|
+
elsif @last_constraint_failure
|
44
|
+
return raise RestErrorResponse.new(412, "Could not satisfy version constraints for: #{@last_constraint_failure}")
|
45
|
+
else
|
46
|
+
|
47
|
+
return raise RestErrorResponse.new(412, "Unsolvable versions!")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
result = {}
|
52
|
+
solved.each_pair do |name, versions|
|
53
|
+
cookbook = FFI_Yajl::Parser.parse(get_data(request, request.rest_path[0..1] + ["cookbooks", name, versions[0]]))
|
54
|
+
result[name] = ChefData::DataNormalizer.normalize_cookbook(self, request.rest_path[0..1], cookbook, name, versions[0], request.base_uri, "MIN", false, api_version: request.api_version)
|
55
|
+
end
|
56
|
+
json_response(200, result)
|
57
|
+
end
|
58
|
+
|
59
|
+
def depsolve(request, unsolved, desired_versions, environment_constraints)
|
60
|
+
desired_versions.each do |cb, ver|
|
61
|
+
if ver.empty?
|
62
|
+
@last_constraint_failure = cb
|
63
|
+
return nil
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# If everything is already
|
68
|
+
solve_for = unsolved[0]
|
69
|
+
return desired_versions unless solve_for
|
70
|
+
|
71
|
+
# Go through each desired version of this cookbook, starting with the latest,
|
72
|
+
# until we find one we can solve successfully with
|
73
|
+
sort_versions(desired_versions[solve_for]).each do |desired_version|
|
74
|
+
new_desired_versions = desired_versions.clone
|
75
|
+
new_desired_versions[solve_for] = [ desired_version ]
|
76
|
+
new_unsolved = unsolved[1..-1]
|
77
|
+
|
78
|
+
# Pick this cookbook, and add dependencies
|
79
|
+
cookbook_obj = FFI_Yajl::Parser.parse(get_data(request, request.rest_path[0..1] + ["cookbooks", solve_for, desired_version]))
|
80
|
+
cookbook_metadata = cookbook_obj["metadata"] || {}
|
81
|
+
cookbook_dependencies = cookbook_metadata["dependencies"] || {}
|
82
|
+
dep_not_found = false
|
83
|
+
cookbook_dependencies.each_pair do |dep_name, dep_constraint|
|
84
|
+
# If the dep is not already in the list, add it to the list to solve
|
85
|
+
# and bring in all environment-allowed cookbook versions to desired_versions
|
86
|
+
unless new_desired_versions.key?(dep_name)
|
87
|
+
new_unsolved += [dep_name]
|
88
|
+
# If the dep is missing, we will try other versions of the cookbook that might not have the bad dep.
|
89
|
+
unless exists_data_dir?(request, request.rest_path[0..1] + ["cookbooks", dep_name])
|
90
|
+
@last_missing_dep = dep_name.to_s
|
91
|
+
dep_not_found = true
|
92
|
+
break
|
93
|
+
end
|
94
|
+
new_desired_versions[dep_name] = list_data(request, request.rest_path[0..1] + ["cookbooks", dep_name])
|
95
|
+
new_desired_versions = filter_by_constraint(new_desired_versions, dep_name, environment_constraints[dep_name])
|
96
|
+
end
|
97
|
+
new_desired_versions = filter_by_constraint(new_desired_versions, dep_name, dep_constraint)
|
98
|
+
end
|
99
|
+
|
100
|
+
next if dep_not_found
|
101
|
+
|
102
|
+
# Depsolve children with this desired version! First solution wins.
|
103
|
+
result = depsolve(request, new_unsolved, new_desired_versions, environment_constraints)
|
104
|
+
return result if result
|
105
|
+
end
|
106
|
+
nil
|
107
|
+
end
|
108
|
+
|
109
|
+
def sort_versions(versions)
|
110
|
+
result = versions.sort_by { |version| Gem::Version.new(version.dup) }
|
111
|
+
result.reverse
|
112
|
+
end
|
113
|
+
|
114
|
+
def filter_by_constraint(versions, cookbook_name, constraint)
|
115
|
+
return versions unless constraint
|
116
|
+
|
117
|
+
constraint = Gem::Requirement.new(constraint)
|
118
|
+
new_versions = versions[cookbook_name]
|
119
|
+
new_versions = new_versions.select { |version| constraint.satisfied_by?(Gem::Version.new(version.dup)) }
|
120
|
+
result = versions.clone
|
121
|
+
result[cookbook_name] = new_versions
|
122
|
+
result
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -1,22 +1,22 @@
|
|
1
|
-
require "ffi_yajl" unless defined?(FFI_Yajl)
|
2
|
-
require_relative "cookbooks_base"
|
3
|
-
|
4
|
-
module ChefZero
|
5
|
-
module Endpoints
|
6
|
-
# /environments/NAME/cookbooks
|
7
|
-
class EnvironmentCookbooksEndpoint < CookbooksBase
|
8
|
-
def get(request)
|
9
|
-
environment = FFI_Yajl::Parser.parse(get_data(request, request.rest_path[0..3]))
|
10
|
-
constraints = environment["cookbook_versions"] || {}
|
11
|
-
if request.query_params["num_versions"] == "all"
|
12
|
-
num_versions = nil
|
13
|
-
elsif request.query_params["num_versions"]
|
14
|
-
num_versions = request.query_params["num_versions"].to_i
|
15
|
-
else
|
16
|
-
num_versions = 1
|
17
|
-
end
|
18
|
-
json_response(200, format_cookbooks_list(request, all_cookbooks_list(request), constraints, num_versions))
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
1
|
+
require "ffi_yajl" unless defined?(FFI_Yajl)
|
2
|
+
require_relative "cookbooks_base"
|
3
|
+
|
4
|
+
module ChefZero
|
5
|
+
module Endpoints
|
6
|
+
# /environments/NAME/cookbooks
|
7
|
+
class EnvironmentCookbooksEndpoint < CookbooksBase
|
8
|
+
def get(request)
|
9
|
+
environment = FFI_Yajl::Parser.parse(get_data(request, request.rest_path[0..3]))
|
10
|
+
constraints = environment["cookbook_versions"] || {}
|
11
|
+
if request.query_params["num_versions"] == "all"
|
12
|
+
num_versions = nil
|
13
|
+
elsif request.query_params["num_versions"]
|
14
|
+
num_versions = request.query_params["num_versions"].to_i
|
15
|
+
else
|
16
|
+
num_versions = 1
|
17
|
+
end
|
18
|
+
json_response(200, format_cookbooks_list(request, all_cookbooks_list(request), constraints, num_versions))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -1,33 +1,33 @@
|
|
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
|
-
# /environments/NAME
|
8
|
-
class EnvironmentEndpoint < RestObjectEndpoint
|
9
|
-
def delete(request)
|
10
|
-
if request.rest_path[3] == "_default"
|
11
|
-
# 405, really?
|
12
|
-
error(405, "The '_default' environment cannot be modified.")
|
13
|
-
else
|
14
|
-
super(request)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def put(request)
|
19
|
-
if request.rest_path[3] == "_default"
|
20
|
-
error(405, "The '_default' environment cannot be modified.")
|
21
|
-
else
|
22
|
-
super(request)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def populate_defaults(request, response_json)
|
27
|
-
response = FFI_Yajl::Parser.parse(response_json)
|
28
|
-
response = ChefData::DataNormalizer.normalize_environment(response, request.rest_path[3])
|
29
|
-
FFI_Yajl::Encoder.encode(response, pretty: true)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
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
|
+
# /environments/NAME
|
8
|
+
class EnvironmentEndpoint < RestObjectEndpoint
|
9
|
+
def delete(request)
|
10
|
+
if request.rest_path[3] == "_default"
|
11
|
+
# 405, really?
|
12
|
+
error(405, "The '_default' environment cannot be modified.")
|
13
|
+
else
|
14
|
+
super(request)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def put(request)
|
19
|
+
if request.rest_path[3] == "_default"
|
20
|
+
error(405, "The '_default' environment cannot be modified.")
|
21
|
+
else
|
22
|
+
super(request)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def populate_defaults(request, response_json)
|
27
|
+
response = FFI_Yajl::Parser.parse(response_json)
|
28
|
+
response = ChefData::DataNormalizer.normalize_environment(response, request.rest_path[3])
|
29
|
+
FFI_Yajl::Encoder.encode(response, pretty: true)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -1,23 +1,23 @@
|
|
1
|
-
require "ffi_yajl" unless defined?(FFI_Yajl)
|
2
|
-
require_relative "../rest_base"
|
3
|
-
|
4
|
-
module ChefZero
|
5
|
-
module Endpoints
|
6
|
-
# /environment/NAME/nodes
|
7
|
-
class EnvironmentNodesEndpoint < RestBase
|
8
|
-
def get(request)
|
9
|
-
# 404 if environment does not exist
|
10
|
-
get_data(request, request.rest_path[0..3])
|
11
|
-
|
12
|
-
result = {}
|
13
|
-
list_data(request, request.rest_path[0..1] + ["nodes"]).each do |name|
|
14
|
-
node = FFI_Yajl::Parser.parse(get_data(request, request.rest_path[0..1] + ["nodes", name]))
|
15
|
-
if node["chef_environment"] == request.rest_path[3]
|
16
|
-
result[name] = build_uri(request.base_uri, request.rest_path[0..1] + ["nodes", name])
|
17
|
-
end
|
18
|
-
end
|
19
|
-
json_response(200, result)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
1
|
+
require "ffi_yajl" unless defined?(FFI_Yajl)
|
2
|
+
require_relative "../rest_base"
|
3
|
+
|
4
|
+
module ChefZero
|
5
|
+
module Endpoints
|
6
|
+
# /environment/NAME/nodes
|
7
|
+
class EnvironmentNodesEndpoint < RestBase
|
8
|
+
def get(request)
|
9
|
+
# 404 if environment does not exist
|
10
|
+
get_data(request, request.rest_path[0..3])
|
11
|
+
|
12
|
+
result = {}
|
13
|
+
list_data(request, request.rest_path[0..1] + ["nodes"]).each do |name|
|
14
|
+
node = FFI_Yajl::Parser.parse(get_data(request, request.rest_path[0..1] + ["nodes", name]))
|
15
|
+
if node["chef_environment"] == request.rest_path[3]
|
16
|
+
result[name] = build_uri(request.base_uri, request.rest_path[0..1] + ["nodes", name])
|
17
|
+
end
|
18
|
+
end
|
19
|
+
json_response(200, result)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -1,22 +1,22 @@
|
|
1
|
-
require "ffi_yajl" unless defined?(FFI_Yajl)
|
2
|
-
require_relative "cookbooks_base"
|
3
|
-
|
4
|
-
module ChefZero
|
5
|
-
module Endpoints
|
6
|
-
# /environment/NAME/recipes
|
7
|
-
class EnvironmentRecipesEndpoint < CookbooksBase
|
8
|
-
def get(request)
|
9
|
-
environment = FFI_Yajl::Parser.parse(get_data(request, request.rest_path[0..3]))
|
10
|
-
constraints = environment["cookbook_versions"] || {}
|
11
|
-
result = []
|
12
|
-
filter_cookbooks(all_cookbooks_list(request), constraints, 1) do |name, versions|
|
13
|
-
if versions.size > 0
|
14
|
-
cookbook = FFI_Yajl::Parser.parse(get_data(request, request.rest_path[0..1] + ["cookbooks", name, versions[0]]))
|
15
|
-
result += recipe_names(name, cookbook)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
json_response(200, result.sort)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
1
|
+
require "ffi_yajl" unless defined?(FFI_Yajl)
|
2
|
+
require_relative "cookbooks_base"
|
3
|
+
|
4
|
+
module ChefZero
|
5
|
+
module Endpoints
|
6
|
+
# /environment/NAME/recipes
|
7
|
+
class EnvironmentRecipesEndpoint < CookbooksBase
|
8
|
+
def get(request)
|
9
|
+
environment = FFI_Yajl::Parser.parse(get_data(request, request.rest_path[0..3]))
|
10
|
+
constraints = environment["cookbook_versions"] || {}
|
11
|
+
result = []
|
12
|
+
filter_cookbooks(all_cookbooks_list(request), constraints, 1) do |name, versions|
|
13
|
+
if versions.size > 0
|
14
|
+
cookbook = FFI_Yajl::Parser.parse(get_data(request, request.rest_path[0..1] + ["cookbooks", name, versions[0]]))
|
15
|
+
result += recipe_names(name, cookbook)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
json_response(200, result.sort)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -1,36 +1,36 @@
|
|
1
|
-
require "ffi_yajl" unless defined?(FFI_Yajl)
|
2
|
-
require_relative "cookbooks_base"
|
3
|
-
|
4
|
-
module ChefZero
|
5
|
-
module Endpoints
|
6
|
-
# /environments/NAME/roles/NAME
|
7
|
-
# /roles/NAME/environments/NAME
|
8
|
-
class EnvironmentRoleEndpoint < CookbooksBase
|
9
|
-
def get(request)
|
10
|
-
# 404 if environment does not exist
|
11
|
-
if request.rest_path[2] == "environments"
|
12
|
-
environment_path = request.rest_path[0..1] + request.rest_path[2..3]
|
13
|
-
role_path = request.rest_path[0..1] + request.rest_path[4..5]
|
14
|
-
else
|
15
|
-
environment_path = request.rest_path[0..1] + request.rest_path[4..5]
|
16
|
-
role_path = request.rest_path[0..1] + request.rest_path[2..3]
|
17
|
-
end
|
18
|
-
# Verify that the environment exists
|
19
|
-
get_data(request, environment_path)
|
20
|
-
|
21
|
-
role = FFI_Yajl::Parser.parse(get_data(request, role_path))
|
22
|
-
environment_name = environment_path[3]
|
23
|
-
if environment_name == "_default"
|
24
|
-
run_list = role["run_list"]
|
25
|
-
else
|
26
|
-
if role["env_run_lists"]
|
27
|
-
run_list = role["env_run_lists"][environment_name]
|
28
|
-
else
|
29
|
-
run_list = nil
|
30
|
-
end
|
31
|
-
end
|
32
|
-
json_response(200, { "run_list" => run_list })
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
1
|
+
require "ffi_yajl" unless defined?(FFI_Yajl)
|
2
|
+
require_relative "cookbooks_base"
|
3
|
+
|
4
|
+
module ChefZero
|
5
|
+
module Endpoints
|
6
|
+
# /environments/NAME/roles/NAME
|
7
|
+
# /roles/NAME/environments/NAME
|
8
|
+
class EnvironmentRoleEndpoint < CookbooksBase
|
9
|
+
def get(request)
|
10
|
+
# 404 if environment does not exist
|
11
|
+
if request.rest_path[2] == "environments"
|
12
|
+
environment_path = request.rest_path[0..1] + request.rest_path[2..3]
|
13
|
+
role_path = request.rest_path[0..1] + request.rest_path[4..5]
|
14
|
+
else
|
15
|
+
environment_path = request.rest_path[0..1] + request.rest_path[4..5]
|
16
|
+
role_path = request.rest_path[0..1] + request.rest_path[2..3]
|
17
|
+
end
|
18
|
+
# Verify that the environment exists
|
19
|
+
get_data(request, environment_path)
|
20
|
+
|
21
|
+
role = FFI_Yajl::Parser.parse(get_data(request, role_path))
|
22
|
+
environment_name = environment_path[3]
|
23
|
+
if environment_name == "_default"
|
24
|
+
run_list = role["run_list"]
|
25
|
+
else
|
26
|
+
if role["env_run_lists"]
|
27
|
+
run_list = role["env_run_lists"][environment_name]
|
28
|
+
else
|
29
|
+
run_list = nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
json_response(200, { "run_list" => run_list })
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|