diff options
author | Steven Danna <steve@chef.io> | 2015-06-04 10:57:46 +0100 |
---|---|---|
committer | Steven Danna <steve@chef.io> | 2015-06-04 10:57:46 +0100 |
commit | c69db828a15451a91196385876cb215a01141394 (patch) | |
tree | 4d5430fd015b2b0eb3b893d35d5ce7ab06246245 | |
parent | ef2c094b7dd9d61fa9c441b96adafda5c677b2e4 (diff) | |
parent | a0115458cd27e1b9e6c05f56fdff88dc1ccca0d9 (diff) | |
download | chef-c69db828a15451a91196385876cb215a01141394.tar.gz |
Merge pull request #3489 from chef/hyphenated-lwrp
Hyphenated LWRP
-rw-r--r-- | lib/chef/mixin/convert_to_class_name.rb | 14 | ||||
-rw-r--r-- | spec/integration/recipes/lwrp_spec.rb | 57 | ||||
-rw-r--r-- | spec/unit/lwrp_spec.rb | 133 |
3 files changed, 164 insertions, 40 deletions
diff --git a/lib/chef/mixin/convert_to_class_name.rb b/lib/chef/mixin/convert_to_class_name.rb index 19f229fdd3..14676e5ed4 100644 --- a/lib/chef/mixin/convert_to_class_name.rb +++ b/lib/chef/mixin/convert_to_class_name.rb @@ -23,9 +23,7 @@ class Chef extend self def convert_to_class_name(str) - str = str.dup - str.gsub!(/[^A-Za-z0-9_]/,'_') - str.gsub!(/^(_+)?/,'') + str = normalize_snake_case_name(str) rname = nil regexp = %r{^(.+?)(_(.+))?$} @@ -51,6 +49,13 @@ class Chef str end + def normalize_snake_case_name(str) + str = str.dup + str.gsub!(/[^A-Za-z0-9_]/,'_') + str.gsub!(/^(_+)?/,'') + str + end + def snake_case_basename(str) with_namespace = convert_to_snake_case(str) with_namespace.split("::").last.sub(/^_/, '') @@ -58,7 +63,8 @@ class Chef def filename_to_qualified_string(base, filename) file_base = File.basename(filename, ".rb") - base.to_s + (file_base == 'default' ? '' : "_#{file_base}") + str = base.to_s + (file_base == 'default' ? '' : "_#{file_base}") + normalize_snake_case_name(str) end # Copied from rails activesupport. In ruby >= 2.0 const_get will just do this, so this can diff --git a/spec/integration/recipes/lwrp_spec.rb b/spec/integration/recipes/lwrp_spec.rb new file mode 100644 index 0000000000..e93763fddc --- /dev/null +++ b/spec/integration/recipes/lwrp_spec.rb @@ -0,0 +1,57 @@ +require 'support/shared/integration/integration_helper' +require 'chef/mixin/shell_out' + +describe "LWRPs" do + include IntegrationSupport + include Chef::Mixin::ShellOut + + let(:chef_dir) { File.expand_path("../../../../bin", __FILE__) } + + # Invoke `chef-client` as `ruby PATH/TO/chef-client`. This ensures the + # following constraints are satisfied: + # * Windows: windows can only run batch scripts as bare executables. Rubygems + # creates batch wrappers for installed gems, but we don't have batch wrappers + # in the source tree. + # * Other `chef-client` in PATH: A common case is running the tests on a + # machine that has omnibus chef installed. In that case we need to ensure + # we're running `chef-client` from the source tree and not the external one. + # cf. CHEF-4914 + let(:chef_client) { "ruby '#{chef_dir}/chef-client' --minimal-ohai" } + + when_the_repository "has a cookbook named l-w-r-p" do + before do + directory 'cookbooks/l-w-r-p' do + + file 'resources/foo.rb', <<EOM +default_action :create +EOM + file 'providers/foo.rb', <<EOM +action :create do +end +EOM + + file 'recipes/default.rb', <<EOM +l_w_r_p_foo "me" +EOM + + end # directory 'cookbooks/x' + end + + it "should complete with success" do + file 'config/client.rb', <<EOM +local_mode true +cookbook_path "#{path_to('cookbooks')}" +log_level :warn +EOM + + result = shell_out("#{chef_client} -c \"#{path_to('config/client.rb')}\" --no-color -F doc -o 'l-w-r-p::default'", :cwd => chef_dir) + actual = result.stdout.lines.map { |l| l.chomp }.join("\n") + expected = <<EOM + * l_w_r_p_foo[me] action create (up to date) +EOM + expected = expected.lines.map { |l| l.chomp }.join("\n") + expect(actual).to include(expected) + result.error! + end + end +end diff --git a/spec/unit/lwrp_spec.rb b/spec/unit/lwrp_spec.rb index 58cba27adf..dbf76d3c13 100644 --- a/spec/unit/lwrp_spec.rb +++ b/spec/unit/lwrp_spec.rb @@ -122,6 +122,23 @@ describe "LWRP" do end + context "When an LWRP resource in cookbook l-w-r-p is loaded" do + before do + @tmpdir = Dir.mktmpdir("lwrp_test") + resource_path = File.join(@tmpdir, "foo.rb") + IO.write(resource_path, "default_action :create") + provider_path = File.join(@tmpdir, "foo.rb") + IO.write(provider_path, <<-EOM) + action :create do + raise "hi" + end + EOM + end + + it "Can find the resource at l_w_r_p_foo" do + end + end + context "When an LWRP resource lwrp_foo is loaded" do before do @tmpdir = Dir.mktmpdir("lwrp_test") @@ -448,27 +465,38 @@ describe "LWRP" do end describe "Lightweight Chef::Provider" do + + let(:node) do + Chef::Node.new.tap do |n| + n.automatic[:platform] = :ubuntu + n.automatic[:platform_version] = '8.10' + end + end + + let(:events) { Chef::EventDispatch::Dispatcher.new } + + let(:run_context) { Chef::RunContext.new(node, Chef::CookbookCollection.new({}), events) } + + let(:runner) { Chef::Runner.new(run_context) } + + let(:lwrp_cookbok_name) { "lwrp" } + before do - @node = Chef::Node.new - @node.automatic[:platform] = :ubuntu - @node.automatic[:platform_version] = '8.10' - @events = Chef::EventDispatch::Dispatcher.new - @run_context = Chef::RunContext.new(@node, Chef::CookbookCollection.new({}), @events) - @runner = Chef::Runner.new(@run_context) + Chef::Provider::LWRPBase.class_eval { @loaded_lwrps = {} } end before(:each) do Dir[File.expand_path(File.expand_path("../../data/lwrp/resources/*", __FILE__))].each do |file| - Chef::Resource::LWRPBase.build_from_file("lwrp", file, @run_context) + Chef::Resource::LWRPBase.build_from_file(lwrp_cookbok_name, file, run_context) end Dir[File.expand_path(File.expand_path("../../data/lwrp/providers/*", __FILE__))].each do |file| - Chef::Provider::LWRPBase.build_from_file("lwrp", file, @run_context) + Chef::Provider::LWRPBase.build_from_file(lwrp_cookbok_name, file, run_context) end end it "should properly handle a new_resource reference" do - resource = get_lwrp(:lwrp_foo).new("morpheus", @run_context) + resource = get_lwrp(:lwrp_foo).new("morpheus", run_context) resource.monkey("bob") resource.provider(get_lwrp_provider(:lwrp_monkey_name_printer)) @@ -481,6 +509,7 @@ describe "LWRP" do @old_treat_deprecation_warnings_as_errors = Chef::Config[:treat_deprecation_warnings_as_errors] Chef::Config[:treat_deprecation_warnings_as_errors] = false end + after do Chef::Config[:treat_deprecation_warnings_as_errors] = @old_treat_deprecation_warnings_as_errors end @@ -494,54 +523,86 @@ describe "LWRP" do expect(get_lwrp_provider(:lwrp_buck_passer).instance_methods).to include(:action_pass_buck) expect(get_lwrp_provider(:lwrp_thumb_twiddler).instance_methods).to include(:action_twiddle_thumbs) end + + it "sets itself as a provider for a resource of the same name" do + found_providers = Chef::Platform::ProviderPriorityMap.instance.list_handlers(node, :lwrp_buck_passer) + # we bypass the per-file loading to get the file to load each time, + # which creates the LWRP class repeatedly. New things get prepended to + # the list of providers. + expect(found_providers.first).to eq(get_lwrp_provider(:lwrp_buck_passer)) + end + + context "with a cookbook with an underscore in the name" do + + let(:lwrp_cookbok_name) { "l_w_r_p" } + + it "sets itself as a provider for a resource of the same name" do + found_providers = Chef::Platform::ProviderPriorityMap.instance.list_handlers(node, :l_w_r_p_buck_passer) + expect(found_providers.size).to eq(1) + expect(found_providers.last).to eq(get_lwrp_provider(:l_w_r_p_buck_passer)) + end + end + + context "with a cookbook with a hypen in the name" do + + let(:lwrp_cookbok_name) { "l-w-r-p" } + + it "sets itself as a provider for a resource of the same name" do + incorrect_providers = Chef::Platform::ProviderPriorityMap.instance.list_handlers(node, :'l-w-r-p_buck_passer') + expect(incorrect_providers).to eq([]) + + found_providers = Chef::Platform::ProviderPriorityMap.instance.list_handlers(node, :l_w_r_p_buck_passer) + expect(found_providers.first).to eq(get_lwrp_provider(:l_w_r_p_buck_passer)) + end + end end it "should insert resources embedded in the provider into the middle of the resource collection" do - injector = get_lwrp(:lwrp_foo).new("morpheus", @run_context) + injector = get_lwrp(:lwrp_foo).new("morpheus", run_context) injector.action(:pass_buck) injector.provider(get_lwrp_provider(:lwrp_buck_passer)) - dummy = Chef::Resource::ZenMaster.new("keanu reeves", @run_context) + dummy = Chef::Resource::ZenMaster.new("keanu reeves", run_context) dummy.provider(Chef::Provider::Easy) - @run_context.resource_collection.insert(injector) - @run_context.resource_collection.insert(dummy) + run_context.resource_collection.insert(injector) + run_context.resource_collection.insert(dummy) - Chef::Runner.new(@run_context).converge + Chef::Runner.new(run_context).converge - expect(@run_context.resource_collection[0]).to eql(injector) - expect(@run_context.resource_collection[1].name).to eql('prepared_thumbs') - expect(@run_context.resource_collection[2].name).to eql('twiddled_thumbs') - expect(@run_context.resource_collection[3]).to eql(dummy) + expect(run_context.resource_collection[0]).to eql(injector) + expect(run_context.resource_collection[1].name).to eql('prepared_thumbs') + expect(run_context.resource_collection[2].name).to eql('twiddled_thumbs') + expect(run_context.resource_collection[3]).to eql(dummy) end it "should insert embedded resources from multiple providers, including from the last position, properly into the resource collection" do - injector = get_lwrp(:lwrp_foo).new("morpheus", @run_context) + injector = get_lwrp(:lwrp_foo).new("morpheus", run_context) injector.action(:pass_buck) injector.provider(get_lwrp_provider(:lwrp_buck_passer)) - injector2 = get_lwrp(:lwrp_bar).new("tank", @run_context) + injector2 = get_lwrp(:lwrp_bar).new("tank", run_context) injector2.action(:pass_buck) injector2.provider(get_lwrp_provider(:lwrp_buck_passer_2)) - dummy = Chef::Resource::ZenMaster.new("keanu reeves", @run_context) + dummy = Chef::Resource::ZenMaster.new("keanu reeves", run_context) dummy.provider(Chef::Provider::Easy) - @run_context.resource_collection.insert(injector) - @run_context.resource_collection.insert(dummy) - @run_context.resource_collection.insert(injector2) + run_context.resource_collection.insert(injector) + run_context.resource_collection.insert(dummy) + run_context.resource_collection.insert(injector2) - Chef::Runner.new(@run_context).converge + Chef::Runner.new(run_context).converge - expect(@run_context.resource_collection[0]).to eql(injector) - expect(@run_context.resource_collection[1].name).to eql('prepared_thumbs') - expect(@run_context.resource_collection[2].name).to eql('twiddled_thumbs') - expect(@run_context.resource_collection[3]).to eql(dummy) - expect(@run_context.resource_collection[4]).to eql(injector2) - expect(@run_context.resource_collection[5].name).to eql('prepared_eyes') - expect(@run_context.resource_collection[6].name).to eql('dried_paint_watched') + expect(run_context.resource_collection[0]).to eql(injector) + expect(run_context.resource_collection[1].name).to eql('prepared_thumbs') + expect(run_context.resource_collection[2].name).to eql('twiddled_thumbs') + expect(run_context.resource_collection[3]).to eql(dummy) + expect(run_context.resource_collection[4]).to eql(injector2) + expect(run_context.resource_collection[5].name).to eql('prepared_eyes') + expect(run_context.resource_collection[6].name).to eql('dried_paint_watched') end it "should properly handle a new_resource reference" do - resource = get_lwrp(:lwrp_foo).new("morpheus", @run_context) + resource = get_lwrp(:lwrp_foo).new("morpheus", run_context) resource.monkey("bob") resource.provider(get_lwrp_provider(:lwrp_monkey_name_printer)) @@ -552,7 +613,7 @@ describe "LWRP" do end it "should properly handle an embedded Resource accessing the enclosing Provider's scope" do - resource = get_lwrp(:lwrp_foo).new("morpheus", @run_context) + resource = get_lwrp(:lwrp_foo).new("morpheus", run_context) resource.monkey("bob") resource.provider(get_lwrp_provider(:lwrp_embedded_resource_accesses_providers_scope)) @@ -571,7 +632,7 @@ describe "LWRP" do # Side effect of lwrp_inline_compiler provider for testing notifications. $interior_ruby_block_2 = nil # resource type doesn't matter, so make an existing resource type work with provider. - @resource = get_lwrp(:lwrp_foo).new("morpheus", @run_context) + @resource = get_lwrp(:lwrp_foo).new("morpheus", run_context) @resource.allowed_actions << :test @resource.action(:test) @resource.provider(get_lwrp_provider(:lwrp_inline_compiler)) @@ -579,7 +640,7 @@ describe "LWRP" do it "does not add interior resources to the exterior resource collection" do @resource.run_action(:test) - expect(@run_context.resource_collection).to be_empty + expect(run_context.resource_collection).to be_empty end context "when interior resources are updated" do |