summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteven Danna <steve@chef.io>2015-06-04 10:57:46 +0100
committerSteven Danna <steve@chef.io>2015-06-04 10:57:46 +0100
commitc69db828a15451a91196385876cb215a01141394 (patch)
tree4d5430fd015b2b0eb3b893d35d5ce7ab06246245
parentef2c094b7dd9d61fa9c441b96adafda5c677b2e4 (diff)
parenta0115458cd27e1b9e6c05f56fdff88dc1ccca0d9 (diff)
downloadchef-c69db828a15451a91196385876cb215a01141394.tar.gz
Merge pull request #3489 from chef/hyphenated-lwrp
Hyphenated LWRP
-rw-r--r--lib/chef/mixin/convert_to_class_name.rb14
-rw-r--r--spec/integration/recipes/lwrp_spec.rb57
-rw-r--r--spec/unit/lwrp_spec.rb133
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