chef-zero 15.0.17 → 15.0.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +36 -31
  3. data/LICENSE +201 -201
  4. data/Rakefile +73 -68
  5. data/bin/chef-zero +111 -111
  6. data/chef-zero.gemspec +30 -33
  7. data/lib/chef_zero/chef_data/acl_path.rb +140 -140
  8. data/lib/chef_zero/chef_data/cookbook_data.rb +237 -237
  9. data/lib/chef_zero/chef_data/data_normalizer.rb +276 -276
  10. data/lib/chef_zero/chef_data/default_creator.rb +476 -476
  11. data/lib/chef_zero/data_store/data_already_exists_error.rb +29 -29
  12. data/lib/chef_zero/data_store/data_error.rb +32 -32
  13. data/lib/chef_zero/data_store/data_not_found_error.rb +29 -29
  14. data/lib/chef_zero/data_store/default_facade.rb +143 -147
  15. data/lib/chef_zero/data_store/interface_v1.rb +67 -67
  16. data/lib/chef_zero/data_store/interface_v2.rb +18 -18
  17. data/lib/chef_zero/data_store/memory_store.rb +33 -33
  18. data/lib/chef_zero/data_store/memory_store_v2.rb +159 -159
  19. data/lib/chef_zero/data_store/raw_file_store.rb +143 -143
  20. data/lib/chef_zero/data_store/v1_to_v2_adapter.rb +150 -150
  21. data/lib/chef_zero/data_store/v2_to_v1_adapter.rb +105 -105
  22. data/lib/chef_zero/dist.rb +9 -9
  23. data/lib/chef_zero/endpoints/acl_endpoint.rb +39 -39
  24. data/lib/chef_zero/endpoints/acls_endpoint.rb +41 -41
  25. data/lib/chef_zero/endpoints/actor_default_key_endpoint.rb +78 -78
  26. data/lib/chef_zero/endpoints/actor_endpoint.rb +184 -184
  27. data/lib/chef_zero/endpoints/actor_key_endpoint.rb +62 -62
  28. data/lib/chef_zero/endpoints/actor_keys_endpoint.rb +129 -129
  29. data/lib/chef_zero/endpoints/actors_endpoint.rb +104 -104
  30. data/lib/chef_zero/endpoints/authenticate_user_endpoint.rb +32 -32
  31. data/lib/chef_zero/endpoints/container_endpoint.rb +22 -22
  32. data/lib/chef_zero/endpoints/containers_endpoint.rb +25 -25
  33. data/lib/chef_zero/endpoints/controls_endpoint.rb +16 -16
  34. data/lib/chef_zero/endpoints/cookbook_artifact_endpoint.rb +24 -24
  35. data/lib/chef_zero/endpoints/cookbook_artifact_identifier_endpoint.rb +68 -68
  36. data/lib/chef_zero/endpoints/cookbook_artifacts_endpoint.rb +34 -34
  37. data/lib/chef_zero/endpoints/cookbook_endpoint.rb +39 -39
  38. data/lib/chef_zero/endpoints/cookbook_version_endpoint.rb +136 -136
  39. data/lib/chef_zero/endpoints/cookbooks_base.rb +80 -80
  40. data/lib/chef_zero/endpoints/cookbooks_endpoint.rb +19 -19
  41. data/lib/chef_zero/endpoints/data_bag_endpoint.rb +45 -45
  42. data/lib/chef_zero/endpoints/data_bag_item_endpoint.rb +25 -25
  43. data/lib/chef_zero/endpoints/data_bags_endpoint.rb +23 -23
  44. data/lib/chef_zero/endpoints/dummy_endpoint.rb +29 -29
  45. data/lib/chef_zero/endpoints/environment_cookbook_endpoint.rb +24 -24
  46. data/lib/chef_zero/endpoints/environment_cookbook_versions_endpoint.rb +136 -126
  47. data/lib/chef_zero/endpoints/environment_cookbooks_endpoint.rb +22 -22
  48. data/lib/chef_zero/endpoints/environment_endpoint.rb +33 -33
  49. data/lib/chef_zero/endpoints/environment_nodes_endpoint.rb +23 -23
  50. data/lib/chef_zero/endpoints/environment_recipes_endpoint.rb +22 -22
  51. data/lib/chef_zero/endpoints/environment_role_endpoint.rb +36 -36
  52. data/lib/chef_zero/endpoints/file_store_file_endpoint.rb +22 -22
  53. data/lib/chef_zero/endpoints/group_endpoint.rb +20 -20
  54. data/lib/chef_zero/endpoints/groups_endpoint.rb +13 -13
  55. data/lib/chef_zero/endpoints/license_endpoint.rb +25 -25
  56. data/lib/chef_zero/endpoints/node_endpoint.rb +34 -34
  57. data/lib/chef_zero/endpoints/node_identifiers_endpoint.rb +22 -22
  58. data/lib/chef_zero/endpoints/nodes_endpoint.rb +34 -34
  59. data/lib/chef_zero/endpoints/not_found_endpoint.rb +11 -11
  60. data/lib/chef_zero/endpoints/organization_association_request_endpoint.rb +22 -22
  61. data/lib/chef_zero/endpoints/organization_association_requests_endpoint.rb +30 -30
  62. data/lib/chef_zero/endpoints/organization_authenticate_user_endpoint.rb +26 -26
  63. data/lib/chef_zero/endpoints/organization_endpoint.rb +47 -47
  64. data/lib/chef_zero/endpoints/organization_user_base.rb +15 -15
  65. data/lib/chef_zero/endpoints/organization_user_default_key_endpoint.rb +16 -16
  66. data/lib/chef_zero/endpoints/organization_user_endpoint.rb +26 -26
  67. data/lib/chef_zero/endpoints/organization_user_key_endpoint.rb +17 -17
  68. data/lib/chef_zero/endpoints/organization_user_keys_endpoint.rb +17 -17
  69. data/lib/chef_zero/endpoints/organization_users_endpoint.rb +43 -43
  70. data/lib/chef_zero/endpoints/organization_validator_key_endpoint.rb +20 -20
  71. data/lib/chef_zero/endpoints/organizations_endpoint.rb +61 -61
  72. data/lib/chef_zero/endpoints/policies_endpoint.rb +26 -26
  73. data/lib/chef_zero/endpoints/policy_endpoint.rb +24 -24
  74. data/lib/chef_zero/endpoints/policy_group_endpoint.rb +46 -46
  75. data/lib/chef_zero/endpoints/policy_group_policy_endpoint.rb +83 -83
  76. data/lib/chef_zero/endpoints/policy_groups_endpoint.rb +38 -38
  77. data/lib/chef_zero/endpoints/policy_revision_endpoint.rb +66 -66
  78. data/lib/chef_zero/endpoints/policy_revisions_endpoint.rb +15 -15
  79. data/lib/chef_zero/endpoints/principal_endpoint.rb +55 -55
  80. data/lib/chef_zero/endpoints/rest_list_endpoint.rb +42 -42
  81. data/lib/chef_zero/endpoints/rest_object_endpoint.rb +78 -78
  82. data/lib/chef_zero/endpoints/role_endpoint.rb +16 -16
  83. data/lib/chef_zero/endpoints/role_environments_endpoint.rb +14 -14
  84. data/lib/chef_zero/endpoints/sandbox_endpoint.rb +27 -27
  85. data/lib/chef_zero/endpoints/sandboxes_endpoint.rb +51 -51
  86. data/lib/chef_zero/endpoints/search_endpoint.rb +208 -208
  87. data/lib/chef_zero/endpoints/searches_endpoint.rb +18 -18
  88. data/lib/chef_zero/endpoints/server_api_version_endpoint.rb +14 -14
  89. data/lib/chef_zero/endpoints/system_recovery_endpoint.rb +30 -30
  90. data/lib/chef_zero/endpoints/universe_endpoint.rb +15 -15
  91. data/lib/chef_zero/endpoints/user_association_request_endpoint.rb +41 -41
  92. data/lib/chef_zero/endpoints/user_association_requests_count_endpoint.rb +19 -19
  93. data/lib/chef_zero/endpoints/user_association_requests_endpoint.rb +19 -19
  94. data/lib/chef_zero/endpoints/user_organizations_endpoint.rb +22 -22
  95. data/lib/chef_zero/endpoints/version_endpoint.rb +13 -13
  96. data/lib/chef_zero/log.rb +7 -7
  97. data/lib/chef_zero/rest_base.rb +332 -332
  98. data/lib/chef_zero/rest_error_response.rb +11 -11
  99. data/lib/chef_zero/rest_request.rb +84 -88
  100. data/lib/chef_zero/rest_router.rb +72 -72
  101. data/lib/chef_zero/rspec.rb +355 -355
  102. data/lib/chef_zero/server.rb +730 -730
  103. data/lib/chef_zero/socketless_server_map.rb +92 -93
  104. data/lib/chef_zero/solr/query/binary_operator.rb +52 -52
  105. data/lib/chef_zero/solr/query/phrase.rb +23 -23
  106. data/lib/chef_zero/solr/query/range_query.rb +46 -46
  107. data/lib/chef_zero/solr/query/regexpable_query.rb +30 -30
  108. data/lib/chef_zero/solr/query/subquery.rb +37 -37
  109. data/lib/chef_zero/solr/query/term.rb +45 -45
  110. data/lib/chef_zero/solr/query/unary_operator.rb +41 -41
  111. data/lib/chef_zero/solr/solr_doc.rb +53 -53
  112. data/lib/chef_zero/solr/solr_parser.rb +208 -208
  113. data/lib/chef_zero/version.rb +3 -3
  114. data/lib/chef_zero.rb +10 -10
  115. data/spec/run_oc_pedant.rb +226 -226
  116. data/spec/search_spec.rb +36 -36
  117. data/spec/server_spec.rb +96 -96
  118. data/spec/socketless_server_map_spec.rb +74 -74
  119. data/spec/support/oc_pedant.rb +149 -149
  120. data/spec/support/secrets.json +6 -6
  121. data/spec/support/stickywicket.pem +27 -27
  122. metadata +29 -32
