diff options
26 files changed, 346 insertions, 269 deletions
diff --git a/.travis.yml b/.travis.yml index c60be3843b..5bc5e12790 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,8 +16,8 @@ matrix: - rvm: 1.8.7-p374 - rvm: 1.9.3 - rvm: 2.0.0 - - rvm: 2.1.0 - - rvm: 2.1.0 + - rvm: 2.1.1 + - rvm: 2.1.1 gemfile: pedant.gemfile script: bundle exec rake pedant diff --git a/CHANGELOG.md b/CHANGELOG.md index d2c9d27516..487f3321e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ## Unreleased * Print nested LWRPs with indentation in doc formatter output * Make local mode stable enough to run chef-pedant -* Catch HTTPServerException for 404 in remote_file retry (CHEF-5116) +* Catch HTTPServerException for 404 in remote\_file retry (CHEF-5116) * Wrap code in block context when syntax checking so `return` is valid (CHEF-5199) * Quote git resource rev\_pattern to prevent glob matching files (CHEF-4940) @@ -15,6 +15,8 @@ * Providers are now set correctly on CloudLinux. (CHEF-5182) * -E option now works with single lettered environments (CHEF-3075) * Set --run-lock-timeout to wait/bail if another client has the runlock (CHEF-5074) +* A node's environment can now be set with 'knife node environment set NODE ENVIRONMENT' (CHEF-1910) +* remote\_file's source attribute does not support DelayedEvaluators (CHEF-5162) ## Last Release: 11.12.0 RC1 (03/31/2014) * SIGTERM will once-more kill a non-daemonized chef-client (CHEF-5172) diff --git a/CONTRIBUTIONS.md b/CONTRIBUTIONS.md index f8c930bf6a..b541fed635 100644 --- a/CONTRIBUTIONS.md +++ b/CONTRIBUTIONS.md @@ -12,3 +12,4 @@ Example Contribution: * **johntdyer**: Catch HTTPServerException for 404 in remote_file retry (CHEF-5116) * **Kasen**: Providers are now set correctly on CloudLinux. (CHEF-5182) * **viyh**: Made -E option to work with single lettered environments. (CHEF-3075) +* **JimmyMcCrory**: Added a 'knife node environment set' command. (CHEF-1910) diff --git a/DOC_CHANGES.md b/DOC_CHANGES.md index ee65736b14..27706774f6 100644 --- a/DOC_CHANGES.md +++ b/DOC_CHANGES.md @@ -4,9 +4,20 @@ This file is reset every time a new release is done. This file describes changes Example Doc Change: ### Headline for the required change Description of the required change. +--> -### --run-lock-timeout for `chef-client` and `solo` -Users can now add a timeout for the maximum time a client run waits on another client run to finish. +### --run-lock-timeout for chef-client and chef-solo +You can now add a timeout for the maximum time a client run waits on another client run to finish. The default is to wait indefinitely. -Setting the run lock timeout to 0 causes the second client run to exit immediately. ---> +Setting the run lock timeout to 0 causes the second client run to exit immediately: + +``` +chef-client --run-lock-timeout 0 +``` + +#### New knife command: knife node environment set +You can now easily set the environment for an existing node without editing the node object: + +``` +knife node environment set NODE ENVIRONMENT +``` diff --git a/chef-x86-mingw32.gemspec b/chef-x86-mingw32.gemspec index b0ff015a68..49a15bcf00 100644 --- a/chef-x86-mingw32.gemspec +++ b/chef-x86-mingw32.gemspec @@ -7,7 +7,7 @@ gemspec.add_dependency "ffi", "1.5.0" gemspec.add_dependency "rdp-ruby-wmi", "0.3.1" gemspec.add_dependency "windows-api", "0.4.2" gemspec.add_dependency "windows-pr", "1.2.2" -gemspec.add_dependency "win32-api", "1.4.8" +gemspec.add_dependency "win32-api", "1.5.1" gemspec.add_dependency "win32-dir", "0.4.5" gemspec.add_dependency "win32-event", "0.6.1" gemspec.add_dependency "win32-mutex", "0.4.1" diff --git a/lib/chef/checksum/storage.rb b/lib/chef/checksum/storage.rb deleted file mode 100644 index 4a1b3d38df..0000000000 --- a/lib/chef/checksum/storage.rb +++ /dev/null @@ -1,18 +0,0 @@ -# -# Author:: Andrea Campi (<andrea.campi@zephirworks.com>) -# Copyright:: Copyright (c) 2011 Opscode, 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/checksum/storage/filesystem' diff --git a/lib/chef/checksum/storage/filesystem.rb b/lib/chef/checksum/storage/filesystem.rb deleted file mode 100644 index 94257f518b..0000000000 --- a/lib/chef/checksum/storage/filesystem.rb +++ /dev/null @@ -1,56 +0,0 @@ -# -# Author:: Tim Hinderliter (<tim@opscode.com>) -# Copyright:: Copyright (c) 2011 Opscode, 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. - -class Chef - class Checksum - class Storage - class Filesystem - def initialize(base_dir, checksum) - @base_dir = base_dir - @checksum = checksum - end - - def file_location - File.join(checksum_repo_directory, @checksum) - end - alias :to_s :file_location - - def checksum_repo_directory - File.join(Chef::Config.checksum_path, @checksum[0..1]) - end - - def commit(sandbox_file) - FileUtils.mkdir_p(checksum_repo_directory) - File.rename(sandbox_file, file_location) - end - - def revert(original_committed_file_location) - File.rename(file_location, original_committed_file_location) - end - - # Deletes the file backing this checksum from the on-disk repo. - # Purging the checksums is how users can get back to a valid state if - # they've deleted files, so we silently swallow Errno::ENOENT here. - def purge - FileUtils.rm(file_location) - rescue Errno::ENOENT - true - end - end - end - end -end diff --git a/lib/chef/event_dispatch/base.rb b/lib/chef/event_dispatch/base.rb index 82beefeec9..bfd4503097 100644 --- a/lib/chef/event_dispatch/base.rb +++ b/lib/chef/event_dispatch/base.rb @@ -277,6 +277,20 @@ class Chef def resource_updated(resource, action) end + # A stream has opened. + def stream_opened(stream, options = {}) + end + + # A stream has closed. + def stream_closed(stream, options = {}) + end + + # A chunk of data from a stream. The stream is managed by "stream," which + # can be any tag whatsoever. Data in different "streams" may not be placed + # on the same line or even sent to the same console. + def stream_output(stream, output, options = {}) + end + # Called before handlers run def handlers_start(handler_count) end diff --git a/lib/chef/event_dispatch/events_output_stream.rb b/lib/chef/event_dispatch/events_output_stream.rb new file mode 100644 index 0000000000..8de9b0fed1 --- /dev/null +++ b/lib/chef/event_dispatch/events_output_stream.rb @@ -0,0 +1,29 @@ +class Chef + module EventDispatch + class EventsOutputStream + # This is a fake stream that connects to events. + # + # == Arguments + # events: the EventDispatch object to send data to (run_context.events) + # options is a hash with these possible options: + # - name: a string that identifies the stream to the user. Preferably short. + + def initialize(events, options = {}) + @events = events + @options = options + events.stream_opened(self, options) + end + + attr_reader :options + attr_reader :events + + def print(str) + events.stream_output(self, str, options) + end + + def close + events.stream_closed(self, options) + end + end + end +end diff --git a/lib/chef/formatters/base.rb b/lib/chef/formatters/base.rb index 7bcb629fc7..636ba9c83f 100644 --- a/lib/chef/formatters/base.rb +++ b/lib/chef/formatters/base.rb @@ -21,6 +21,7 @@ require 'chef/event_dispatch/base' require 'chef/formatters/error_inspectors' require 'chef/formatters/error_descriptor' require 'chef/formatters/error_mapper' +require 'chef/formatters/indentable_output_stream' class Chef @@ -56,91 +57,6 @@ class Chef formatter_class.new(out, err) end - # == Outputter - # Handles basic printing tasks like colorizing. - # -- - # TODO: Duplicates functionality from knife, upfactor. - class Outputter - - attr_reader :out - attr_reader :err - attr_accessor :indent - attr_reader :line_started - - def initialize(out, err) - @out, @err = out, err - @indent = 0 - @line_started = false - end - - def highline - @highline ||= begin - require 'highline' - HighLine.new - end - end - - # Print text. This will start a new line and indent if necessary - # but will not terminate the line (future print and puts statements - # will start off where this print left off). - def color(string, *colors) - if !@line_started - @out.print ' ' * indent - @line_started = true - end - if string[-1..-1] == "\n" - @line_started = false - end - - if Chef::Config[:color] - @out.print highline.color(string, *colors) - else - @out.print string - end - end - - alias :print :color - - # Print a line. This will continue from the last start_line or print, - # or start a new line and indent if necessary. - def puts(string, *colors) - if !@line_started - @out.print ' ' * indent - end - - if Chef::Config[:color] - @out.puts highline.color(string, *colors) - else - @out.puts string - end - @line_started = false - end - - # Print an entire line from start to end. This will terminate any existing - # lines and cause indentation. - def puts_line(string, *colors) - if @line_started - @out.puts '' - @line_started = false - end - - puts(string, *colors) - end - - # Print the start of a new line. This will terminate any existing lines and - # cause indentation but will not move to the next line yet (future 'print' - # and 'puts' statements will stay on this line). - def start_line(string, *colors) - if @line_started - @out.puts '' - @line_started = false - end - print(string, *colors) - end - - end - - # == Formatters::Base # Base class that all formatters should inherit from. class Base < EventDispatch::Base @@ -156,7 +72,7 @@ class Chef attr_reader :output def initialize(out, err) - @output = Outputter.new(out, err) + @output = IndentableOutputStream.new(out, err) end def puts(*args) @@ -180,7 +96,7 @@ class Chef end # Input: a Formatters::ErrorDescription object. - # Outputs error to SDOUT. + # Outputs error to STDOUT. def display_error(description) puts("") description.display(output) @@ -303,4 +219,3 @@ class Chef end end - diff --git a/lib/chef/formatters/doc.rb b/lib/chef/formatters/doc.rb index 89ec59b813..4a08b9d095 100644 --- a/lib/chef/formatters/doc.rb +++ b/lib/chef/formatters/doc.rb @@ -166,7 +166,7 @@ class Chef indent end # TODO: info about notifies - start_line "* #{resource} action #{action}" + start_line "* #{resource} action #{action}", :stream => resource indent end @@ -183,7 +183,7 @@ class Chef # Called when a resource action has been skipped b/c of a conditional def resource_skipped(resource, action, conditional) # TODO: more info about conditional - puts " (skipped due to #{conditional.short_description})" + puts " (skipped due to #{conditional.short_description})", :stream => resource unindent end @@ -194,12 +194,12 @@ class Chef # Called when a resource has no converge actions, e.g., it was already correct. def resource_up_to_date(resource, action) @up_to_date_resources+= 1 - puts " (up to date)" + puts " (up to date)", :stream => resource unindent end def resource_bypassed(resource, action, provider) - puts " (Skipped: whyrun not supported by provider #{provider.class.name})" + puts " (Skipped: whyrun not supported by provider #{provider.class.name})", :stream => resource unindent end @@ -240,6 +240,10 @@ class Chef puts_line("* Whyrun not supported for #{resource}, bypassing load.", :yellow) end + def stream_output(stream, output, options = {}) + print(output, { :stream => stream }.merge(options)) + end + # Called before handlers run def handlers_start(handler_count) puts '' diff --git a/lib/chef/formatters/indentable_output_stream.rb b/lib/chef/formatters/indentable_output_stream.rb new file mode 100644 index 0000000000..1beb286e7f --- /dev/null +++ b/lib/chef/formatters/indentable_output_stream.rb @@ -0,0 +1,165 @@ +class Chef + module Formatters + # Handles basic indentation and colorization tasks + class IndentableOutputStream + + attr_reader :out + attr_reader :err + attr_accessor :indent + attr_reader :line_started + attr_accessor :current_stream + attr_reader :semaphore + + def initialize(out, err) + @out, @err = out, err + @indent = 0 + @line_started = false + @semaphore = Mutex.new + end + + def highline + @highline ||= begin + require 'highline' + HighLine.new + end + end + + # Print text. This will start a new line and indent if necessary + # but will not terminate the line (future print and puts statements + # will start off where this print left off). + def color(string, *args) + print(string, from_args(args)) + end + + # Print the start of a new line. This will terminate any existing lines and + # cause indentation but will not move to the next line yet (future 'print' + # and 'puts' statements will stay on this line). + def start_line(string, *args) + print(string, from_args(args, :start_line => true)) + end + + # Print a line. This will continue from the last start_line or print, + # or start a new line and indent if necessary. + def puts(string, *args) + print(string, from_args(args, :end_line => true)) + end + + # Print an entire line from start to end. This will terminate any existing + # lines and cause indentation. + def puts_line(string, *args) + print(string, from_args(args, :start_line => true, :end_line => true)) + end + + # Print a string. + # + # == Arguments + # string: string to print. + # options: a hash with these possible options: + # - :stream => OBJ: unique identifier for a stream. If two prints have + # different streams, they will print on separate lines. + # Otherwise, they will stay together. + # - :start_line => BOOLEAN: if true, print will begin on a blank (indented) line. + # - :end_line => BOOLEAN: if true, current line will be ended. + # - :name => STRING: a name to prefix in front of a stream. It will be printed + # once (with the first line of the stream) and subsequent lines + # will be indented to match. + # + # == Alternative + # + # You may also call print('string', :red) (a list of colors a la Highline.color) + def print(string, *args) + options = from_args(args) + + # Make sure each line stays a unit even with threads sending output + semaphore.synchronize do + if should_start_line?(options) + move_to_next_line + end + + print_string(string, options) + + if should_end_line?(options) + move_to_next_line + end + end + end + + private + + def should_start_line?(options) + options[:start_line] || @current_stream != options[:stream] + end + + def should_end_line?(options) + options[:end_line] && @line_started + end + + def from_args(colors, merge_options = {}) + if colors.size == 1 && colors[0].kind_of?(Hash) + merge_options.merge(colors[0]) + else + merge_options.merge({ :colors => colors }) + end + end + + def print_string(string, options) + if string.empty? + if options[:end_line] + print_line('', options) + end + else + string.lines.each do |line| + print_line(line, options) + end + end + end + + def print_line(line, options) + indent_line(options) + + # Note that the next line will need to be started + if line[-1..-1] == "\n" + @line_started = false + end + + if Chef::Config[:color] && options[:colors] + @out.print highline.color(line, *options[:colors]) + else + @out.print line + end + end + + def move_to_next_line + if @line_started + @out.puts '' + @line_started = false + end + end + + def indent_line(options) + if !@line_started + + # Print indents. If there is a stream name, either print it (if we're + # switching streams) or print enough blanks to match + # the indents. + if options[:name] + if @current_stream != options[:stream] + @out.print "#{(' ' * indent)}[#{options[:name]}] " + else + @out.print ' ' * (indent + 3 + options[:name].size) + end + else + # Otherwise, just print indents. + @out.print ' ' * indent + end + + if @current_stream != options[:stream] + @current_stream = options[:stream] + end + + @line_started = true + end + end + end + end +end diff --git a/lib/chef/knife/node_environment.rb b/lib/chef/knife/node_environment_set.rb index e1548bf566..da72aeaab8 100644 --- a/lib/chef/knife/node_environment.rb +++ b/lib/chef/knife/node_environment_set.rb @@ -20,13 +20,13 @@ require 'chef/knife' class Chef class Knife - class NodeEnvironment < Knife + class NodeEnvironmentSet < Knife deps do require 'chef/node' end - banner "knife node environment NODE ENVIRONMENT" + banner "knife node environment set NODE ENVIRONMENT" def run if @name_args.size < 2 diff --git a/lib/chef/resource/remote_file.rb b/lib/chef/resource/remote_file.rb index 24d2562a9b..6334b1bf44 100644 --- a/lib/chef/resource/remote_file.rb +++ b/lib/chef/resource/remote_file.rb @@ -40,13 +40,37 @@ class Chef @provider = Chef::Provider::RemoteFile end + # source can take any of the following as arguments + # - A single string argument + # - Multiple string arguments + # - An array or strings + # - A delayed evaluator that evaluates to a string + # or array of strings + # All strings must be parsable as URIs. + # source returns an array of strings. def source(*args) - if not args.empty? - args = Array(args).flatten - validate_source(args) - @source = args - elsif self.instance_variable_defined?(:@source) == true - @source + arg = parse_source_args(args) + ret = set_or_return(:source, + arg, + { :callbacks => { + :validate_source => method(:validate_source) + }}) + if ret.is_a? String + Array(ret) + else + ret + end + end + + def parse_source_args(args) + if args.empty? + nil + elsif args[0].is_a?(Chef::DelayedEvaluator) && args.count == 1 + args[0] + elsif args.any? {|a| a.is_a?(Chef::DelayedEvaluator)} && args.count > 1 + raise Exceptions::InvalidRemoteFileURI, "Only 1 source argument allowed when using a lazy evaluator" + else + Array(args).flatten end end @@ -107,6 +131,7 @@ class Chef private def validate_source(source) + source = Array(source).flatten raise ArgumentError, "#{resource_name} has an empty source" if source.empty? source.each do |src| unless absolute_uri?(src) @@ -114,6 +139,7 @@ class Chef "#{src.inspect} is not a valid `source` parameter for #{resource_name}. `source` must be an absolute URI or an array of URIs." end end + true end def absolute_uri?(source) diff --git a/lib/chef/run_context.rb b/lib/chef/run_context.rb index a102ef4692..3dd53f0f8f 100644 --- a/lib/chef/run_context.rb +++ b/lib/chef/run_context.rb @@ -24,6 +24,7 @@ require 'chef/role' require 'chef/log' require 'chef/recipe' require 'chef/run_context/cookbook_compiler' +require 'chef/event_dispatch/events_output_stream' class Chef @@ -249,6 +250,27 @@ ERROR_MESSAGE @cookbook_compiler.unreachable_cookbook?(cookbook_name) end + # Open a stream object that can be printed into and will dispatch to events + # + # == Arguments + # options is a hash with these possible options: + # - name: a string that identifies the stream to the user. Preferably short. + # + # Pass a block and the stream will be yielded to it, and close on its own + # at the end of the block. + def open_stream(options = {}) + stream = EventDispatch::EventsOutputStream.new(events, options) + if block_given? + begin + yield stream + ensure + stream.close + end + else + stream + end + end + private def loaded_recipe(cookbook, recipe) diff --git a/spec/integration/recipes/lwrp_inline_resources_spec.rb b/spec/integration/recipes/lwrp_inline_resources_spec.rb index dca5713ace..df666eaaa9 100644 --- a/spec/integration/recipes/lwrp_inline_resources_spec.rb +++ b/spec/integration/recipes/lwrp_inline_resources_spec.rb @@ -57,7 +57,8 @@ log_level :warn EOM result = shell_out("#{chef_client} -c \"#{path_to('config/client.rb')}\" --no-color -F doc -o 'x::default'", :cwd => chef_dir) - result.stdout.should include(<<EOM) + actual = result.stdout.lines.map { |l| l.chomp }.join("\n") + expected = <<EOM * x_my_machine[me] action create * x_do_nothing[a] action create (up to date) * x_do_nothing[b] action create (up to date) @@ -67,6 +68,8 @@ EOM * x_do_nothing[b] action create (up to date) (up to date) EOM + expected = expected.lines.map { |l| l.chomp }.join("\n") + actual.should include(expected) result.error! end end diff --git a/spec/support/shared/unit/api_error_inspector.rb b/spec/support/shared/unit/api_error_inspector.rb index b59fbce2c7..7577cb6c12 100644 --- a/spec/support/shared/unit/api_error_inspector.rb +++ b/spec/support/shared/unit/api_error_inspector.rb @@ -37,8 +37,8 @@ shared_examples_for "an api error inspector" do :client_key => "/etc/chef/client.pem" } @description = Chef::Formatters::ErrorDescription.new("Error registering the node:") - @outputter = Chef::Formatters::Outputter.new(StringIO.new, STDERR) - #@outputter = Chef::Formatters::Outputter.new(STDOUT, STDERR) + @outputter = Chef::Formatters::IndentableOutputStream.new(StringIO.new, STDERR) + #@outputter = Chef::Formatters::IndentableOutputStream.new(STDOUT, STDERR) end diff --git a/spec/unit/checksum/storage/filesystem_spec.rb b/spec/unit/checksum/storage/filesystem_spec.rb deleted file mode 100644 index 755a64fe07..0000000000 --- a/spec/unit/checksum/storage/filesystem_spec.rb +++ /dev/null @@ -1,70 +0,0 @@ -# -# Author:: Daniel DeLeo (<dan@opscode.com>) -# Copyright:: Copyright (c) 2010 Opscode, 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 'spec_helper' -require 'chef/checksum/storage/filesystem' - -describe Chef::Checksum::Storage::Filesystem do - - before do - Chef::Log.logger = Logger.new(StringIO.new) - - @now = Time.now - - Time.stub(:now).and_return(@now) - Chef::Config.stub(:checksum_path).and_return("/var/chef/checksums") - - @checksum_of_the_file = "3fafecfb15585ede6b840158cbc2f399" - @storage = Chef::Checksum::Storage::Filesystem.new("/not/used/path", @checksum_of_the_file) - end - - it "has the path to the file in the checksum repo" do - @storage.file_location.should == "/var/chef/checksums/3f/3fafecfb15585ede6b840158cbc2f399" - end - - it "has the path the file's subdirectory in the checksum repo" do - @storage.checksum_repo_directory.should == "/var/chef/checksums/3f" - end - - it "commits a file from a given location to the checksum repo location" do - File.should_receive(:rename).with("/tmp/arbitrary_file_location", @storage.file_location) - FileUtils.should_receive(:mkdir_p).with("/var/chef/checksums/3f") - - @storage.commit("/tmp/arbitrary_file_location") - end - - it "reverts committing a file" do - File.should_receive(:rename).with("/tmp/arbitrary_file_location", @storage.file_location) - FileUtils.should_receive(:mkdir_p).with("/var/chef/checksums/3f") - @storage.commit("/tmp/arbitrary_file_location") - - File.should_receive(:rename).with(@storage.file_location, "/tmp/arbitrary_file_location") - @storage.revert("/tmp/arbitrary_file_location") - end - - it "deletes the file" do - FileUtils.should_receive(:rm).with(@storage.file_location) - @storage.purge - end - - it "successfully purges even if its file has been deleted from the repo" do - FileUtils.should_receive(:rm).with(@storage.file_location).and_raise(Errno::ENOENT) - lambda {@storage.purge}.should_not raise_error - end - -end diff --git a/spec/unit/formatters/error_inspectors/compile_error_inspector_spec.rb b/spec/unit/formatters/error_inspectors/compile_error_inspector_spec.rb index bea7eeed21..95911689e4 100644 --- a/spec/unit/formatters/error_inspectors/compile_error_inspector_spec.rb +++ b/spec/unit/formatters/error_inspectors/compile_error_inspector_spec.rb @@ -42,8 +42,8 @@ describe Chef::Formatters::ErrorInspectors::CompileErrorInspector do @description = Chef::Formatters::ErrorDescription.new("Error Evaluating File:") @exception = NoMethodError.new("undefined method `this_is_not_a_valid_method' for Chef::Resource::File") - @outputter = Chef::Formatters::Outputter.new(StringIO.new, STDERR) - #@outputter = Chef::Formatters::Outputter.new(STDOUT, STDERR) + @outputter = Chef::Formatters::IndentableOutputStream.new(StringIO.new, STDERR) + #@outputter = Chef::Formatters::IndentableOutputStream.new(STDOUT, STDERR) end describe "when scrubbing backtraces" do diff --git a/spec/unit/formatters/error_inspectors/cookbook_resolve_error_inspector_spec.rb b/spec/unit/formatters/error_inspectors/cookbook_resolve_error_inspector_spec.rb index c573dc016b..06d45472e4 100644 --- a/spec/unit/formatters/error_inspectors/cookbook_resolve_error_inspector_spec.rb +++ b/spec/unit/formatters/error_inspectors/cookbook_resolve_error_inspector_spec.rb @@ -25,8 +25,8 @@ describe Chef::Formatters::ErrorInspectors::CookbookResolveErrorInspector do @description = Chef::Formatters::ErrorDescription.new("Error Resolving Cookbooks for Run List:") @outputter_output = StringIO.new - @outputter = Chef::Formatters::Outputter.new(@outputter_output, STDERR) - # @outputter = Chef::Formatters::Outputter.new(STDOUT, STDERR) + @outputter = Chef::Formatters::IndentableOutputStream.new(@outputter_output, STDERR) + # @outputter = Chef::Formatters::IndentableOutputStream.new(STDOUT, STDERR) end describe "when explaining a 403 error" do diff --git a/spec/unit/formatters/error_inspectors/cookbook_sync_error_inspector_spec.rb b/spec/unit/formatters/error_inspectors/cookbook_sync_error_inspector_spec.rb index e586f5e3b3..87c3708ef1 100644 --- a/spec/unit/formatters/error_inspectors/cookbook_sync_error_inspector_spec.rb +++ b/spec/unit/formatters/error_inspectors/cookbook_sync_error_inspector_spec.rb @@ -21,8 +21,8 @@ require 'spec_helper' describe Chef::Formatters::ErrorInspectors::CookbookSyncErrorInspector do before do @description = Chef::Formatters::ErrorDescription.new("Error Expanding RunList:") - @outputter = Chef::Formatters::Outputter.new(StringIO.new, STDERR) - #@outputter = Chef::Formatters::Outputter.new(STDOUT, STDERR) + @outputter = Chef::Formatters::IndentableOutputStream.new(StringIO.new, STDERR) + #@outputter = Chef::Formatters::IndentableOutputStream.new(STDOUT, STDERR) end describe "when explaining a 502 error" do diff --git a/spec/unit/formatters/error_inspectors/resource_failure_inspector_spec.rb b/spec/unit/formatters/error_inspectors/resource_failure_inspector_spec.rb index 8cafbcc9d6..6691553ddd 100644 --- a/spec/unit/formatters/error_inspectors/resource_failure_inspector_spec.rb +++ b/spec/unit/formatters/error_inspectors/resource_failure_inspector_spec.rb @@ -39,8 +39,8 @@ describe Chef::Formatters::ErrorInspectors::ResourceFailureInspector do before do @description = Chef::Formatters::ErrorDescription.new("Error Converging Resource:") @stdout = StringIO.new - @outputter = Chef::Formatters::Outputter.new(@stdout, STDERR) - #@outputter = Chef::Formatters::Outputter.new(STDOUT, STDERR) + @outputter = Chef::Formatters::IndentableOutputStream.new(@stdout, STDERR) + #@outputter = Chef::Formatters::IndentableOutputStream.new(STDOUT, STDERR) Chef::Config.stub(:cookbook_path).and_return([ "/var/chef/cache" ]) end diff --git a/spec/unit/formatters/error_inspectors/run_list_expansion_error_inspector_spec.rb b/spec/unit/formatters/error_inspectors/run_list_expansion_error_inspector_spec.rb index 56a6eceec3..7f68c4fba4 100644 --- a/spec/unit/formatters/error_inspectors/run_list_expansion_error_inspector_spec.rb +++ b/spec/unit/formatters/error_inspectors/run_list_expansion_error_inspector_spec.rb @@ -26,8 +26,8 @@ describe Chef::Formatters::ErrorInspectors::RunListExpansionErrorInspector do end @description = Chef::Formatters::ErrorDescription.new("Error Expanding RunList:") - @outputter = Chef::Formatters::Outputter.new(StringIO.new, STDERR) - #@outputter = Chef::Formatters::Outputter.new(STDOUT, STDERR) + @outputter = Chef::Formatters::IndentableOutputStream.new(StringIO.new, STDERR) + #@outputter = Chef::Formatters::IndentableOutputStream.new(STDOUT, STDERR) end describe "when explaining a missing role error" do diff --git a/spec/unit/knife/node_environment_spec.rb b/spec/unit/knife/node_environment_set_spec.rb index dc7599e6cb..46ee1fea18 100644 --- a/spec/unit/knife/node_environment_spec.rb +++ b/spec/unit/knife/node_environment_set_spec.rb @@ -18,10 +18,10 @@ require 'spec_helper' -describe Chef::Knife::NodeEnvironment do +describe Chef::Knife::NodeEnvironmentSet do before(:each) do Chef::Config[:node_name] = "webmonkey.example.com" - @knife = Chef::Knife::NodeEnvironment.new + @knife = Chef::Knife::NodeEnvironmentSet.new @knife.name_args = [ "adam", "bar" ] @knife.stub(:output).and_return(true) @node = Chef::Node.new() @@ -72,7 +72,7 @@ describe Chef::Knife::NodeEnvironment do begin ; @knife.run ; rescue SystemExit ; end - @stdout.string.should eq "USAGE: knife node environment NODE ENVIRONMENT\n" + @stdout.string.should eq "USAGE: knife node environment set NODE ENVIRONMENT\n" @stderr.string.should eq "FATAL: You must specify a node name and an environment.\n" end end diff --git a/spec/unit/resource/remote_file_spec.rb b/spec/unit/resource/remote_file_spec.rb index 643bc8ba21..8f1633119d 100644 --- a/spec/unit/resource/remote_file_spec.rb +++ b/spec/unit/resource/remote_file_spec.rb @@ -50,20 +50,49 @@ describe Chef::Resource::RemoteFile do @resource.source.should eql([ "http://opscode.com/" ]) end + it "should accept a delayed evalutator (string) for the remote file source" do + @resource.source Chef::DelayedEvaluator.new {"http://opscode.com/"} + @resource.source.should eql([ "http://opscode.com/" ]) + end + it "should accept an array of URIs for the remote file source" do @resource.source([ "http://opscode.com/", "http://puppetlabs.com/" ]) @resource.source.should eql([ "http://opscode.com/", "http://puppetlabs.com/" ]) end + it "should accept a delated evaluator (array) for the remote file source" do + @resource.source Chef::DelayedEvaluator.new { [ "http://opscode.com/", "http://puppetlabs.com/" ] } + @resource.source.should eql([ "http://opscode.com/", "http://puppetlabs.com/" ]) + end + it "should accept an multiple URIs as arguments for the remote file source" do @resource.source("http://opscode.com/", "http://puppetlabs.com/") @resource.source.should eql([ "http://opscode.com/", "http://puppetlabs.com/" ]) end + it "should only accept a single argument if a delayed evalutor is used" do + lambda { + @resource.source("http://opscode.com/", Chef::DelayedEvaluator.new {"http://opscode.com/"}) + }.should raise_error(Chef::Exceptions::InvalidRemoteFileURI) + end + + it "should only accept a single array item if a delayed evalutor is used" do + lambda { + @resource.source(["http://opscode.com/", Chef::DelayedEvaluator.new {"http://opscode.com/"}]) + }.should raise_error(Chef::Exceptions::InvalidRemoteFileURI) + end + it "does not accept a non-URI as the source" do lambda { @resource.source("not-a-uri") }.should raise_error(Chef::Exceptions::InvalidRemoteFileURI) end + it "does not accept a non-URI as the source when read from a delayed evaluator" do + lambda { + @resource.source(Chef::DelayedEvaluator.new {"not-a-uri"}) + @resource.source + }.should raise_error(Chef::Exceptions::InvalidRemoteFileURI) + end + it "should raise an exception when source is an empty array" do lambda { @resource.source([]) }.should raise_error(ArgumentError) end diff --git a/spec/unit/resource_spec.rb b/spec/unit/resource_spec.rb index 60f3bdb8ea..82ffdeba98 100644 --- a/spec/unit/resource_spec.rb +++ b/spec/unit/resource_spec.rb @@ -612,7 +612,7 @@ describe Chef::Resource do it "should print \"skipped due to action :nothing\" message for doc formatter when action is :nothing" do fdoc = Chef::Formatters.new(:doc, STDOUT, STDERR) @run_context.stub(:events).and_return(fdoc) - fdoc.should_receive(:puts).with(" (skipped due to action :nothing)") + fdoc.should_receive(:puts).with(" (skipped due to action :nothing)", anything()) @resource.should_skip?(:nothing) end |