diff options
author | John Keiser <john@johnkeiser.com> | 2015-02-11 15:47:43 -0800 |
---|---|---|
committer | John Keiser <john@johnkeiser.com> | 2015-02-11 15:47:43 -0800 |
commit | 76b0106cfcdb990c7d0881d1324d0e2cf61029e1 (patch) | |
tree | 9057eff89d7576e4e5a78774ca1bf72756912243 | |
parent | 8788aa9da7f3c420bcab8d001208d4cb2cfc4883 (diff) | |
parent | fb454e1b87462f951bea3ec666351293072d160a (diff) | |
download | chef-zero-76b0106cfcdb990c7d0881d1324d0e2cf61029e1.tar.gz |
Merge policyfile endpoints
-rw-r--r-- | .travis.yml | 30 | ||||
-rw-r--r-- | Gemfile | 6 | ||||
-rw-r--r-- | Rakefile | 3 | ||||
-rw-r--r-- | lib/chef_zero/data_store/memory_store_v2.rb | 2 | ||||
-rw-r--r-- | lib/chef_zero/data_store/v1_to_v2_adapter.rb | 8 | ||||
-rw-r--r-- | lib/chef_zero/endpoints/policies_endpoint.rb | 126 | ||||
-rw-r--r-- | lib/chef_zero/server.rb | 3 | ||||
-rw-r--r-- | spec/run_oc_pedant.rb | 3 | ||||
-rw-r--r-- | spec/run_pedant.rb | 2 | ||||
-rw-r--r-- | spec/support/pedant.rb | 4 |
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 @@ -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' + @@ -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 |