diff options
22 files changed, 247 insertions, 47 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index b0704862eb..032fca2bac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,13 @@ [pr#3764](https://github.com/chef/chef/pull/3764) uniquify chef\_repo\_path * [**Renan Vicente**](https://github.com/renanvicente): [pr#3771](https://github.com/chef/chef/pull/3771) add depth property for deploy resource +* [**James Belchamber**](https://github.com/JamesBelchamber): + [pr#1796](https://github.com/chef/chef/pull/1796): make mount options aware + +* [pr#2460](https://github.com/chef/chef/pull/2460) add privacy flag +* [pr#1259](https://github.com/chef/chef/pull/1259) CHEF-5012: add methods for template breadcrumbs +* [pr#3656](https://github.com/chef/chef/pull/3656) remove use of self.provides? * [pr#3455](https://github.com/chef/chef/pull/3455) powershell\_script: do not allow suppression of syntax errors * [pr#3519](https://github.com/chef/chef/pull/3519) The wording seemed odd. * [pr#3208](https://github.com/chef/chef/pull/3208) Missing require (require what you use). @@ -68,11 +68,11 @@ read the The general development process is: -1. Fork this repo and clone it to your workstation -2. Create a feature branch for your change -3. Write code and tests +1. Fork this repo and clone it to your workstation. +2. Create a feature branch for your change. +3. Write code and tests. 4. Push your feature branch to github and open a pull request against - master + master. Once your repository is set up, you can start working on the code. We do use TDD with RSpec, so you'll need to get a development environment running. diff --git a/lib/chef/cookbook/metadata.rb b/lib/chef/cookbook/metadata.rb index 01a98fda39..9822920a7d 100644 --- a/lib/chef/cookbook/metadata.rb +++ b/lib/chef/cookbook/metadata.rb @@ -54,12 +54,13 @@ class Chef VERSION = 'version'.freeze SOURCE_URL = 'source_url'.freeze ISSUES_URL = 'issues_url'.freeze + PRIVACY = 'privacy'.freeze COMPARISON_FIELDS = [ :name, :description, :long_description, :maintainer, :maintainer_email, :license, :platforms, :dependencies, :recommendations, :suggestions, :conflicting, :providing, :replacing, :attributes, :groupings, :recipes, :version, - :source_url, :issues_url ] + :source_url, :issues_url, :privacy ] VERSION_CONSTRAINTS = {:depends => DEPENDENCIES, :recommends => RECOMMENDATIONS, @@ -116,6 +117,7 @@ class Chef @version = Version.new("0.0.0") @source_url = '' @issues_url = '' + @privacy = false @errors = [] end @@ -454,7 +456,8 @@ class Chef :recipes => { :kind_of => [ Array ], :default => [] }, :default => { :kind_of => [ String, Array, Hash, Symbol, Numeric, TrueClass, FalseClass ] }, :source_url => { :kind_of => String }, - :issues_url => { :kind_of => String } + :issues_url => { :kind_of => String }, + :privacy => { :kind_of => [ TrueClass, FalseClass ] } } ) options[:required] = remap_required_attribute(options[:required]) unless options[:required].nil? @@ -498,7 +501,8 @@ class Chef RECIPES => self.recipes, VERSION => self.version, SOURCE_URL => self.source_url, - ISSUES_URL => self.issues_url + ISSUES_URL => self.issues_url, + PRIVACY => self.privacy } end @@ -532,6 +536,7 @@ class Chef @version = o[VERSION] if o.has_key?(VERSION) @source_url = o[SOURCE_URL] if o.has_key?(SOURCE_URL) @issues_url = o[ISSUES_URL] if o.has_key?(ISSUES_URL) + @privacy = o[PRIVACY] if o.has_key?(PRIVACY) self end @@ -590,6 +595,23 @@ class Chef ) end + # + # Sets the cookbook's privacy flag, or returns it. + # + # === Parameters + # privacy<TrueClass,FalseClass>:: Whether this cookbook is private or not + # + # === Returns + # privacy<TrueClass,FalseClass>:: Whether this cookbook is private or not + # + def privacy(arg=nil) + set_or_return( + :privacy, + arg, + :kind_of => [ TrueClass, FalseClass ] + ) + end + private def run_validation diff --git a/lib/chef/mixin/template.rb b/lib/chef/mixin/template.rb index d705a9e7be..be83edc697 100644 --- a/lib/chef/mixin/template.rb +++ b/lib/chef/mixin/template.rb @@ -44,6 +44,52 @@ class Chef attr_reader :_extension_modules + # + # Helpers for adding context of which resource is rendering the template (CHEF-5012) + # + + # name of the cookbook containing the template resource, e.g.: + # test + # + # @return [String] cookbook name + attr_reader :cookbook_name + + # name of the recipe containing the template resource, e.g.: + # default + # + # @return [String] recipe name + attr_reader :recipe_name + + # string representation of the line in the recipe containing the template resource, e.g.: + # /Users/lamont/solo/cookbooks/test/recipes/default.rb:2:in `from_file' + # + # @return [String] recipe line + attr_reader :recipe_line_string + + # path to the recipe containing the template resource, e.g.: + # /Users/lamont/solo/cookbooks/test/recipes/default.rb + # + # @return [String] recipe path + attr_reader :recipe_path + + # line in the recipe containing the template reosurce, e.g.: + # 2 + # + # @return [String] recipe line + attr_reader :recipe_line + + # name of the template source itself, e.g.: + # foo.erb + # + # @return [String] template name + attr_reader :template_name + + # path to the template source itself, e.g.: + # /Users/lamont/solo/cookbooks/test/templates/default/foo.erb + # + # @return [String] template path + attr_reader :template_path + def initialize(variables) super @_extension_modules = [] @@ -62,6 +108,7 @@ class Chef "include a node variable if you plan to use it." end + # # Takes the name of the partial, plus a hash of options. Returns a # string that contains the result of the evaluation of the partial. diff --git a/lib/chef/provider/mount.rb b/lib/chef/provider/mount.rb index 2039e9ae51..6bdfd5b867 100644 --- a/lib/chef/provider/mount.rb +++ b/lib/chef/provider/mount.rb @@ -42,13 +42,17 @@ class Chef end def action_mount - unless current_resource.mounted + if current_resource.mounted + if mount_options_unchanged? + Chef::Log.debug("#{new_resource} is already mounted") + else + action_remount + end + else converge_by("mount #{current_resource.device} to #{current_resource.mount_point}") do mount_fs Chef::Log.info("#{new_resource} mounted") end - else - Chef::Log.debug("#{new_resource} is already mounted") end end diff --git a/lib/chef/provider/service/debian.rb b/lib/chef/provider/service/debian.rb index 46c23fdd34..7d23e4ac77 100644 --- a/lib/chef/provider/service/debian.rb +++ b/lib/chef/provider/service/debian.rb @@ -22,15 +22,13 @@ class Chef class Provider class Service class Debian < Chef::Provider::Service::Init - provides :service, platform_family: 'debian' + provides :service, platform_family: 'debian' do |node| + Chef::Platform::ServiceHelpers.service_resource_providers.include?(:debian) + end UPDATE_RC_D_ENABLED_MATCHES = /\/rc[\dS].d\/S|not installed/i UPDATE_RC_D_PRIORITIES = /\/rc([\dS]).d\/([SK])(\d\d)/i - def self.provides?(node, resource) - super && Chef::Platform::ServiceHelpers.service_resource_providers.include?(:debian) - end - def self.supports?(resource, action) Chef::Platform::ServiceHelpers.config_for_service(resource.service_name).include?(:initd) end diff --git a/lib/chef/provider/service/insserv.rb b/lib/chef/provider/service/insserv.rb index 2fd2eac38e..dd01f9ab87 100644 --- a/lib/chef/provider/service/insserv.rb +++ b/lib/chef/provider/service/insserv.rb @@ -24,10 +24,8 @@ class Chef class Service class Insserv < Chef::Provider::Service::Init - provides :service, platform_family: %w(debian rhel fedora suse) - - def self.provides?(node, resource) - super && Chef::Platform::ServiceHelpers.service_resource_providers.include?(:insserv) + provides :service, platform_family: %w(debian rhel fedora suse) do |node| + Chef::Platform::ServiceHelpers.service_resource_providers.include?(:insserv) end def self.supports?(resource, action) diff --git a/lib/chef/provider/service/invokercd.rb b/lib/chef/provider/service/invokercd.rb index 39022546b0..2b045e0e60 100644 --- a/lib/chef/provider/service/invokercd.rb +++ b/lib/chef/provider/service/invokercd.rb @@ -23,10 +23,8 @@ class Chef class Service class Invokercd < Chef::Provider::Service::Init - provides :service, platform_family: 'debian', override: true - - def self.provides?(node, resource) - super && Chef::Platform::ServiceHelpers.service_resource_providers.include?(:invokercd) + provides :service, platform_family: 'debian', override: true do |node| + Chef::Platform::ServiceHelpers.service_resource_providers.include?(:invokercd) end def self.supports?(resource, action) diff --git a/lib/chef/provider/service/redhat.rb b/lib/chef/provider/service/redhat.rb index 2330d88eb7..19cd2aa485 100644 --- a/lib/chef/provider/service/redhat.rb +++ b/lib/chef/provider/service/redhat.rb @@ -23,15 +23,13 @@ class Chef class Service class Redhat < Chef::Provider::Service::Init - provides :service, platform_family: %w(rhel fedora suse) + provides :service, platform_family: %w(rhel fedora suse) do |node| + Chef::Platform::ServiceHelpers.service_resource_providers.include?(:redhat) + end CHKCONFIG_ON = /\d:on/ CHKCONFIG_MISSING = /No such/ - def self.provides?(node, resource) - super && Chef::Platform::ServiceHelpers.service_resource_providers.include?(:redhat) - end - def self.supports?(resource, action) Chef::Platform::ServiceHelpers.config_for_service(resource.service_name).include?(:initd) end diff --git a/lib/chef/provider/service/systemd.rb b/lib/chef/provider/service/systemd.rb index 9085ffde2e..d41f6248c2 100644 --- a/lib/chef/provider/service/systemd.rb +++ b/lib/chef/provider/service/systemd.rb @@ -24,14 +24,12 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple include Chef::Mixin::Which - provides :service, os: "linux" + provides :service, os: "linux" do |node| + Chef::Platform::ServiceHelpers.service_resource_providers.include?(:systemd) + end attr_accessor :status_check_success - def self.provides?(node, resource) - super && Chef::Platform::ServiceHelpers.service_resource_providers.include?(:systemd) - end - def self.supports?(resource, action) Chef::Platform::ServiceHelpers.config_for_service(resource.service_name).include?(:systemd) end diff --git a/lib/chef/provider/service/upstart.rb b/lib/chef/provider/service/upstart.rb index 13145bd055..c08a5f8636 100644 --- a/lib/chef/provider/service/upstart.rb +++ b/lib/chef/provider/service/upstart.rb @@ -26,14 +26,12 @@ class Chef class Service class Upstart < Chef::Provider::Service::Simple - provides :service, platform_family: 'debian', override: true + provides :service, platform_family: 'debian', override: true do |node| + Chef::Platform::ServiceHelpers.service_resource_providers.include?(:upstart) + end UPSTART_STATE_FORMAT = /\w+ \(?(\w+)\)?[\/ ](\w+)/ - def self.provides?(node, resource) - super && Chef::Platform::ServiceHelpers.service_resource_providers.include?(:upstart) - end - def self.supports?(resource, action) Chef::Platform::ServiceHelpers.config_for_service(resource.service_name).include?(:upstart) end diff --git a/lib/chef/provider/template/content.rb b/lib/chef/provider/template/content.rb index 7fc680ec85..a231bd509e 100644 --- a/lib/chef/provider/template/content.rb +++ b/lib/chef/provider/template/content.rb @@ -39,6 +39,16 @@ class Chef context = TemplateContext.new(@new_resource.variables) context[:node] = @run_context.node context[:template_finder] = template_finder + + # helper variables + context[:cookbook_name] = @new_resource.cookbook_name unless context.keys.include?(:coookbook_name) + context[:recipe_name] = @new_resource.recipe_name unless context.keys.include?(:recipe_name) + context[:recipe_line_string] = @new_resource.source_line unless context.keys.include?(:recipe_line_string) + context[:recipe_path] = @new_resource.source_line_file unless context.keys.include?(:recipe_path) + context[:recipe_line] = @new_resource.source_line_number unless context.keys.include?(:recipe_line) + context[:template_name] = @new_resource.source unless context.keys.include?(:template_name) + context[:template_path] = template_location unless context.keys.include?(:template_path) + context._extend_modules(@new_resource.helper_modules) output = context.render_template(template_location) diff --git a/lib/chef/resource.rb b/lib/chef/resource.rb index 60ec6bde93..5bef40625f 100644 --- a/lib/chef/resource.rb +++ b/lib/chef/resource.rb @@ -1627,16 +1627,31 @@ class Chef run_context.delayed_notifications(self) end + def source_line_file + if source_line + source_line.match(/(.*):(\d+):?.*$/).to_a[1] + else + nil + end + end + + def source_line_number + if source_line + source_line.match(/(.*):(\d+):?.*$/).to_a[2] + else + nil + end + end + def defined_at # The following regexp should match these two sourceline formats: # /some/path/to/file.rb:80:in `wombat_tears' # C:/some/path/to/file.rb:80 in 1`wombat_tears' # extracting the path to the source file and the line number. - (file, line_no) = source_line.match(/(.*):(\d+):?.*$/).to_a[1,2] if source_line if cookbook_name && recipe_name && source_line - "#{cookbook_name}::#{recipe_name} line #{line_no}" + "#{cookbook_name}::#{recipe_name} line #{source_line_number}" elsif source_line - "#{file} line #{line_no}" + "#{source_line_file} line #{source_line_number}" else "dynamically defined" end diff --git a/lib/chef/resource/registry_key.rb b/lib/chef/resource/registry_key.rb index 4ed0d4a4e0..d2e5c4b94c 100644 --- a/lib/chef/resource/registry_key.rb +++ b/lib/chef/resource/registry_key.rb @@ -93,7 +93,7 @@ class Chef raise ArgumentError, "Bad key #{key} in RegistryKey values hash" unless [:name,:type,:data].include?(key) end raise ArgumentError, "Type of name => #{v[:name]} should be string" unless v[:name].is_a?(String) - raise Argument Error "Type of type => #{v[:name]} should be symbol" unless v[:type].is_a?(Symbol) + raise ArgumentError, "Type of type => #{v[:type]} should be symbol" unless v[:type].is_a?(Symbol) end @unscrubbed_values = @values elsif self.instance_variable_defined?(:@values) diff --git a/spec/data/cookbooks/openldap/templates/default/helpers.erb b/spec/data/cookbooks/openldap/templates/default/helpers.erb new file mode 100644 index 0000000000..b973a5287c --- /dev/null +++ b/spec/data/cookbooks/openldap/templates/default/helpers.erb @@ -0,0 +1,14 @@ +<%= @cookbook_name %> +<%= @recipe_name %> +<%= @recipe_line_string %> +<%= @recipe_path %> +<%= @recipe_line %> +<%= @template_name %> +<%= @template_path %> +<%= cookbook_name %> +<%= recipe_name %> +<%= recipe_line_string %> +<%= recipe_path %> +<%= recipe_line %> +<%= template_name %> +<%= template_path %> diff --git a/spec/unit/cookbook/metadata_spec.rb b/spec/unit/cookbook/metadata_spec.rb index d2954726e8..1b30286f51 100644 --- a/spec/unit/cookbook/metadata_spec.rb +++ b/spec/unit/cookbook/metadata_spec.rb @@ -30,7 +30,7 @@ describe Chef::Cookbook::Metadata do :maintainer_email, :license, :platforms, :dependencies, :recommendations, :suggestions, :conflicting, :providing, :replacing, :attributes, :groupings, :recipes, :version, - :source_url, :issues_url ] + :source_url, :issues_url, :privacy ] end it "does not depend on object identity for equality" do @@ -148,6 +148,10 @@ describe Chef::Cookbook::Metadata do it "has an empty issues_url string" do expect(metadata.issues_url).to eq('') end + + it "is not private" do + expect(metadata.privacy).to eq(false) + end end describe "validation" do @@ -198,7 +202,8 @@ describe Chef::Cookbook::Metadata do :long_description => "Much Longer\nSeriously", :version => "0.6.0", :source_url => "http://example.com", - :issues_url => "http://example.com/issues" + :issues_url => "http://example.com/issues", + :privacy => true } params.sort { |a,b| a.to_s <=> b.to_s }.each do |field, field_value| describe field do @@ -360,7 +365,8 @@ describe Chef::Cookbook::Metadata do "recipes" => [ "mysql::server", "mysql::master" ], "default" => [ ], "source_url" => "http://example.com", - "issues_url" => "http://example.com/issues" + "issues_url" => "http://example.com/issues", + "privacy" => true } expect(metadata.attribute("/db/mysql/databases", attrs)).to eq(attrs) end @@ -401,6 +407,18 @@ describe Chef::Cookbook::Metadata do }.to raise_error(ArgumentError) end + it "should not accept anything but true or false for the privacy flag" do + expect { + metadata.attribute("db/mysql/databases", :privacy => true) + }.not_to raise_error + expect { + metadata.attribute("db/mysql/databases", :privacy => false) + }.not_to raise_error + expect { + metadata.attribute("db/mysql/databases", :privacy => 'true') + }.to raise_error(ArgumentError) + end + it "should not accept anything but an array of strings for choice" do expect { metadata.attribute("db/mysql/databases", :choice => ['dedicated', 'shared']) @@ -699,6 +717,7 @@ describe Chef::Cookbook::Metadata do version source_url issues_url + privacy }.each do |t| it "should include '#{t}'" do expect(deserialized_metadata[t]).to eq(metadata.send(t.to_sym)) @@ -734,6 +753,7 @@ describe Chef::Cookbook::Metadata do version source_url issues_url + privacy }.each do |t| it "should match '#{t}'" do expect(deserialized_metadata.send(t.to_sym)).to eq(metadata.send(t.to_sym)) diff --git a/spec/unit/cookbook/syntax_check_spec.rb b/spec/unit/cookbook/syntax_check_spec.rb index ee4e0bed02..764829c387 100644 --- a/spec/unit/cookbook/syntax_check_spec.rb +++ b/spec/unit/cookbook/syntax_check_spec.rb @@ -53,6 +53,7 @@ describe Chef::Cookbook::SyntaxCheck do @ruby_files = @attr_files + @libr_files + @defn_files + @recipes + [File.join(cookbook_path, "metadata.rb")] basenames = %w{ helpers_via_partial_test.erb helper_test.erb + helpers.erb openldap_stuff.conf.erb openldap_variable_stuff.conf.erb test.erb diff --git a/spec/unit/provider/mount/aix_spec.rb b/spec/unit/provider/mount/aix_spec.rb index ca0ddd006c..e232592275 100644 --- a/spec/unit/provider/mount/aix_spec.rb +++ b/spec/unit/provider/mount/aix_spec.rb @@ -126,9 +126,10 @@ ENABLED @provider.run_action(:mount) end - it "should not mount resource if it is already mounted" do + it "should not mount resource if it is already mounted and the options have not changed" do stub_mounted_enabled(@provider, @mounted_output, "") + allow(@provider).to receive(:mount_options_unchanged?).and_return(true) expect(@provider).not_to receive(:mount_fs) @provider.run_action(:mount) diff --git a/spec/unit/provider/mount/mount_spec.rb b/spec/unit/provider/mount/mount_spec.rb index 7a37ffe74e..dd13a62796 100644 --- a/spec/unit/provider/mount/mount_spec.rb +++ b/spec/unit/provider/mount/mount_spec.rb @@ -323,6 +323,12 @@ describe Chef::Provider::Mount::Mount do @provider.mount_fs() end + it "should not mount the filesystem if it is mounted and the options have not changed" do + allow(@current_resource).to receive(:mounted).and_return(true) + expect(@provider).to_not receive(:shell_out!) + @provider.mount_fs() + end + end describe "umount_fs" do diff --git a/spec/unit/provider/mount/windows_spec.rb b/spec/unit/provider/mount/windows_spec.rb index 467d923c6a..2de6f11d43 100644 --- a/spec/unit/provider/mount/windows_spec.rb +++ b/spec/unit/provider/mount/windows_spec.rb @@ -111,6 +111,20 @@ describe Chef::Provider::Mount::Windows do allow(@current_resource).to receive(:mounted).and_return(true) @provider.mount_fs end + + it "should remount the filesystem if it is mounted and the options have changed" do + expect(@vol).to receive(:add).with(:remote => @new_resource.device, + :username => @new_resource.username, + :domainname => @new_resource.domain, + :password => @new_resource.password) + @provider.mount_fs + end + + it "should not mount the filesystem if it is mounted and the options have not changed" do + expect(@vol).to_not receive(:add) + allow(@current_resource).to receive(:mounted).and_return(true) + @provider.mount_fs + end end describe "when unmounting a file system" do diff --git a/spec/unit/provider/mount_spec.rb b/spec/unit/provider/mount_spec.rb index e9fe3fa050..cc2a456440 100644 --- a/spec/unit/provider/mount_spec.rb +++ b/spec/unit/provider/mount_spec.rb @@ -61,8 +61,19 @@ describe Chef::Provider::Mount do expect(new_resource).to be_updated_by_last_action end - it "should not mount the filesystem if it is mounted" do + it "should remount the filesystem if it is mounted and the options have changed" do allow(current_resource).to receive(:mounted).and_return(true) + allow(provider).to receive(:mount_options_unchanged?).and_return(false) + expect(provider).to receive(:umount_fs).and_return(true) + expect(provider).to receive(:wait_until_unmounted) + expect(provider).to receive(:mount_fs).and_return(true) + provider.run_action(:mount) + expect(new_resource).to be_updated_by_last_action + end + + it "should not mount the filesystem if it is mounted and the options have not changed" do + allow(current_resource).to receive(:mounted).and_return(true) + expect(provider).to receive(:mount_options_unchanged?).and_return(true) expect(provider).not_to receive(:mount_fs) provider.run_action(:mount) expect(new_resource).not_to be_updated_by_last_action diff --git a/spec/unit/provider/template/content_spec.rb b/spec/unit/provider/template/content_spec.rb index 4b88a3aea5..3d6e822c00 100644 --- a/spec/unit/provider/template/content_spec.rb +++ b/spec/unit/provider/template/content_spec.rb @@ -23,6 +23,10 @@ describe Chef::Provider::Template::Content do let(:new_resource) do double("Chef::Resource::Template (new)", :cookbook_name => 'openldap', + :recipe_name => 'default', + :source_line => "/Users/lamont/solo/cookbooks/openldap/recipes/default.rb:2:in `from_file'", + :source_line_file => "/Users/lamont/solo/cookbooks/openldap/recipes/default.rb", + :source_line_number => "2", :source => 'openldap_stuff.conf.erb', :local => false, :cookbook => nil, @@ -75,4 +79,41 @@ describe Chef::Provider::Template::Content do expect(IO.read(content.tempfile.path)).to eq("slappiness is a warm gun") end + describe "when using location helpers" do + let(:new_resource) do + double("Chef::Resource::Template (new)", + :cookbook_name => 'openldap', + :recipe_name => 'default', + :source_line => CHEF_SPEC_DATA + "/cookbooks/openldap/recipes/default.rb:2:in `from_file'", + :source_line_file => CHEF_SPEC_DATA + "/cookbooks/openldap/recipes/default.rb", + :source_line_number => "2", + :source => 'helpers.erb', + :local => false, + :cookbook => nil, + :variables => {}, + :inline_helper_blocks => {}, + :inline_helper_modules => [], + :helper_modules => []) + end + + it "creates the template with the rendered content" do + expect(IO.read(content.tempfile.path)).to eql <<EOF +openldap +default +#{CHEF_SPEC_DATA}/cookbooks/openldap/recipes/default.rb:2:in `from_file' +#{CHEF_SPEC_DATA}/cookbooks/openldap/recipes/default.rb +2 +helpers.erb +#{CHEF_SPEC_DATA}/cookbooks/openldap/templates/default/helpers.erb +openldap +default +#{CHEF_SPEC_DATA}/cookbooks/openldap/recipes/default.rb:2:in `from_file' +#{CHEF_SPEC_DATA}/cookbooks/openldap/recipes/default.rb +2 +helpers.erb +#{CHEF_SPEC_DATA}/cookbooks/openldap/templates/default/helpers.erb +EOF + end + + end end |