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.
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 +34 -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 +126 -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 +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
- begin
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
- end
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
- begin
115
- delete_data(request, request.rest_path[0..1] + ["file_store", "checksums", checksum], :data_store_exceptions)
116
- rescue ChefZero::DataStore::DataNotFoundError
117
- end
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