summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/chef_zero/chef_data/data_normalizer.rb27
-rw-r--r--lib/chef_zero/endpoints/cookbook_artifacts_cookbook_endpoint.rb24
-rw-r--r--lib/chef_zero/endpoints/cookbook_artifacts_cookbook_identifier.rb67
-rw-r--r--lib/chef_zero/endpoints/cookbook_artifacts_endpoint.rb34
-rw-r--r--lib/chef_zero/endpoints/cookbook_version_endpoint.rb8
-rw-r--r--lib/chef_zero/server.rb6
-rw-r--r--spec/run_oc_pedant.rb6
7 files changed, 155 insertions, 17 deletions
diff --git a/lib/chef_zero/chef_data/data_normalizer.rb b/lib/chef_zero/chef_data/data_normalizer.rb
index 87e7c8a..9a6d1ae 100644
--- a/lib/chef_zero/chef_data/data_normalizer.rb
+++ b/lib/chef_zero/chef_data/data_normalizer.rb
@@ -79,7 +79,8 @@ module ChefZero
data_bag_item
end
- def self.normalize_cookbook(endpoint, org_prefix, cookbook, name, version, base_uri, method)
+ def self.normalize_cookbook(endpoint, org_prefix, cookbook, name, version, base_uri, method,
+ is_cookbook_artifact=false)
# TODO I feel dirty
if method != 'PUT'
cookbook.each_pair do |key, value|
@@ -92,24 +93,28 @@ module ChefZero
end
end
cookbook['name'] ||= "#{name}-#{version}"
- # TODO this feels wrong, but the real chef server doesn't expand this default
- # cookbook['version'] ||= version
- cookbook['cookbook_name'] ||= name
+ # TODO it feels wrong, but the real chef server doesn't expand 'version', so we don't either.
+
cookbook['frozen?'] ||= false
cookbook['metadata'] ||= {}
cookbook['metadata']['version'] ||= version
- # Sad to not be expanding defaults just because Chef doesn't :(
- # cookbook['metadata']['name'] ||= name
- # cookbook['metadata']['description'] ||= "A fabulous new cookbook"
+
+ # defaults set by the client and not the Server:
+ # metadata[name, description, maintainer, maintainer_email, license]
+
cookbook['metadata']['long_description'] ||= ""
- # cookbook['metadata']['maintainer'] ||= "YOUR_COMPANY_NAME"
- # cookbook['metadata']['maintainer_email'] ||= "YOUR_EMAIL"
- # cookbook['metadata']['license'] ||= "none"
cookbook['metadata']['dependencies'] ||= {}
cookbook['metadata']['attributes'] ||= {}
cookbook['metadata']['recipes'] ||= {}
end
- cookbook['json_class'] ||= 'Chef::CookbookVersion'
+
+ if is_cookbook_artifact
+ cookbook.delete('json_class')
+ else
+ cookbook['cookbook_name'] ||= name
+ cookbook['json_class'] ||= 'Chef::CookbookVersion'
+ end
+
cookbook['chef_type'] ||= 'cookbook_version'
if method == 'MIN'
cookbook['metadata'].delete('attributes')
diff --git a/lib/chef_zero/endpoints/cookbook_artifacts_cookbook_endpoint.rb b/lib/chef_zero/endpoints/cookbook_artifacts_cookbook_endpoint.rb
new file mode 100644
index 0000000..841f0c9
--- /dev/null
+++ b/lib/chef_zero/endpoints/cookbook_artifacts_cookbook_endpoint.rb
@@ -0,0 +1,24 @@
+require 'chef_zero/chef_data/data_normalizer'
+
+module ChefZero
+ module Endpoints
+ class CookbookArtifactsCookbookEndpoint < RestBase
+ # GET /organizations/ORG/cookbook_artifacts/COOKBOOK
+ def get(request)
+ cookbook_name = request.rest_path.last
+ cookbook_url = build_uri(request.base_uri, request.rest_path)
+ response_data = {}
+ versions = []
+
+ list_data(request).each do |identifier|
+ artifact_url = build_uri(request.base_uri, request.rest_path + [cookbook_name, identifier])
+ versions << { url: artifact_url, identifier: identifier }
+ end
+
+ response_data[cookbook_name] = { url: cookbook_url, versions: versions }
+
+ return json_response(200, response_data)
+ end
+ end
+ end
+end
diff --git a/lib/chef_zero/endpoints/cookbook_artifacts_cookbook_identifier.rb b/lib/chef_zero/endpoints/cookbook_artifacts_cookbook_identifier.rb
new file mode 100644
index 0000000..4d22d08
--- /dev/null
+++ b/lib/chef_zero/endpoints/cookbook_artifacts_cookbook_identifier.rb
@@ -0,0 +1,67 @@
+require 'chef_zero/chef_data/data_normalizer'
+
+module ChefZero
+ module Endpoints
+ class CookbookArtifactsCookbookIdentifierEndpoint < ChefZero::Endpoints::CookbookVersionEndpoint
+ # these endpoints are almost, but not quite, not entirely unlike the corresponding /cookbooks endpoints.
+ # it could all be refactored for maximum reuse, but they're short REST methods with well-defined
+ # behavioral specs (pedant), so there's not a huge benefit.
+
+ # GET /organizations/ORG/cookbook_artifacts/NAME/IDENTIFIER
+ def get(request)
+ cookbook_data = normalize(request, parse_json(get_data(request)))
+ return json_response(200, cookbook_data)
+ end
+
+ # PUT /organizations/ORG/cookbook_artifacts/COOKBOOK/IDENTIFIER
+ def put(request)
+ if exists_data?(request)
+ return error(409, "Cookbooks cannot be modified, and a cookbook with this identifier already exists.")
+ end
+
+ set_data(request, nil, request.body, :create_dir)
+
+ return already_json_response(201, request.body)
+ end
+
+ # DELETE /organizations/ORG/cookbook_artifacts/COOKBOOK/IDENTIFIER
+ def delete(request)
+ begin
+ doomed_cookbook_json = get_data(request)
+ identified_cookbook_data = normalize(request, parse_json(doomed_cookbook_json))
+ delete_data(request)
+
+ # go through the recipes and delete stuff in the file store.
+ hoover_unused_checksums(get_checksums(doomed_cookbook_json), request, 'cookbook_artifacts')
+
+ # if this was the last revision, delete the directory so future requests will 404, instead of
+ # returning 200 with an empty list.
+ artifact_path = request.rest_path[0..-2]
+ if list_data(request, artifact_path).size == 0
+ delete_data_dir(request, artifact_path)
+ end
+
+ json_response(200, identified_cookbook_data)
+ rescue RestErrorResponse => ex
+ if ex.response_code == 404
+ error(404, "not_found")
+ else
+ raise
+ end
+ end
+ end
+
+ private
+
+ def make_file_store_path(rest_path, recipe)
+ rest_path.first(2) + ["file_store", "checksums", recipe["checksum"]]
+ end
+
+ def normalize(request, cookbook_artifact_data)
+ ChefData::DataNormalizer.normalize_cookbook(self, request.rest_path[0..1],
+ cookbook_artifact_data, request.rest_path[3], request.rest_path[4],
+ request.base_uri, request.method, true)
+ end
+ end
+ end
+end
diff --git a/lib/chef_zero/endpoints/cookbook_artifacts_endpoint.rb b/lib/chef_zero/endpoints/cookbook_artifacts_endpoint.rb
new file mode 100644
index 0000000..d9fdb20
--- /dev/null
+++ b/lib/chef_zero/endpoints/cookbook_artifacts_endpoint.rb
@@ -0,0 +1,34 @@
+require 'chef_zero/chef_data/data_normalizer'
+
+module ChefZero
+ module Endpoints
+ class CookbookArtifactsEndpoint < RestBase
+ # GET /organizations/ORG/cookbook_artifacts
+ def get(request)
+ data = {}
+
+ artifacts = begin
+ list_data(request)
+ rescue Exception => e
+ if e.response_code == 404
+ return already_json_response(200, "{}")
+ end
+ end
+
+ artifacts.each do |cookbook_artifact|
+ cookbook_url = build_uri(request.base_uri, request.rest_path + [cookbook_artifact])
+
+ versions = []
+ list_data(request, request.rest_path + [cookbook_artifact]).each do |identifier|
+ artifact_url = build_uri(request.base_uri, request.rest_path + [cookbook_artifact, identifier])
+ versions << { url: artifact_url, identifier: identifier }
+ end
+
+ data[cookbook_artifact] = { url: cookbook_url, versions: versions }
+ end
+
+ return json_response(200, data)
+ end
+ end
+ end
+end
diff --git a/lib/chef_zero/endpoints/cookbook_version_endpoint.rb b/lib/chef_zero/endpoints/cookbook_version_endpoint.rb
index 8dad508..e78d44c 100644
--- a/lib/chef_zero/endpoints/cookbook_version_endpoint.rb
+++ b/lib/chef_zero/endpoints/cookbook_version_endpoint.rb
@@ -85,10 +85,10 @@ module ChefZero
private
- def hoover_unused_checksums(deleted_checksums, request)
- data_store.list(request.rest_path[0..1] + ['cookbooks']).each do |cookbook_name|
- data_store.list(request.rest_path[0..1] + ['cookbooks', cookbook_name]).each do |version|
- cookbook = data_store.get(request.rest_path[0..1] + ['cookbooks', cookbook_name, version], request)
+ def hoover_unused_checksums(deleted_checksums, request, data_type='cookbooks')
+ data_store.list(request.rest_path[0..1] + [data_type]).each do |cookbook_name|
+ data_store.list(request.rest_path[0..1] + [data_type, cookbook_name]).each do |version|
+ cookbook = data_store.get(request.rest_path[0..1] + [data_type, cookbook_name, version], request)
deleted_checksums = deleted_checksums - get_checksums(cookbook)
end
end
diff --git a/lib/chef_zero/server.rb b/lib/chef_zero/server.rb
index 2d84a52..c96150e 100644
--- a/lib/chef_zero/server.rb
+++ b/lib/chef_zero/server.rb
@@ -45,6 +45,9 @@ require 'chef_zero/endpoints/actor_endpoint'
require 'chef_zero/endpoints/cookbooks_endpoint'
require 'chef_zero/endpoints/cookbook_endpoint'
require 'chef_zero/endpoints/cookbook_version_endpoint'
+require 'chef_zero/endpoints/cookbook_artifacts_cookbook_endpoint'
+require 'chef_zero/endpoints/cookbook_artifacts_cookbook_identifier'
+require 'chef_zero/endpoints/cookbook_artifacts_endpoint'
require 'chef_zero/endpoints/containers_endpoint'
require 'chef_zero/endpoints/container_endpoint'
require 'chef_zero/endpoints/dummy_endpoint'
@@ -558,6 +561,9 @@ module ChefZero
[ "/organizations/*/cookbooks", CookbooksEndpoint.new(self) ],
[ "/organizations/*/cookbooks/*", CookbookEndpoint.new(self) ],
[ "/organizations/*/cookbooks/*/*", CookbookVersionEndpoint.new(self) ],
+ [ "/organizations/*/cookbook_artifacts", CookbookArtifactsEndpoint.new(self) ],
+ [ "/organizations/*/cookbook_artifacts/*", CookbookArtifactsCookbookEndpoint.new(self) ],
+ [ "/organizations/*/cookbook_artifacts/*/*", CookbookArtifactsCookbookIdentifierEndpoint.new(self) ],
[ "/organizations/*/data", DataBagsEndpoint.new(self) ],
[ "/organizations/*/data/*", DataBagEndpoint.new(self) ],
[ "/organizations/*/data/*/*", DataBagItemEndpoint.new(self) ],
diff --git a/spec/run_oc_pedant.rb b/spec/run_oc_pedant.rb
index 726279f..3cf873c 100644
--- a/spec/run_oc_pedant.rb
+++ b/spec/run_oc_pedant.rb
@@ -83,7 +83,10 @@ begin
'--skip-users',
'--skip-organizations',
'--skip-multiuser',
- '--skip-policies' # these are expected to be broken, they're what we're trying to fix.
+
+ # will be supported.
+ '--skip-policies',
+ '--skip-cookbook-artifacts',
]
else
[]
@@ -104,7 +107,6 @@ begin
'--skip-headers',
# Chef 12 features not yet 100% supported by Chef Zero
- '--skip-cookbook-artifacts',
'--skip-containers',
'--skip-api-v1'
] + chef_fs_skips)