Skip to content
This repository has been archived by the owner on Jan 15, 2024. It is now read-only.

Commit

Permalink
Release v2.1.0
Browse files Browse the repository at this point in the history
- Added `--sandbox` option (#24)
- Added automatic logging and logfile
- Added support for Windows output (since it can't handle colors)
- Moved sandbox out of gem directory
- Converted UI to a module instead of subclass of Thor
  • Loading branch information
sethvargo committed May 29, 2013
1 parent c8e3583 commit 5bf5a0f
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 33 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
Strainer CHANGELOG
==================
v2.1.0
------
- Added `--sandbox` option (#24)
- Added automatic logging and logfile
- Added support for Windows output (since it can't handle colors)
- Moved sandbox out of gem directory
- Converted UI to a module instead of subclass of Thor

v2.0.1
------
Expand Down
56 changes: 48 additions & 8 deletions lib/strainer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,41 +5,81 @@
require 'thor'

require 'strainer/errors'
require 'strainer/ui'

module Strainer
autoload :Cli, 'strainer/cli'
autoload :Command, 'strainer/command'
autoload :Logger, 'strainer/logger'
autoload :Runner, 'strainer/runner'
autoload :Sandbox, 'strainer/sandbox'
autoload :Strainerfile, 'strainer/strainerfile'
autoload :UI, 'strainer/ui'
autoload :Version, 'strainer/version'

class << self
# The root of the application
# The root of the application.
#
# @return [Pathname]
# the path to the root of Strainer
def root
@root ||= Pathname.new(File.expand_path('../../', __FILE__))
end

# The UI instance
# The UI instance.
#
# @return [Strainer::UI]
# an instance of the strainer UI
def ui
@ui ||= Strainer::UI.new
@ui ||= Thor::Base.shell.new
end

# Helper method to access a constant defined in Strainer::Sandbox that
# specifies the location of the sandbox
# Get the file logger for Strainer.
#
# The logger writes to a temporary file and then copies itself back
# into the sandbox directory after the run. This is because Strainer
# clears the sandbox and would delete the logfile after some
# important debugging information was printed.
#
# @return [Logger]
# the file logger
def log
@logger ||= begin
log = Logger.new(logfile_path)
log.level = Logger::DEBUG
log
end
end

# The path to the Strainer sandbox. Defaults to a temporary
# directory on the local file system.
#
# @return [Pathname]
# the path to the sandbox
def sandbox_path
Strainer::Sandbox::SANDBOX
@sandbox_path ||= Pathname.new(Dir.mktmpdir)
end

# Set Strainer's sandbox path, ensuring the given path exists.
#
# @param [#to_s] path
# the path to set
#
# @return [Pathname]
# the path to the Strainer sandbox
def sandbox_path=(path)
path = File.expand_path(path.to_s)

# Make the directory unless it already exists
FileUtils.mkdir_p(path) unless File.exists?(path)

@sandbox_path = Pathname.new(path.to_s)
end

# The path to the temporary logfile for the strain.
#
# @return [Pathname]
# the path to the log file
def logfile_path
@logfile_path ||= Pathname.new(File.join(Dir.mktmpdir, 'strainer.out'))
end
end
end
Expand Down
7 changes: 4 additions & 3 deletions lib/strainer/cli.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
require 'strainer'

module Strainer
# Use our own custom shell
Thor::Base.shell = Strainer::UI

# Cli runner for Strainer
#
# @author Seth Vargo <sethvargo@gmail.com>
Expand All @@ -27,6 +24,9 @@ def initialize(*args)
# Override the config file if it's specified
Berkshelf::Chef::Config.path = @options[:config] if @options[:config]

# Set the Strainer path if it's specified
Strainer.sandbox_path = @options[:sandbox] if @options[:sandbox]

# Unfreeze the options Hash from Thor
@options = options.dup

Expand All @@ -39,6 +39,7 @@ def initialize(*args)
class_option :cookbooks_path, :type => :string, :aliases => '-p', :desc => 'The path to the cookbook store', :banner => 'PATH'
class_option :config, :type => :string, :aliases => '-c', :desc => 'The path to the knife.rb/client.rb config'
class_option :strainer_file, :type => :string, :aliases => '-s', :desc => 'The path to the Strainer file to run against', :banner => 'FILE', :default => Strainer::Strainerfile::DEFAULT_FILENAME
class_option :sandbox, :type => :string, :aliases => '-s', :desc => 'The sandbox path (defaults to a temporary directory)', :defaut => Dir.mktmpdir
class_option :debug, :type => :boolean, :aliases => '-d', :desc => 'Show debugging log output', :default => false

# strainer test *COOKBOOKS
Expand Down
3 changes: 3 additions & 0 deletions lib/strainer/runner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ def run!
end
end

# Move the logfile back over
FileUtils.mv(Strainer.logfile_path, Strainer.sandbox_path.join('strainer.out'))

abort unless @report.values.collect(&:values).flatten.all?
end

Expand Down
39 changes: 21 additions & 18 deletions lib/strainer/sandbox.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class Sandbox
# @param [Hash] options
# a list of options to pass along
def initialize(cookbook_names, options = {})
@options = options
@options = options

if chef_repo?
@cookbooks = load_cookbooks(cookbook_names)
Expand All @@ -32,7 +32,6 @@ def initialize(cookbook_names, options = {})
end

reset_sandbox
copy_cookbooks
end

private
Expand All @@ -45,20 +44,24 @@ def reset_sandbox

# Destroy the current sandbox, if it exists
def destroy_sandbox
if File.directory?(SANDBOX)
Strainer.ui.debug " Destroying sandbox at '#{SANDBOX}'"
FileUtils.rm_rf(SANDBOX)
if File.directory?(Strainer.sandbox_path)
Strainer.ui.debug " Destroying sandbox at '#{Strainer.sandbox_path}'"
FileUtils.rm_rf(Strainer.sandbox_path)
else
Strainer.ui.debug " Sandbox does not exist... skipping"
end
end

# Create the sandbox unless it already exits
def create_sandbox
unless File.directory?(SANDBOX)
Strainer.ui.debug " Creating sandbox at '#{SANDBOX}'"
FileUtils.mkdir_p(SANDBOX)
copy_globals
place_knife_rb
unless File.directory?(Strainer.sandbox_path)
Strainer.ui.debug " Creating sandbox at '#{Strainer.sandbox_path}'"
FileUtils.mkdir_p(Strainer.sandbox_path)
end

copy_globals
place_knife_rb
copy_cookbooks
end

# Copy over a whitelist of common files into our sandbox
Expand All @@ -71,13 +74,13 @@ def copy_globals
files = []
end

Strainer.ui.debug "Copying '#{files}' to '#{SANDBOX}'"
FileUtils.cp_r(files, SANDBOX)
Strainer.ui.debug "Copying '#{files}' to '#{Strainer.sandbox_path}'"
FileUtils.cp_r(files, Strainer.sandbox_path)
end

# Create a basic knife.rb file to ensure tests run successfully
def place_knife_rb
chef_path = SANDBOX.join('.chef')
chef_path = Strainer.sandbox_path.join('.chef')

Strainer.ui.debug "Creating directory '#{chef_path}'"
FileUtils.mkdir_p(chef_path)
Expand All @@ -86,7 +89,7 @@ def place_knife_rb
contents = <<-EOH
cache_type 'BasicFile'
cache_options(:path => "\#{ENV['HOME']}/.chef/checksums")
cookbook_path '#{SANDBOX}'
cookbook_path '#{Strainer.sandbox_path}'
EOH

# Create knife.rb
Expand All @@ -98,14 +101,14 @@ def place_knife_rb
def copy_cookbooks
Strainer.ui.debug "Sandbox#copy_cookbooks"
cookbooks_and_dependencies.each do |cookbook|
sandbox_path = SANDBOX.join(cookbook.cookbook_name)
cookbook_sandbox = Strainer.sandbox_path.join(cookbook.cookbook_name)

# Copy the files to our sandbox
Strainer.ui.debug "Copying '#{cookbook.name}' to '#{sandbox_path}'"
FileUtils.cp_r(cookbook.path, sandbox_path)
Strainer.ui.debug "Copying '#{cookbook.name}' to '#{cookbook_sandbox}'"
FileUtils.cp_r(cookbook.path, cookbook_sandbox)

# Override the @path location so we don't need to create a new object
cookbook.path = sandbox_path
cookbook.path = cookbook_sandbox
end
end

Expand Down
27 changes: 24 additions & 3 deletions lib/strainer/ui.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
require 'thor'

module Strainer
# Extend Thor::Shell::Color to provide nice helpers for outputting
# to the console.
#
# This module will also force UI calls to log to the output file.
#
# @author Seth Vargo <sethvargo@gmail.com>
class UI < ::Thor::Shell::Color
module UI
# Print the given message to STDOUT.
#
# @param [String]
Expand All @@ -13,10 +17,20 @@ class UI < ::Thor::Shell::Color
# @param [Boolean] new_line
# include a new_line character
def say(message = '', color = nil, new_line = nil)
Strainer.log.info(message.gsub(/\e\[\d+[;\d]*m/, ''))

return if quiet?
super(message, color)
end

# Print the given message to STDOUT.
# @see {say}
def info(message = '', color = nil, new_line = nil)
Strainer.log.info(message.gsub(/\e\[\d+[;\d]*m/, ''))

return if quiet?
super(message, color)
end
alias_method :info, :say

# Print the given message to STDOUT.
#
Expand All @@ -27,6 +41,8 @@ def say(message = '', color = nil, new_line = nil)
# @param [Boolean] log_status
# whether to log the status
def say_status(status, message, log_status = true)
Strainer.log.info("status: #{status}, message: #{message}")

return if quiet?
super(status, message, log_status)
end
Expand Down Expand Up @@ -69,6 +85,8 @@ def warn(message, color = :yellow)
# @param [Symbol] color
# the color to use
def error(message, color = :red)
Strainer.log.error(message)

return if quiet?
message = set_color(message, *color) if color
super(message)
Expand All @@ -88,7 +106,10 @@ def debug(message)
# the message to print
def deprecated(message)
return if quiet?
error('[DEPRECATION] ' + message)
warn('[DEPRECATION] ' + message)
end
end
end

# Include this module in Thor's shell
Thor::Base.shell.send(:include, Strainer::UI)
2 changes: 1 addition & 1 deletion lib/strainer/version.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module Strainer
# The current version of Strainer
VERSION = '2.0.2'
VERSION = '2.1.0'
end

0 comments on commit 5bf5a0f

Please sign in to comment.