diff options
author | Lamont Granquist <lamont@scriptkiddie.org> | 2015-10-24 23:56:29 -0700 |
---|---|---|
committer | Lamont Granquist <lamont@scriptkiddie.org> | 2015-10-24 23:56:29 -0700 |
commit | 798339fd64729224a27cedd4e4aeb87e47fd1e92 (patch) | |
tree | da762f76f14ef0a6dd92eacbe849d0220fe9d4b9 | |
parent | 12c8f798ddf94c99943c71f8dbf55ed8b193a3c0 (diff) | |
parent | 1bebe8c4d9199490b8bde182f476a0375d053c22 (diff) | |
download | chef-798339fd64729224a27cedd4e4aeb87e47fd1e92.tar.gz |
Merge pull request #4105 from chef/lcg/merges
Lcg/merges
26 files changed, 263 insertions, 88 deletions
diff --git a/.gitignore b/.gitignore index 39962d2f5f..953f58919f 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,6 @@ Vagrantfile # Kitchen Tests Local Mode Data kitchen-tests/nodes/* + +# Temporary files present during spec runs +spec/data/test-dir diff --git a/CHANGELOG.md b/CHANGELOG.md index f2c5223eec..00041ca584 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,35 @@ [pr#3263](https://github.com/chef/chef/pull/3263) `value_for_platform` should use `Chef::VersionConstraint::Platform` * [**Scott McGillivray**](https://github.com/thechile) [pr#3450](https://github.com/chef/chef/pull/3450) Fix 'knife cookbook show' to work on root files - +* [**Aubrey Holland**](https://github.com/aub) + [pr#3986](https://github.com/chef/chef/pull/3986) fix errors when files go away during chown +* [**James Michael DuPont**](https://github.com/h4ck3rm1k3) + [pr#3973](https://github.com/chef/chef/pull/3973) better error reporting +* [**Michael Pereira**](https://github.com/MichaelPereira) + [pr#3968](https://github.com/chef/chef/pull/3968) Fix cookbook installation from supermarket on windows +* [**Yukihiko SAWANOBORI**](https://github.com/sawanoboly) + [pr#3941](https://github.com/chef/chef/pull/3941) allow reboot by reboot resource with chef-apply +* [**permyakovsv**](https://github.com/permyakovsv) + [pr#3901](https://github.com/chef/chef/pull/3901) Add tmux-split parameter to knife ssh +* [**Yukihiko SAWANOBORI**](https://github.com/sawanoboly) + [pr#3900](https://github.com/chef/chef/pull/3900) Add new option json attributes file to bootstraping +* [**Evan Gilman**](https://github.com/evan2645) + [pr#3864](https://github.com/chef/chef/pull/3864) Knife `bootstrap_environment` should use Explicit config before Implicit +* [**Ranjib Dey**](https://github.com/ranjib) + [pr#3834](https://github.com/chef/chef/pull/3834) Dont spit out stdout and stderr for execute resource failure, if its declared sensitive +* [**Jeff Blaine**](https://github.com/jblaine) + [pr#3776](https://github.com/chef/chef/pull/3776) Changes --hide-healthy to --hide-by-mins MINS +* [**dbresson**](https://github.com/dbresson) + [pr#3650](https://github.com/chef/chef/pull/3650) Define == for node objects +* [**Jordan Evans**](https://github.com/jordane) + [pr#3633](https://github.com/chef/chef/pull/3633) add the word group to `converge_by` call for group provider +* [**Patrick Connolly**](https://github.com/patcon) + [pr#3529](https://github.com/chef/chef/pull/3529) Allow user@hostname format for knife-bootstrap + +* [pr#3530](https://github.com/chef/chef/pull/3530) Allow using --sudo option with user's home folder in knife bootstrap +* [pr#3858](https://github.com/chef/chef/pull/3858) Remove duplicate 'Accept' header in spec +* [pr#3911](https://github.com/chef/chef/pull/3911) Avoid subclassing Struct.new +* [pr#3990](https://github.com/chef/chef/pull/3990) Use SHA256 instead of MD5 for `registry_key` when data is not displayable * [pr#4034](https://github.com/chef/chef/pull/4034) add optional ruby-profiling with --profile-ruby * [pr#3119](https://github.com/chef/chef/pull/3119) allow removing user, even if their GID isn't resolvable * [pr#4068](https://github.com/chef/chef/pull/4068) update messaging from LWRP to Custom Resource in logging and spec diff --git a/lib/chef/api_client/registration.rb b/lib/chef/api_client/registration.rb index de5fc7ac3d..4882323293 100644 --- a/lib/chef/api_client/registration.rb +++ b/lib/chef/api_client/registration.rb @@ -68,7 +68,8 @@ class Chef def assert_destination_writable! if (File.exists?(destination) && !File.writable?(destination)) or !File.writable?(File.dirname(destination)) - raise Chef::Exceptions::CannotWritePrivateKey, "I cannot write your private key to #{destination} - check permissions?" + abs_path = File.expand_path(destination) + raise Chef::Exceptions::CannotWritePrivateKey, "I can't write your private key to #{abs_path} - check permissions?" end end diff --git a/lib/chef/application/apply.rb b/lib/chef/application/apply.rb index b21b838d72..4c559542f1 100644 --- a/lib/chef/application/apply.rb +++ b/lib/chef/application/apply.rb @@ -196,6 +196,7 @@ class Chef::Application::Apply < Chef::Application ensure @recipe_fh.close end + Chef::Platform::Rebooter.reboot_if_needed!(runner) end def run_application diff --git a/lib/chef/digester.rb b/lib/chef/digester.rb index 75c4e76859..f2b496b785 100644 --- a/lib/chef/digester.rb +++ b/lib/chef/digester.rb @@ -38,7 +38,11 @@ class Chef end def generate_checksum(file) - checksum_file(file, OpenSSL::Digest::SHA256.new) + if file.is_a?(StringIO) + checksum_io(file, OpenSSL::Digest::SHA256.new) + else + checksum_file(file, OpenSSL::Digest::SHA256.new) + end end def self.generate_md5_checksum_for_file(*args) diff --git a/lib/chef/exceptions.rb b/lib/chef/exceptions.rb index 6e7ff2e24a..855c86d9cc 100644 --- a/lib/chef/exceptions.rb +++ b/lib/chef/exceptions.rb @@ -74,6 +74,11 @@ class Chef class InvalidPrivateKey < ArgumentError; end class MissingKeyAttribute < ArgumentError; end class KeyCommandInputError < ArgumentError; end + class BootstrapCommandInputError < ArgumentError + def initialize + super "You cannot pass both --json-attributes and --json-attribute-file. Please pass one or none." + end + end class InvalidKeyArgument < ArgumentError; end class InvalidKeyAttribute < ArgumentError; end class InvalidUserAttribute < ArgumentError; end diff --git a/lib/chef/knife/bootstrap.rb b/lib/chef/knife/bootstrap.rb index 93236225a2..8502ccb8eb 100644 --- a/lib/chef/knife/bootstrap.rb +++ b/lib/chef/knife/bootstrap.rb @@ -42,7 +42,7 @@ class Chef Chef::Knife::Ssh.load_deps end - banner "knife bootstrap FQDN (options)" + banner "knife bootstrap [SSH_USER@]FQDN (options)" option :ssh_user, :short => "-x USERNAME", @@ -122,6 +122,11 @@ class Chef :description => "Execute the bootstrap via sudo", :boolean => true + option :preserve_home, + :long => "--sudo-preserve-home", + :description => "Preserve non-root user HOME environment variable with sudo", + :boolean => true + option :use_sudo_password, :long => "--use-sudo-password", :description => "Execute the bootstrap via sudo with password", @@ -164,7 +169,13 @@ class Chef :long => "--json-attributes", :description => "A JSON string to be added to the first run of chef-client", :proc => lambda { |o| Chef::JSONCompat.parse(o) }, - :default => {} + :default => nil + + option :first_boot_attributes_from_file, + :long => "--json-attribute-file FILE", + :description => "A JSON file to be used to the first run of chef-client", + :proc => lambda { |o| Chef::JSONCompat.parse(File.read(o)) }, + :default => nil option :host_key_verify, :long => "--[no-]host-key-verify", @@ -256,13 +267,25 @@ class Chef "chef-full" end + def host_descriptor + Array(@name_args).first + end + # The server_name is the DNS or IP we are going to connect to, it is not necessarily # the node name, the fqdn, or the hostname of the server. This is a public API hook # which knife plugins use or inherit and override. # # @return [String] The DNS or IP that bootstrap will connect to def server_name - Array(@name_args).first + if host_descriptor + @server_name ||= host_descriptor.split('@').reverse[0] + end + end + + def user_name + if host_descriptor + @user_name ||= host_descriptor.split('@').reverse[1] + end end def bootstrap_template @@ -317,13 +340,22 @@ class Chef ) end + def first_boot_attributes + @config[:first_boot_attributes] || @config[:first_boot_attributes_from_file] || {} + end + def render_template + @config[:first_boot_attributes] = first_boot_attributes template_file = find_template template = IO.read(template_file).chomp Erubis::Eruby.new(template).evaluate(bootstrap_context) end def run + if @config[:first_boot_attributes] && @config[:first_boot_attributes_from_file] + raise Chef::Exceptions::BootstrapCommandInputError + end + validate_name_args! validate_options! @@ -358,7 +390,7 @@ class Chef if config[:ssh_password] raise else - ui.info("Failed to authenticate #{config[:ssh_user]} - trying password auth") + ui.info("Failed to authenticate #{knife_ssh.config[:ssh_user]} - trying password auth") knife_ssh_with_password_auth.run end end @@ -389,7 +421,7 @@ class Chef ssh = Chef::Knife::Ssh.new ssh.ui = ui ssh.name_args = [ server_name, ssh_command ] - ssh.config[:ssh_user] = config[:ssh_user] + ssh.config[:ssh_user] = user_name || config[:ssh_user] ssh.config[:ssh_password] = config[:ssh_password] ssh.config[:ssh_port] = config[:ssh_port] ssh.config[:ssh_gateway] = config[:ssh_gateway] @@ -412,7 +444,8 @@ class Chef command = render_template if config[:use_sudo] - command = config[:use_sudo_password] ? "echo '#{config[:ssh_password]}' | sudo -SH #{command}" : "sudo -H #{command}" + sudo_prefix = config[:use_sudo_password] ? "echo '#{config[:ssh_password]}' | sudo -S " : "sudo " + command = config[:preserve_home] ? "#{sudo_prefix} #{command}" : "#{sudo_prefix} -H #{command}" end command diff --git a/lib/chef/knife/cookbook_site_install.rb b/lib/chef/knife/cookbook_site_install.rb index aee8b7fa94..cc68fe7897 100644 --- a/lib/chef/knife/cookbook_site_install.rb +++ b/lib/chef/knife/cookbook_site_install.rb @@ -142,7 +142,11 @@ class Chef def extract_cookbook(upstream_file, version) ui.info("Uncompressing #{@cookbook_name} version #{version}.") # FIXME: Detect if we have the bad tar from git on Windows: https://github.com/opscode/chef/issues/1753 - shell_out!("tar zxvf #{convert_path upstream_file}", :cwd => @install_path) + extract_command="tar zxvf \"#{convert_path upstream_file}\"" + if Chef::Platform.windows? + extract_command << " --force-local" + end + shell_out!(extract_command, :cwd => @install_path) end def clear_existing_files(cookbook_path) diff --git a/lib/chef/knife/core/bootstrap_context.rb b/lib/chef/knife/core/bootstrap_context.rb index d210b9418f..8613a50cb4 100644 --- a/lib/chef/knife/core/bootstrap_context.rb +++ b/lib/chef/knife/core/bootstrap_context.rb @@ -40,7 +40,7 @@ class Chef end def bootstrap_environment - @chef_config[:environment] + @config[:environment] end def validation_key diff --git a/lib/chef/knife/ssh.rb b/lib/chef/knife/ssh.rb index 996f40c91d..89a9608c60 100644 --- a/lib/chef/knife/ssh.rb +++ b/lib/chef/knife/ssh.rb @@ -111,6 +111,12 @@ class Chef :boolean => true, :proc => Proc.new { :raise } + option :tmux_split, + :long => "--tmux-split", + :description => "Split tmux window.", + :boolean => true, + :default => false + def session config[:on_error] ||= :skip ssh_error_handler = Proc.new do |server| @@ -404,7 +410,11 @@ class Chef new_window_cmds = lambda do if session.servers_for.size > 1 [""] + session.servers_for[1..-1].map do |server| - "new-window -a -n '#{server.host}' #{ssh_dest.call(server)}" + if config[:tmux_split] + "split-window #{ssh_dest.call(server)}; tmux select-layout tiled" + else + "new-window -a -n '#{server.host}' #{ssh_dest.call(server)}" + end end else [] diff --git a/lib/chef/knife/status.rb b/lib/chef/knife/status.rb index 95f2c724ff..1a61b035cb 100644 --- a/lib/chef/knife/status.rb +++ b/lib/chef/knife/status.rb @@ -44,7 +44,11 @@ class Chef option :hide_healthy, :short => "-H", :long => "--hide-healthy", - :description => "Hide nodes that have run chef in the last hour" + :description => "Hide nodes that have run chef in the last hour. [DEPRECATED] Use --hide-by-mins MINS instead" + + option :hide_by_mins, + :long => "--hide-by-mins MINS", + :description => "Hide nodes that have run chef in the last MINS minutes" def append_to_query(term) @query << " AND " unless @query.empty? @@ -68,12 +72,21 @@ class Chef append_to_query("chef_environment:#{config[:environment]}") if config[:environment] if config[:hide_healthy] + ui.warn("-H / --hide-healthy is deprecated. Use --hide-by-mins MINS instead") time = Time.now.to_i # AND NOT is not valid lucene syntax, so don't use append_to_query @query << " " unless @query.empty? @query << "NOT ohai_time:[#{(time - 60*60).to_s} TO #{time.to_s}]" end + if config[:hide_by_mins] + hidemins = config[:hide_by_mins].to_i + time = Time.now.to_i + # AND NOT is not valid lucene syntax, so don't use append_to_query + @query << " " unless @query.empty? + @query << "NOT ohai_time:[#{(time - hidemins*60).to_s} TO #{time.to_s}]" + end + @query = @query.empty? ? "*:*" : @query all_nodes = [] diff --git a/lib/chef/node.rb b/lib/chef/node.rb index ad065cc02b..83ec7e2550 100644 --- a/lib/chef/node.rb +++ b/lib/chef/node.rb @@ -647,6 +647,14 @@ class Chef "node[#{name}]" end + def ==(other) + if other.kind_of?(self.class) + self.name == other.name + else + false + end + end + def <=>(other_node) self.name <=> other_node.name end diff --git a/lib/chef/provider/deploy.rb b/lib/chef/provider/deploy.rb index 77a0410593..c59200e717 100644 --- a/lib/chef/provider/deploy.rb +++ b/lib/chef/provider/deploy.rb @@ -276,7 +276,7 @@ class Chef def enforce_ownership converge_by("force ownership of #{@new_resource.deploy_to} to #{@new_resource.group}:#{@new_resource.user}") do - FileUtils.chown_R(@new_resource.user, @new_resource.group, @new_resource.deploy_to) + FileUtils.chown_R(@new_resource.user, @new_resource.group, @new_resource.deploy_to, :force => true) Chef::Log.info("#{@new_resource} set user to #{@new_resource.user}") if @new_resource.user Chef::Log.info("#{@new_resource} set group to #{@new_resource.group}") if @new_resource.group end diff --git a/lib/chef/provider/execute.rb b/lib/chef/provider/execute.rb index c3dd3b4ee1..30de0d3b9e 100644 --- a/lib/chef/provider/execute.rb +++ b/lib/chef/provider/execute.rb @@ -58,7 +58,16 @@ class Chef end converge_by("execute #{description}") do - result = shell_out!(command, opts) + begin + shell_out!(command, opts) + rescue Mixlib::ShellOut::ShellCommandFailed + if sensitive? + raise Mixlib::ShellOut::ShellCommandFailed, + "Command execution failed. STDOUT/STDERR suppressed for sensitive resource" + else + raise + end + end Chef::Log.info("#{new_resource} ran successfully") end end diff --git a/lib/chef/provider/group.rb b/lib/chef/provider/group.rb index a802758dce..a1cf92058d 100644 --- a/lib/chef/provider/group.rb +++ b/lib/chef/provider/group.rb @@ -125,7 +125,7 @@ class Chef def action_create case @group_exists when false - converge_by("create #{@new_resource.group_name}") do + converge_by("create group #{@new_resource.group_name}") do create_group Chef::Log.info("#{@new_resource} created") end diff --git a/lib/chef/resource/registry_key.rb b/lib/chef/resource/registry_key.rb index d2e5c4b94c..f1bf7954ce 100644 --- a/lib/chef/resource/registry_key.rb +++ b/lib/chef/resource/registry_key.rb @@ -125,7 +125,7 @@ class Chef scrubbed_value = value.dup if needs_checksum?(scrubbed_value) data_io = StringIO.new(scrubbed_value[:data].to_s) - scrubbed_value[:data] = Chef::Digester.instance.generate_md5_checksum(data_io) + scrubbed_value[:data] = Chef::Digester.instance.generate_checksum(data_io) end scrubbed << scrubbed_value end diff --git a/lib/chef/resource/resource_notification.rb b/lib/chef/resource/resource_notification.rb index a27ed961c7..4fd61ad1f8 100644 --- a/lib/chef/resource/resource_notification.rb +++ b/lib/chef/resource/resource_notification.rb @@ -20,7 +20,15 @@ require 'chef/resource' class Chef class Resource - class Notification < Struct.new(:resource, :action, :notifying_resource) + class Notification + + attr_accessor :resource, :action, :notifying_resource + + def initialize(resource, action, notifying_resource) + @resource = resource + @action = action + @notifying_resource = notifying_resource + end def duplicates?(other_notification) unless other_notification.respond_to?(:resource) && other_notification.respond_to?(:action) @@ -104,6 +112,11 @@ is defined near #{resource.source_line} raise err end + def ==(other) + return false unless other.is_a?(self.class) + other.resource == resource && other.action == action && other.notifying_resource == notifying_resource + end + end end end diff --git a/spec/unit/knife/bootstrap_spec.rb b/spec/unit/knife/bootstrap_spec.rb index 48aae3e61b..342c1878f1 100644 --- a/spec/unit/knife/bootstrap_spec.rb +++ b/spec/unit/knife/bootstrap_spec.rb @@ -235,12 +235,39 @@ describe Chef::Knife::Bootstrap do expect(knife.render_template).to eq('{"run_list":["role[base]","recipe[cupcakes]"]}') end - it "should have foo => {bar => baz} in the first_boot" do - knife.parse_options(["-j", '{"foo":{"bar":"baz"}}']) - knife.merge_configs - expected_hash = FFI_Yajl::Parser.new.parse('{"foo":{"bar":"baz"},"run_list":[]}') - actual_hash = FFI_Yajl::Parser.new.parse(knife.render_template) - expect(actual_hash).to eq(expected_hash) + context "with bootstrap_attribute options" do + let(:jsonfile) { + file = Tempfile.new (['node', '.json']) + File.open(file.path, "w") {|f| f.puts '{"foo":{"bar":"baz"}}' } + file + } + + it "should have foo => {bar => baz} in the first_boot from cli" do + knife.parse_options(["-j", '{"foo":{"bar":"baz"}}']) + knife.merge_configs + expected_hash = FFI_Yajl::Parser.new.parse('{"foo":{"bar":"baz"},"run_list":[]}') + actual_hash = FFI_Yajl::Parser.new.parse(knife.render_template) + expect(actual_hash).to eq(expected_hash) + end + + it "should have foo => {bar => baz} in the first_boot from file" do + knife.parse_options(["--json-attribute-file", jsonfile.path]) + knife.merge_configs + expected_hash = FFI_Yajl::Parser.new.parse('{"foo":{"bar":"baz"},"run_list":[]}') + actual_hash = FFI_Yajl::Parser.new.parse(knife.render_template) + expect(actual_hash).to eq(expected_hash) + jsonfile.close + end + + context "when --json-attributes and --json-attribute-file were both passed" do + it "raises a Chef::Exceptions::BootstrapCommandInputError with the proper error message" do + knife.parse_options(["-j", '{"foo":{"bar":"baz"}}']) + knife.parse_options(["--json-attribute-file", jsonfile.path]) + knife.merge_configs + expect{ knife.run }.to raise_error(Chef::Exceptions::BootstrapCommandInputError) + jsonfile.close + end + end end end diff --git a/spec/unit/knife/core/bootstrap_context_spec.rb b/spec/unit/knife/core/bootstrap_context_spec.rb index 0433ef9983..4d69d6300a 100644 --- a/spec/unit/knife/core/bootstrap_context_spec.rb +++ b/spec/unit/knife/core/bootstrap_context_spec.rb @@ -91,7 +91,7 @@ EXPECTED end describe "when bootstrapping into a specific environment" do - let(:chef_config){ {:environment => "prodtastic"} } + let(:config){ {:environment => "prodtastic"} } it "starts chef in the configured environment" do expect(bootstrap_context.start_chef).to eq('chef-client -j /etc/chef/first-boot.json -E prodtastic') end diff --git a/spec/unit/knife/status_spec.rb b/spec/unit/knife/status_spec.rb index ee44f3b3fd..11728a6f9b 100644 --- a/spec/unit/knife/status_spec.rb +++ b/spec/unit/knife/status_spec.rb @@ -44,9 +44,9 @@ describe Chef::Knife::Status do @knife.run end - it "should filter healthy nodes" do - @knife.config[:hide_healthy] = true - expect(@query).to receive(:search).with(:node, "NOT ohai_time:[1428569820 TO 1428573420]", opts) + it "should filter by nodes older than some mins" do + @knife.config[:hide_by_mins] = 59 + expect(@query).to receive(:search).with(:node, "NOT ohai_time:[1428569880 TO 1428573420]", opts) @knife.run end @@ -56,10 +56,10 @@ describe Chef::Knife::Status do @knife.run end - it "should filter by environment and health" do + it "should filter by environment and nodes older than some mins" do @knife.config[:environment] = "production" - @knife.config[:hide_healthy] = true - expect(@query).to receive(:search).with(:node, "chef_environment:production NOT ohai_time:[1428569820 TO 1428573420]", opts) + @knife.config[:hide_by_mins] = 59 + expect(@query).to receive(:search).with(:node, "chef_environment:production NOT ohai_time:[1428569880 TO 1428573420]", opts) @knife.run end @@ -79,22 +79,22 @@ describe Chef::Knife::Status do @knife.run end - it "should filter healthy nodes" do - @knife.config[:hide_healthy] = true - expect(@query).to receive(:search).with(:node, "name:my_custom_name NOT ohai_time:[1428569820 TO 1428573420]", opts) + it "should filter by nodes older than some mins with nodename specified" do + @knife.config[:hide_by_mins] = 59 + expect(@query).to receive(:search).with(:node, "name:my_custom_name NOT ohai_time:[1428569880 TO 1428573420]", opts) @knife.run end - it "should filter by environment" do + it "should filter by environment with nodename specified" do @knife.config[:environment] = "production" expect(@query).to receive(:search).with(:node, "name:my_custom_name AND chef_environment:production", opts) @knife.run end - it "should filter by environment and health" do + it "should filter by environment and nodes older than some mins with nodename specified" do @knife.config[:environment] = "production" - @knife.config[:hide_healthy] = true - expect(@query).to receive(:search).with(:node, "name:my_custom_name AND chef_environment:production NOT ohai_time:[1428569820 TO 1428573420]", opts) + @knife.config[:hide_by_mins] = 59 + expect(@query).to receive(:search).with(:node, "name:my_custom_name AND chef_environment:production NOT ohai_time:[1428569880 TO 1428573420]", opts) @knife.run end end diff --git a/spec/unit/node_spec.rb b/spec/unit/node_spec.rb index 5f3bed2833..17e085a465 100644 --- a/spec/unit/node_spec.rb +++ b/spec/unit/node_spec.rb @@ -42,6 +42,14 @@ describe Chef::Node do expect([n3, n1, n2].sort).to eq([n1, n2, n3]) end + it "should share identity only with others of the same name" do + n1 = Chef::Node.build('foo') + n2 = Chef::Node.build('foo') + n3 = Chef::Node.build('bar') + expect(n1).to eq(n2) + expect(n1).not_to eq(n3) + end + describe "when the node does not exist on the server" do before do response = OpenStruct.new(:code => '404') diff --git a/spec/unit/provider/deploy_spec.rb b/spec/unit/provider/deploy_spec.rb index e6a7125e32..adcb9431eb 100644 --- a/spec/unit/provider/deploy_spec.rb +++ b/spec/unit/provider/deploy_spec.rb @@ -356,7 +356,7 @@ describe Chef::Provider::Deploy do it "chowns the whole release dir to user and group specified in the resource" do @resource.user "foo" @resource.group "bar" - expect(FileUtils).to receive(:chown_R).with("foo", "bar", "/my/deploy/dir") + expect(FileUtils).to receive(:chown_R).with("foo", "bar", "/my/deploy/dir", { :force => true }) @provider.enforce_ownership end diff --git a/spec/unit/provider/execute_spec.rb b/spec/unit/provider/execute_spec.rb index 1274203ce3..e7607d9417 100644 --- a/spec/unit/provider/execute_spec.rb +++ b/spec/unit/provider/execute_spec.rb @@ -172,5 +172,14 @@ describe Chef::Provider::Execute do provider.run_action(:run) expect(new_resource).to be_updated end + + it "should not include stdout/stderr in failure exception for sensitive resource" do + opts.delete(:live_stream) + new_resource.sensitive true + expect(provider).to receive(:shell_out!).and_raise(Mixlib::ShellOut::ShellCommandFailed) + expect do + provider.run_action(:run) + end.to raise_error(Mixlib::ShellOut::ShellCommandFailed, /suppressed for sensitive resource/) + end end end diff --git a/spec/unit/resource/registry_key_spec.rb b/spec/unit/resource/registry_key_spec.rb index 2e2811d026..2d82f1a51c 100644 --- a/spec/unit/resource/registry_key_spec.rb +++ b/spec/unit/resource/registry_key_spec.rb @@ -91,7 +91,7 @@ describe Chef::Resource::RegistryKey, "values" do it "should return checksummed data if the type is unsafe" do @resource.values( { :name => 'poosh', :type => :binary, :data => 255.chr * 1 }) - expect(@resource.values).to eql([ { :name => 'poosh', :type => :binary, :data => "00594fd4f42ba43fc1ca0427a0576295" } ]) + expect(@resource.values).to eql([ { :name => 'poosh', :type => :binary, :data => 'a8100ae6aa1940d0b663bb31cd466142ebbdbd5187131b92d93818987832eb89' } ]) end it "should throw an exception if the name field is missing" do @@ -194,6 +194,6 @@ describe Chef::Resource::RegistryKey, "state" do it "should return scrubbed values" do @resource.values([ { :name => 'poosh', :type => :binary, :data => 255.chr * 1 } ]) - expect(@resource.state).to eql( { :values => [{ :name => 'poosh', :type => :binary, :data => "00594fd4f42ba43fc1ca0427a0576295" }] } ) + expect(@resource.state).to eql( { :values => [{ :name => 'poosh', :type => :binary, :data => 'a8100ae6aa1940d0b663bb31cd466142ebbdbd5187131b92d93818987832eb89'}] } ) end end diff --git a/spec/unit/resource/resource_notification_spec.rb b/spec/unit/resource/resource_notification_spec.rb index 7f6b124d4d..024b6f93f7 100644 --- a/spec/unit/resource/resource_notification_spec.rb +++ b/spec/unit/resource/resource_notification_spec.rb @@ -19,149 +19,148 @@ require 'spec_helper' require 'chef/resource/resource_notification' describe Chef::Resource::Notification do - before do - @notification = Chef::Resource::Notification.new(:service_apache, :restart, :template_httpd_conf) - end + + let(:notification) { Chef::Resource::Notification.new(:service_apache, :restart, :template_httpd_conf) } it "has a resource to be notified" do - expect(@notification.resource).to eq(:service_apache) + expect(notification.resource).to eq(:service_apache) end it "has an action to take on the service" do - expect(@notification.action).to eq(:restart) + expect(notification.action).to eq(:restart) end it "has a notifying resource" do - expect(@notification.notifying_resource).to eq(:template_httpd_conf) + expect(notification.notifying_resource).to eq(:template_httpd_conf) end it "is a duplicate of another notification with the same target resource and action" do other = Chef::Resource::Notification.new(:service_apache, :restart, :sync_web_app_code) - expect(@notification.duplicates?(other)).to be_truthy + expect(notification.duplicates?(other)).to be_truthy end it "is not a duplicate of another notification if the actions differ" do other = Chef::Resource::Notification.new(:service_apache, :enable, :install_apache) - expect(@notification.duplicates?(other)).to be_falsey + expect(notification.duplicates?(other)).to be_falsey end it "is not a duplicate of another notification if the target resources differ" do other = Chef::Resource::Notification.new(:service_sshd, :restart, :template_httpd_conf) - expect(@notification.duplicates?(other)).to be_falsey + expect(notification.duplicates?(other)).to be_falsey end it "raises an ArgumentError if you try to check a non-ducktype object for duplication" do - expect {@notification.duplicates?(:not_a_notification)}.to raise_error(ArgumentError) + expect {notification.duplicates?(:not_a_notification)}.to raise_error(ArgumentError) end it "takes no action to resolve a resource reference that doesn't need to be resolved" do @keyboard_cat = Chef::Resource::Cat.new("keyboard_cat") - @notification.resource = @keyboard_cat + notification.resource = @keyboard_cat @long_cat = Chef::Resource::Cat.new("long_cat") - @notification.notifying_resource = @long_cat + notification.notifying_resource = @long_cat @resource_collection = Chef::ResourceCollection.new # would raise an error since the resource is not in the collection - @notification.resolve_resource_reference(@resource_collection) - expect(@notification.resource).to eq(@keyboard_cat) + notification.resolve_resource_reference(@resource_collection) + expect(notification.resource).to eq(@keyboard_cat) end it "resolves a lazy reference to a resource" do - @notification.resource = {:cat => "keyboard_cat"} + notification.resource = {:cat => "keyboard_cat"} @keyboard_cat = Chef::Resource::Cat.new("keyboard_cat") @resource_collection = Chef::ResourceCollection.new @resource_collection << @keyboard_cat @long_cat = Chef::Resource::Cat.new("long_cat") - @notification.notifying_resource = @long_cat - @notification.resolve_resource_reference(@resource_collection) - expect(@notification.resource).to eq(@keyboard_cat) + notification.notifying_resource = @long_cat + notification.resolve_resource_reference(@resource_collection) + expect(notification.resource).to eq(@keyboard_cat) end it "resolves a lazy reference to its notifying resource" do @keyboard_cat = Chef::Resource::Cat.new("keyboard_cat") - @notification.resource = @keyboard_cat - @notification.notifying_resource = {:cat => "long_cat"} + notification.resource = @keyboard_cat + notification.notifying_resource = {:cat => "long_cat"} @long_cat = Chef::Resource::Cat.new("long_cat") @resource_collection = Chef::ResourceCollection.new @resource_collection << @long_cat - @notification.resolve_resource_reference(@resource_collection) - expect(@notification.notifying_resource).to eq(@long_cat) + notification.resolve_resource_reference(@resource_collection) + expect(notification.notifying_resource).to eq(@long_cat) end it "resolves lazy references to both its resource and its notifying resource" do - @notification.resource = {:cat => "keyboard_cat"} + notification.resource = {:cat => "keyboard_cat"} @keyboard_cat = Chef::Resource::Cat.new("keyboard_cat") @resource_collection = Chef::ResourceCollection.new @resource_collection << @keyboard_cat - @notification.notifying_resource = {:cat => "long_cat"} + notification.notifying_resource = {:cat => "long_cat"} @long_cat = Chef::Resource::Cat.new("long_cat") @resource_collection << @long_cat - @notification.resolve_resource_reference(@resource_collection) - expect(@notification.resource).to eq(@keyboard_cat) - expect(@notification.notifying_resource).to eq(@long_cat) + notification.resolve_resource_reference(@resource_collection) + expect(notification.resource).to eq(@keyboard_cat) + expect(notification.notifying_resource).to eq(@long_cat) end it "raises a RuntimeError if you try to reference multiple resources" do - @notification.resource = {:cat => ["keyboard_cat", "cheez_cat"]} + notification.resource = {:cat => ["keyboard_cat", "cheez_cat"]} @keyboard_cat = Chef::Resource::Cat.new("keyboard_cat") @cheez_cat = Chef::Resource::Cat.new("cheez_cat") @resource_collection = Chef::ResourceCollection.new @resource_collection << @keyboard_cat @resource_collection << @cheez_cat @long_cat = Chef::Resource::Cat.new("long_cat") - @notification.notifying_resource = @long_cat - expect {@notification.resolve_resource_reference(@resource_collection)}.to raise_error(RuntimeError) + notification.notifying_resource = @long_cat + expect {notification.resolve_resource_reference(@resource_collection)}.to raise_error(RuntimeError) end it "raises a RuntimeError if you try to reference multiple notifying resources" do - @notification.notifying_resource = {:cat => ["long_cat", "cheez_cat"]} + notification.notifying_resource = {:cat => ["long_cat", "cheez_cat"]} @long_cat = Chef::Resource::Cat.new("long_cat") @cheez_cat = Chef::Resource::Cat.new("cheez_cat") @resource_collection = Chef::ResourceCollection.new @resource_collection << @long_cat @resource_collection << @cheez_cat @keyboard_cat = Chef::Resource::Cat.new("keyboard_cat") - @notification.resource = @keyboard_cat - expect {@notification.resolve_resource_reference(@resource_collection)}.to raise_error(RuntimeError) + notification.resource = @keyboard_cat + expect {notification.resolve_resource_reference(@resource_collection)}.to raise_error(RuntimeError) end it "raises a RuntimeError if it can't find a resource in the resource collection when resolving a lazy reference" do - @notification.resource = {:cat => "keyboard_cat"} + notification.resource = {:cat => "keyboard_cat"} @cheez_cat = Chef::Resource::Cat.new("cheez_cat") @resource_collection = Chef::ResourceCollection.new @resource_collection << @cheez_cat @long_cat = Chef::Resource::Cat.new("long_cat") - @notification.notifying_resource = @long_cat - expect {@notification.resolve_resource_reference(@resource_collection)}.to raise_error(RuntimeError) + notification.notifying_resource = @long_cat + expect {notification.resolve_resource_reference(@resource_collection)}.to raise_error(RuntimeError) end it "raises a RuntimeError if it can't find a notifying resource in the resource collection when resolving a lazy reference" do - @notification.notifying_resource = {:cat => "long_cat"} + notification.notifying_resource = {:cat => "long_cat"} @cheez_cat = Chef::Resource::Cat.new("cheez_cat") @resource_collection = Chef::ResourceCollection.new @resource_collection << @cheez_cat @keyboard_cat = Chef::Resource::Cat.new("keyboard_cat") - @notification.resource = @keyboard_cat - expect {@notification.resolve_resource_reference(@resource_collection)}.to raise_error(RuntimeError) + notification.resource = @keyboard_cat + expect {notification.resolve_resource_reference(@resource_collection)}.to raise_error(RuntimeError) end it "raises an ArgumentError if improper syntax is used in the lazy reference to its resource" do - @notification.resource = "cat => keyboard_cat" + notification.resource = "cat => keyboard_cat" @keyboard_cat = Chef::Resource::Cat.new("keyboard_cat") @resource_collection = Chef::ResourceCollection.new @resource_collection << @keyboard_cat @long_cat = Chef::Resource::Cat.new("long_cat") - @notification.notifying_resource = @long_cat - expect {@notification.resolve_resource_reference(@resource_collection)}.to raise_error(ArgumentError) + notification.notifying_resource = @long_cat + expect {notification.resolve_resource_reference(@resource_collection)}.to raise_error(ArgumentError) end it "raises an ArgumentError if improper syntax is used in the lazy reference to its notifying resource" do - @notification.notifying_resource = "cat => long_cat" + notification.notifying_resource = "cat => long_cat" @long_cat = Chef::Resource::Cat.new("long_cat") @resource_collection = Chef::ResourceCollection.new @resource_collection << @long_cat @keyboard_cat = Chef::Resource::Cat.new("keyboard_cat") - @notification.resource = @keyboard_cat - expect {@notification.resolve_resource_reference(@resource_collection)}.to raise_error(ArgumentError) + notification.resource = @keyboard_cat + expect {notification.resolve_resource_reference(@resource_collection)}.to raise_error(ArgumentError) end # Create test to resolve lazy references to both notifying resource and dest. resource diff --git a/spec/unit/rest_spec.rb b/spec/unit/rest_spec.rb index 3b04981610..3eee997c50 100644 --- a/spec/unit/rest_spec.rb +++ b/spec/unit/rest_spec.rb @@ -69,8 +69,8 @@ describe Chef::REST do rest end - let(:standard_read_headers) {{"Accept"=>"application/json", "Accept"=>"application/json", "Accept-Encoding"=>"gzip;q=1.0,deflate;q=0.6,identity;q=0.3", "X-REMOTE-REQUEST-ID"=>request_id, 'X-Ops-Server-API-Version' => Chef::HTTP::Authenticator::DEFAULT_SERVER_API_VERSION}} - let(:standard_write_headers) {{"Accept"=>"application/json", "Content-Type"=>"application/json", "Accept"=>"application/json", "Accept-Encoding"=>"gzip;q=1.0,deflate;q=0.6,identity;q=0.3", "X-REMOTE-REQUEST-ID"=>request_id, 'X-Ops-Server-API-Version' => Chef::HTTP::Authenticator::DEFAULT_SERVER_API_VERSION}} + let(:standard_read_headers) {{"Accept"=>"application/json", "Accept-Encoding"=>"gzip;q=1.0,deflate;q=0.6,identity;q=0.3", "X-REMOTE-REQUEST-ID"=>request_id, 'X-Ops-Server-API-Version' => Chef::HTTP::Authenticator::DEFAULT_SERVER_API_VERSION}} + let(:standard_write_headers) {{"Accept"=>"application/json", "Content-Type"=>"application/json", "Accept-Encoding"=>"gzip;q=1.0,deflate;q=0.6,identity;q=0.3", "X-REMOTE-REQUEST-ID"=>request_id, 'X-Ops-Server-API-Version' => Chef::HTTP::Authenticator::DEFAULT_SERVER_API_VERSION}} before(:each) do Chef::Log.init(log_stringio) |