summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Keiser <john@johnkeiser.com>2015-02-11 15:47:43 -0800
committerJohn Keiser <john@johnkeiser.com>2015-02-11 15:47:43 -0800
commit76b0106cfcdb990c7d0881d1324d0e2cf61029e1 (patch)
tree9057eff89d7576e4e5a78774ca1bf72756912243
parent8788aa9da7f3c420bcab8d001208d4cb2cfc4883 (diff)
parentfb454e1b87462f951bea3ec666351293072d160a (diff)
downloadchef-zero-76b0106cfcdb990c7d0881d1324d0e2cf61029e1.tar.gz
Merge policyfile endpoints
-rw-r--r--.travis.yml30
-rw-r--r--Gemfile6
-rw-r--r--Rakefile3
-rw-r--r--lib/chef_zero/data_store/memory_store_v2.rb2
-rw-r--r--lib/chef_zero/data_store/v1_to_v2_adapter.rb8
-rw-r--r--lib/chef_zero/endpoints/policies_endpoint.rb126
-rw-r--r--lib/chef_zero/server.rb3
-rw-r--r--spec/run_oc_pedant.rb3
-rw-r--r--spec/run_pedant.rb2
-rw-r--r--spec/support/pedant.rb4
10 files changed, 161 insertions, 26 deletions
diff --git a/.travis.yml b/.travis.yml
index 985730f..c0b640e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,38 +1,28 @@
-rvm: 1.9.3
-
+rvm: 2.0
gemfile: Gemfile
+sudo: false
script: bundle exec rake pedant
matrix:
include:
- - rvm: 1.8.7
- - rvm: 1.8.7
- env: SKIP_PEDANT=true
- gemfile: gemfiles/no-pedant.gemfile
- - rvm: jruby-19mode
- - rvm: jruby-19mode
- env: SKIP_PEDANT=true
- gemfile: gemfiles/no-pedant.gemfile
- - rvm: 2.0.0
- - rvm: 2.1.1
- - rvm: 2.1.1
+ - rvm: 2.0
+ - rvm: 2.1
+ - rvm: 2.1
env: SINGLE_ORG=true
- - rvm: 2.1.1
+ - rvm: 2.1
env: CHEF_FS=true
- - rvm: 2.1.1
+ - rvm: 2.1
env: FILE_STORE=true
- - rvm: 2.1.1
+ - rvm: 2.1
script: bundle exec rake chef_spec
env: TEST=chef_spec
- - rvm: 2.1.1
+ - rvm: 2.1
script: bundle exec rake spec
env: TEST=rake_spec
allow_failures:
- - rvm: 1.8.7
- - rvm: jruby-19mode
- - rvm: 2.1.1
+ - rvm: 2.1
gemfile: gemfiles/latest-chef.gemfile
script: bundle exec rake chef_spec
enc: TEST=chef_spec_latest
diff --git a/Gemfile b/Gemfile
index 3845ad6..0041f61 100644
--- a/Gemfile
+++ b/Gemfile
@@ -2,5 +2,7 @@ source 'https://rubygems.org'
gemspec
gem 'rest-client', :github => 'opscode/rest-client'
-gem 'chef-pedant', :github => 'opscode/chef-pedant', :ref => '81f3b4ecbc09d04950f2819b38a6a8f906ada2a7'
-gem 'chef', :github => 'opscode/chef', :ref => 'a2dee150e68a611249577a8adcb2c3e329d6762d'
+gem 'chef-pedant', :github => 'opscode/chef-pedant', :tag => '1.0.41'
+
+gem 'chef', :github => 'opscode/chef', :ref => '92eefc79bb28d217b15099655244228b9e1efec7'
+
diff --git a/Rakefile b/Rakefile
index 3a3eb96..209b5df 100644
--- a/Rakefile
+++ b/Rakefile
@@ -5,14 +5,17 @@ require 'chef_zero/version'
task :default => :pedant
+desc "run specs"
task :spec do
system('rspec spec/*_spec.rb')
end
+desc "run pedant"
task :pedant do
require File.expand_path('spec/run_pedant')
end
+desc "run oc pedant"
task :oc_pedant do
require File.expand_path('spec/run_oc_pedant')
end
diff --git a/lib/chef_zero/data_store/memory_store_v2.rb b/lib/chef_zero/data_store/memory_store_v2.rb
index 9f8b80e..d330972 100644
--- a/lib/chef_zero/data_store/memory_store_v2.rb
+++ b/lib/chef_zero/data_store/memory_store_v2.rb
@@ -47,7 +47,7 @@ module ChefZero
def create(path, name, data, *options)
if !data.is_a?(String)
- raise "set only works with strings"
+ raise "set only works with strings (given data: #{data.inspect})"
end
parent = _get(path, options.include?(:create_dir))
diff --git a/lib/chef_zero/data_store/v1_to_v2_adapter.rb b/lib/chef_zero/data_store/v1_to_v2_adapter.rb
index 576f27d..d9ea6e1 100644
--- a/lib/chef_zero/data_store/v1_to_v2_adapter.rb
+++ b/lib/chef_zero/data_store/v1_to_v2_adapter.rb
@@ -112,9 +112,13 @@ module ChefZero
begin
yield
rescue DataAlreadyExistsError => e
- raise DataAlreadyExistsError.new([ 'organizations', single_org ] + e.path, e)
+ err = DataAlreadyExistsError.new([ 'organizations', single_org ] + e.path, e)
+ err.set_backtrace(e.backtrace)
+ raise err
rescue DataNotFoundError => e
- raise DataNotFoundError.new([ 'organizations', single_org ] + e.path, e)
+ err = DataNotFoundError.new([ 'organizations', single_org ] + e.path, e)
+ err.set_backtrace(e.backtrace)
+ raise e
end
end
diff --git a/lib/chef_zero/endpoints/policies_endpoint.rb b/lib/chef_zero/endpoints/policies_endpoint.rb
new file mode 100644
index 0000000..992d5ae
--- /dev/null
+++ b/lib/chef_zero/endpoints/policies_endpoint.rb
@@ -0,0 +1,126 @@
+require 'ffi_yajl'
+require 'chef_zero/endpoints/rest_object_endpoint'
+require 'chef_zero/chef_data/data_normalizer'
+
+module ChefZero
+ module Endpoints
+ # /policies/:group/:name
+ class PoliciesEndpoint < RestObjectEndpoint
+ def initialize(server)
+ super(server, 'id')
+ end
+
+ def get(request)
+ already_json_response(200, get_data(request))
+ end
+
+ # Right now we're allowing PUT to create.
+ def put(request)
+ error = validate(request)
+ return error if error
+
+ code =
+ if data_store.exists?(request.rest_path)
+ set_data(request, request.rest_path, request.body, :data_store_exceptions)
+ 200
+ else
+ name = request.rest_path[4]
+ data_store.create(request.rest_path[0..3], name, request.body, :create_dir)
+ 201
+ end
+ already_json_response(code, request.body)
+ end
+
+ def delete(request)
+ result = get_data(request, request.rest_path)
+ delete_data(request, request.rest_path, :data_store_exceptions)
+ already_json_response(200, result)
+ end
+
+ private
+
+ def validate(request)
+ req_object = validate_json(request.body)
+ validate_name(request, req_object) ||
+ validate_run_list(req_object) ||
+ validate_each_run_list_item(req_object) ||
+ validate_cookbook_locks_collection(req_object) ||
+ validate_each_cookbook_locks_item(req_object)
+ end
+
+ def validate_json(request_body)
+ FFI_Yajl::Parser.parse(request_body)
+ # TODO: rescue parse error, return 400
+ # error(400, "Must specify #{identity_keys.map { |k| k.inspect }.join(' or ')} in JSON")
+ end
+
+ def validate_name(request, req_object)
+ if !req_object.key?("name")
+ error(400, "Must specify 'name' in JSON")
+ elsif req_object["name"] != URI.decode(request.rest_path[4])
+ error(400, "'name' field in JSON must match the policy name in the URL")
+ elsif req_object["name"].size > 255
+ error(400, "'name' field in JSON must be 255 characters or fewer")
+ elsif req_object["name"] !~ /^[\-[:alnum:]_\.\:]+$/
+ error(400, "'name' field in JSON must be contain only alphanumeric, hypen, underscore, and dot characters")
+ end
+ end
+
+ def validate_run_list(req_object)
+ if !req_object.key?("run_list")
+ error(400, "Must specify 'run_list' in JSON")
+ elsif !req_object["run_list"].kind_of?(Array)
+ error(400, "'run_list' must be an Array of run list items")
+ end
+ end
+
+ def validate_each_run_list_item(req_object)
+ req_object["run_list"].each do |run_list_item|
+ if res_400 = validate_run_list_item(run_list_item)
+ return res_400
+ end
+ end
+ nil
+ end
+
+ def validate_run_list_item(run_list_item)
+ if !run_list_item.kind_of?(String)
+ error(400, "Items in run_list must be strings in fully qualified recipe format, like recipe[cookbook::recipe]")
+ elsif run_list_item !~ /\Arecipe\[[^\s]+::[^\s]+\]\Z/
+ error(400, "Items in run_list must be strings in fully qualified recipe format, like recipe[cookbook::recipe]")
+ end
+ end
+
+ def validate_cookbook_locks_collection(req_object)
+ if !req_object.key?("cookbook_locks")
+ error(400, "Must specify 'cookbook_locks' in JSON")
+ elsif !req_object["cookbook_locks"].kind_of?(Hash)
+ error(400, "'cookbook_locks' must be a JSON object of cookbook_name: lock_data pairs")
+ end
+ end
+
+ def validate_each_cookbook_locks_item(req_object)
+ req_object["cookbook_locks"].each do |cookbook_name, lock|
+ if res_400 = validate_cookbook_locks_item(cookbook_name, lock)
+ return res_400
+ end
+ end
+ nil
+ end
+
+ def validate_cookbook_locks_item(cookbook_name, lock)
+ if !lock.kind_of?(Hash)
+ error(400, "cookbook_lock entries must be a JSON object")
+ elsif !lock.key?("identifier")
+ error(400, "cookbook_lock entries must contain an 'identifier' field")
+ elsif !lock.key?("dotted_decimal_identifier")
+ error(400, "cookbook_lock entries must contain an 'dotted_decimal_identifier' field")
+ elsif lock["identifier"].size > 255
+ error(400, "cookbook_lock entries 'identifier' field must be 255 or fewer characters")
+ end
+ end
+
+ end
+ end
+end
+
diff --git a/lib/chef_zero/server.rb b/lib/chef_zero/server.rb
index fb2b127..de2a3f5 100644
--- a/lib/chef_zero/server.rb
+++ b/lib/chef_zero/server.rb
@@ -69,6 +69,7 @@ require 'chef_zero/endpoints/organization_users_endpoint'
require 'chef_zero/endpoints/organization_user_endpoint'
require 'chef_zero/endpoints/organization_validator_key_endpoint'
require 'chef_zero/endpoints/principal_endpoint'
+require 'chef_zero/endpoints/policies_endpoint'
require 'chef_zero/endpoints/role_endpoint'
require 'chef_zero/endpoints/role_environments_endpoint'
require 'chef_zero/endpoints/sandboxes_endpoint'
@@ -358,7 +359,6 @@ module ChefZero
# }
# }
def load_data(contents, org_name = nil)
- passed_org = !!org_name
org_name ||= options[:single_org]
if org_name.nil? && contents.keys != [ 'users' ]
raise "Must pass an org name to load_data or run in single_org mode"
@@ -516,6 +516,7 @@ module ChefZero
[ "/organizations/*/environments/*/roles/*", EnvironmentRoleEndpoint.new(self) ],
[ "/organizations/*/nodes", RestListEndpoint.new(self) ],
[ "/organizations/*/nodes/*", NodeEndpoint.new(self) ],
+ [ "/organizations/*/policies/*/*", PoliciesEndpoint.new(self) ],
[ "/organizations/*/principals/*", PrincipalEndpoint.new(self) ],
[ "/organizations/*/roles", RestListEndpoint.new(self) ],
[ "/organizations/*/roles/*", RoleEndpoint.new(self) ],
diff --git a/spec/run_oc_pedant.rb b/spec/run_oc_pedant.rb
index 562bf6a..79d92e7 100644
--- a/spec/run_oc_pedant.rb
+++ b/spec/run_oc_pedant.rb
@@ -34,6 +34,9 @@ begin
Pedant.config[:config_file] = 'spec/support/oc_pedant.rb'
Pedant.setup([
'--skip-knife',
+ '--skip-keys',
+ '--skip-controls',
+ '--skip-acl',
'--skip-validation',
'--skip-authentication',
'--skip-authorization',
diff --git a/spec/run_pedant.rb b/spec/run_pedant.rb
index 3657da8..2caf1ff 100644
--- a/spec/run_pedant.rb
+++ b/spec/run_pedant.rb
@@ -72,11 +72,13 @@ begin
Pedant.config.suite = 'api'
Pedant.config[:config_file] = 'spec/support/pedant.rb'
+
Pedant.setup([
'--skip-knife',
'--skip-validation',
'--skip-authentication',
'--skip-authorization',
+ '--skip-keys',
'--skip-omnibus'
])
diff --git a/spec/support/pedant.rb b/spec/support/pedant.rb
index d6100d2..29a0ec1 100644
--- a/spec/support/pedant.rb
+++ b/spec/support/pedant.rb
@@ -75,6 +75,10 @@ superuser_name 'admin'
superuser_key key
webui_key key
+# The Policies endpoint is feature-flagged during development. Zero supports
+# the policies endpoint, so turn it on:
+policies? true
+
# Set the platform_class
platform_class Pedant::OpenSourcePlatform