diff options
author | Thom May <thom@chef.io> | 2016-03-02 16:39:00 +0000 |
---|---|---|
committer | Thom May <thom@chef.io> | 2016-03-02 16:39:00 +0000 |
commit | f68bf3c899ea68f6fbc4ab95bb6c6117e9aec147 (patch) | |
tree | 52089ee0debd68a04620b32075ca378687e4e13c | |
parent | be1438e82d3fc6dfd85eaf24402283dec765de32 (diff) | |
download | chef-tm/ruby_zero_roles.tar.gz |
read roles from ruby filestm/ruby_zero_roles
10 files changed, 274 insertions, 5 deletions
diff --git a/lib/chef/chef_fs/data_handler/data_handler_base.rb b/lib/chef/chef_fs/data_handler/data_handler_base.rb index 83f56ed16d..863efa6bd0 100644 --- a/lib/chef/chef_fs/data_handler/data_handler_base.rb +++ b/lib/chef/chef_fs/data_handler/data_handler_base.rb @@ -190,7 +190,7 @@ class Chef # Calls the on_error block with the error, if there is one. # def verify_integrity(object, entry, &on_error) - base_name = remove_dot_json(entry.name) + base_name = File.basename(entry.name, ".*") if object["name"] != base_name on_error.call("Name must be '#{base_name}' (is '#{object['name']}')") end diff --git a/lib/chef/chef_fs/data_handler/role_data_handler.rb b/lib/chef/chef_fs/data_handler/role_data_handler.rb index 74533cff05..56de519a3e 100644 --- a/lib/chef/chef_fs/data_handler/role_data_handler.rb +++ b/lib/chef/chef_fs/data_handler/role_data_handler.rb @@ -7,7 +7,7 @@ class Chef class RoleDataHandler < DataHandlerBase def normalize(role, entry) result = normalize_hash(role, { - "name" => remove_dot_json(entry.name), + "name" => File.basename(entry.name, ".*"), "description" => "", "json_class" => "Chef::Role", "chef_type" => "role", @@ -31,6 +31,12 @@ class Chef Chef::Role end + def from_ruby(path) + r = Chef::Role.new + r.from_file(path) + r.to_hash + end + def to_ruby(object) to_ruby_keys(object, %w{name description default_attributes override_attributes run_list env_run_lists}) end diff --git a/lib/chef/chef_fs/file_system/chef_server/chef_server_root_dir.rb b/lib/chef/chef_fs/file_system/chef_server/chef_server_root_dir.rb index 6c99d6de73..b5a651ad1a 100644 --- a/lib/chef/chef_fs/file_system/chef_server/chef_server_root_dir.rb +++ b/lib/chef/chef_fs/file_system/chef_server/chef_server_root_dir.rb @@ -31,6 +31,7 @@ require "chef/chef_fs/file_system/chef_server/organization_members_entry" require "chef/chef_fs/file_system/chef_server/policies_dir" require "chef/chef_fs/file_system/chef_server/policy_groups_dir" require "chef/chef_fs/file_system/chef_server/environments_dir" +require "chef/chef_fs/file_system/chef_server/roles_dir" require "chef/chef_fs/data_handler/acl_data_handler" require "chef/chef_fs/data_handler/client_data_handler" require "chef/chef_fs/data_handler/environment_data_handler" @@ -149,7 +150,7 @@ class Chef # /environments EnvironmentsDir.new("environments", self, nil, Chef::ChefFS::DataHandler::EnvironmentDataHandler.new), # /roles - RestListDir.new("roles", self, nil, Chef::ChefFS::DataHandler::RoleDataHandler.new), + RolesDir.new("roles", self, nil, Chef::ChefFS::DataHandler::RoleDataHandler.new), ] if repo_mode == "hosted_everything" result += [ diff --git a/lib/chef/chef_fs/file_system/chef_server/environments_dir.rb b/lib/chef/chef_fs/file_system/chef_server/environments_dir.rb index 494036931f..2b8a400435 100644 --- a/lib/chef/chef_fs/file_system/chef_server/environments_dir.rb +++ b/lib/chef/chef_fs/file_system/chef_server/environments_dir.rb @@ -34,6 +34,10 @@ class Chef end end + def can_have_child?(name, is_dir) + %w{ .rb .json }.include?(File.extname(name)) && !is_dir + end + class DefaultEnvironmentEntry < RestListEntry def initialize(name, parent, exists = nil) super(name, parent) diff --git a/lib/chef/chef_fs/file_system/chef_server/role_entry.rb b/lib/chef/chef_fs/file_system/chef_server/role_entry.rb new file mode 100644 index 0000000000..1d4cd4bf5d --- /dev/null +++ b/lib/chef/chef_fs/file_system/chef_server/role_entry.rb @@ -0,0 +1,59 @@ +# +# Author:: John Keiser (<jkeiser@chef.io>) +# Copyright:: Copyright 2013-2016, Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require "chef/chef_fs/file_system/chef_server/rest_list_entry" +require "chef/chef_fs/file_system/not_found_error" +require "chef/chef_fs/file_system/operation_not_allowed_error" +require "chef/chef_fs/file_system/operation_failed_error" + +class Chef + module ChefFS + module FileSystem + module ChefServer + class RoleEntry < RestListEntry + + def api_child_name + raise "Invalid name #{name}" unless %w{ .rb .json}.include? File.extname(name) + File.basename(name, ".*") + end + + def child_name(name) + if File.extname(name) == ".rb" + name.gsub(/.rb$/, ".json") + else + name + end + end + + def exists? + cn = child_name(name) + if @exists.nil? + begin + @exists = parent.children.any? { |child| child.name == cn } + rescue Chef::ChefFS::FileSystem::NotFoundError + @exists = false + end + end + @exists + end + + end + end + end + end +end diff --git a/lib/chef/chef_fs/file_system/chef_server/roles_dir.rb b/lib/chef/chef_fs/file_system/chef_server/roles_dir.rb new file mode 100644 index 0000000000..707b5424c8 --- /dev/null +++ b/lib/chef/chef_fs/file_system/chef_server/roles_dir.rb @@ -0,0 +1,51 @@ +# +# Author:: John Keiser (<jkeiser@chef.io>) +# Copyright:: Copyright 2012-2016, Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require "chef/chef_fs/file_system/base_fs_dir" +require "chef/chef_fs/file_system/chef_server/rest_list_dir" +require "chef/chef_fs/file_system/chef_server/role_entry" +require "chef/chef_fs/file_system/not_found_error" + +class Chef + module ChefFS + module FileSystem + module ChefServer + class RolesDir < RestListDir + def can_have_child?(name, is_dir) + %w{ .rb .json }.include?(File.extname(name)) && !is_dir + end + + def child_name(name) + if File.extname(name) == ".rb" + name.gsub(/.rb$/, ".json") + else + name + end + end + + def make_child_entry(name, exists = nil) + cn = child_name(name) + @children.select { |child| child.name == cn }.first if @children + RoleEntry.new(cn, self, exists) + end + + end + end + end + end +end diff --git a/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_roles_dir.rb b/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_roles_dir.rb new file mode 100644 index 0000000000..e8e3ee07e2 --- /dev/null +++ b/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_roles_dir.rb @@ -0,0 +1,45 @@ +# +# Author:: Jordan Running (<jr@chef.io>) +# Copyright:: Copyright 2013-2016, Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require "chef/chef_fs/file_system/repository/chef_repository_file_system_entry" +require "chef/chef_fs/file_system/repository/ruby_or_json_file.rb" +require "chef/chef_fs/data_handler/role_data_handler" + +class Chef + module ChefFS + module FileSystem + module Repository + class ChefRepositoryFileSystemRolesDir < ChefRepositoryFileSystemEntry + def initialize(name, parent, path = nil) + super(name, parent, path, Chef::ChefFS::DataHandler::RoleDataHandler.new) + end + + def can_have_child?(name, is_dir) + %w{ .rb .json }.include?(File.extname(name)) && !is_dir + end + + protected + def make_child_entry(child_name) + RubyOrJsonFile.new(child_name, self) + end + + end + end + end + end +end diff --git a/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_root_dir.rb b/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_root_dir.rb index c7209ba634..72bb402ab5 100644 --- a/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_root_dir.rb +++ b/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_root_dir.rb @@ -22,6 +22,7 @@ require "chef/chef_fs/file_system/repository/cookbooks_dir" require "chef/chef_fs/file_system/repository/cookbook_artifacts_dir" require "chef/chef_fs/file_system/repository/data_bags_dir" require "chef/chef_fs/file_system/repository/chef_repository_file_system_client_keys_dir" +require "chef/chef_fs/file_system/repository/chef_repository_file_system_roles_dir" require "chef/chef_fs/file_system/repository/chef_repository_file_system_entry" require "chef/chef_fs/file_system/repository/chef_repository_file_system_policies_dir" require "chef/chef_fs/file_system/repository/versioned_cookbooks_dir" @@ -182,6 +183,8 @@ class Chef dirs = paths.map { |path| ChefRepositoryFileSystemAclsDir.new(name, self, path) } when "client_keys" dirs = paths.map { |path| ChefRepositoryFileSystemClientKeysDir.new(name, self, path) } + when "roles" + dirs = paths.map { |path| ChefRepositoryFileSystemRolesDir.new(name, self, path) } else data_handler = case name when "clients" @@ -192,8 +195,6 @@ class Chef Chef::ChefFS::DataHandler::NodeDataHandler.new when "policy_groups" Chef::ChefFS::DataHandler::PolicyGroupDataHandler.new - when "roles" - Chef::ChefFS::DataHandler::RoleDataHandler.new when "users" Chef::ChefFS::DataHandler::UserDataHandler.new when "groups" diff --git a/lib/chef/chef_fs/file_system/repository/ruby_or_json_file.rb b/lib/chef/chef_fs/file_system/repository/ruby_or_json_file.rb new file mode 100644 index 0000000000..2e6644e34f --- /dev/null +++ b/lib/chef/chef_fs/file_system/repository/ruby_or_json_file.rb @@ -0,0 +1,84 @@ +# +# Author:: Thom May (<thom@chef.io>) +# Copyright:: Copyright 2016, Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require "chef/chef_fs/data_handler/role_data_handler" +class Chef + module ChefFS + module FileSystem + module Repository + class RubyOrJsonFile < ChefRepositoryFileSystemEntry + attr_reader :name + attr_reader :parent + attr_reader :path + attr_reader :file_path + attr_reader :data_handler + + def initialize(name, parent) + @parent = parent + @name = name + @path = Chef::ChefFS::PathUtils.join(parent.path, name) + @data_handler = parent.data_handler + @file_path = "#{parent.file_path}/#{name}" + end + + def name_valid? + !name.start_with?(".") && %w{ .rb .json }.include?(File.extname(name)) + end + + def fs_entry_valid? + name_valid? && File.file?(file_path) + end + + def create(file_contents) + if exists? + raise Chef::ChefFS::FileSystem::AlreadyExistsError.new(:create_child, self) + else + write(file_contents) + end + end + + def can_have_child?(name, is_dir) + false + end + + def path_for_printing + file_path + end + + def read + if File.extname(file_path) == ".rb" + data_handler.from_ruby(file_path).to_json + else + File.read(file_path) + end + rescue Errno::ENOENT + raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!) + end + + def root + parent.root + end + + def compare_to(other) + nil + end + end + end + end + end +end diff --git a/spec/integration/knife/upload_spec.rb b/spec/integration/knife/upload_spec.rb index 739dfa44d1..708cc8f04c 100644 --- a/spec/integration/knife/upload_spec.rb +++ b/spec/integration/knife/upload_spec.rb @@ -154,6 +154,24 @@ EOM end end + context "the role is in ruby" do + before do + file "roles/x.rb", <<EOM +name "x" +description "blarghle" +EOM + end + + it "knife upload changes the role" do + knife("upload /").should_succeed "Updated /roles/x.json\n" + knife("diff --name-status /").should_succeed "" + end + it "knife upload --no-diff does not change the role" do + knife("upload --no-diff /").should_succeed "" + knife("diff --name-status /").should_succeed "M\t/roles/x.rb\n" + end + end + context "when cookbook metadata has a self-dependency" do before do file "cookbooks/x/metadata.rb", "name 'x'; version '1.0.0'; depends 'x'" |