@@ -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,136 @@
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, cookbook_obj_cache = 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
+ if cookbook_obj_cache.dig(name, versions[0])
54
+ cookbook = cookbook_obj_cache[name][versions[0]]
55
+ else
56
+ cookbook = FFI_Yajl::Parser.parse(get_data(request, request.rest_path[0..1] + ["cookbooks", name, versions[0]]))
57
+ end
58
+ 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)
59
+ end
60
+ json_response(200, result)
61
+ end
62
+
63
+ def depsolve(request, unsolved, desired_versions, environment_constraints, cookbook_obj_cache = nil)
64
+ desired_versions.each do |cb, ver|
65
+ if ver.empty?
66
+ @last_constraint_failure = cb
67
+ return [nil, nil]
68
+ end
69
+ end
70
+
71
+ # If everything is already
72
+ solve_for = unsolved[0]
73
+ return [desired_versions, cookbook_obj_cache] unless solve_for
74
+
75
+ # Cache the get_data calls - this saves the need to run the get_data call a second time in #post
76
+ # Conceptually: cache[cookbook][version] = cookbook_object
77
+ cookbook_obj_cache ||= {}
78
+
79
+ # Go through each desired version of this cookbook, starting with the latest,
80
+ # until we find one we can solve successfully with
81
+ sort_versions(desired_versions[solve_for]).each do |desired_version|
82
+ new_desired_versions = desired_versions.clone
83
+ new_desired_versions[solve_for] = [ desired_version ]
84
+ new_unsolved = unsolved[1..-1]
85
+
86
+ # Pick this cookbook, and add dependencies
87
+ cookbook_obj = FFI_Yajl::Parser.parse(get_data(request, request.rest_path[0..1] + ["cookbooks", solve_for, desired_version]))
88
+ cookbook_obj_cache[solve_for] ||= {}
89
+ cookbook_obj_cache[solve_for][desired_version] = cookbook_obj
90
+ cookbook_metadata = cookbook_obj["metadata"] || {}
91
+ cookbook_dependencies = cookbook_metadata["dependencies"] || {}
92
+ dep_not_found = false
93
+ cookbook_dependencies.each_pair do |dep_name, dep_constraint|
94
+ # If the dep is not already in the list, add it to the list to solve
95
+ # and bring in all environment-allowed cookbook versions to desired_versions
96
+ unless new_desired_versions.key?(dep_name)
97
+ new_unsolved += [dep_name]
98
+ # If the dep is missing, we will try other versions of the cookbook that might not have the bad dep.
99
+ unless exists_data_dir?(request, request.rest_path[0..1] + ["cookbooks", dep_name])
100
+ @last_missing_dep = dep_name.to_s
101
+ dep_not_found = true
102
+ break
103
+ end
104
+ new_desired_versions[dep_name] = list_data(request, request.rest_path[0..1] + ["cookbooks", dep_name])
105
+ new_desired_versions = filter_by_constraint(new_desired_versions, dep_name, environment_constraints[dep_name])
106
+ end
107
+ new_desired_versions = filter_by_constraint(new_desired_versions, dep_name, dep_constraint)
108
+ end
109
+
110
+ next if dep_not_found
111
+
112
+ # Depsolve children with this desired version! First solution wins.
113
+ result, cookbook_obj_cache = depsolve(request, new_unsolved, new_desired_versions, environment_constraints, cookbook_obj_cache)
114
+ return [result, cookbook_obj_cache] if result
115
+ end
116
+ [nil, nil]
117
+ end
118
+
119
+ def sort_versions(versions)
120
+ result = versions.sort_by { |version| Gem::Version.new(version.dup) }
121
+ result.reverse
122
+ end
123
+
124
+ def filter_by_constraint(versions, cookbook_name, constraint)
125
+ return versions unless constraint
126
+
127
+ constraint = Gem::Requirement.new(constraint)
128
+ new_versions = versions[cookbook_name]
129
+ new_versions = new_versions.select { |version| constraint.satisfied_by?(Gem::Version.new(version.dup)) }
130
+ result = versions.clone
131
+ result[cookbook_name] = new_versions
132
+ result
133
+ end
134
+ end
135
+ end
136
+ 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