Skip to content

Commit

Permalink
Mix Configurable into Busser to use default_config.
Browse files Browse the repository at this point in the history
Now Busser uses the same intialization as Drivers, Provisioners, and
Transports (using `#finalize_config!`). The suite_name is now provided
by asking `instance.suite.name`.
  • Loading branch information
fnichol committed Mar 15, 2015
1 parent a778878 commit bbc177a
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 118 deletions.
96 changes: 23 additions & 73 deletions lib/kitchen/busser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,62 +28,37 @@ module Kitchen
# @author Fletcher Nichol <[email protected]>
class Busser

# Constructs a new Busser command generator, given a suite name.
#
# @param [String] suite_name name of suite on which to operate
# (**Required**)
# @param [Hash] opts optional configuration
# @option opts [String] :kitchen_root local path to the root of the project
# @option opts [String] :instance_ruby_bindir path to the directory
# containing the Ruby binary on the remote instance
# @option opts [TrueClass, FalseClass] :sudo whether or not to invoke
# sudo before commands requiring root access (default: `true`)
def initialize(suite_name, opts = {})
validate_options(suite_name)

kitchen_root = opts.fetch(:kitchen_root) { Dir.pwd }
test_base_path = opts.fetch(:test_base_path, Kitchen::DEFAULT_TEST_DIR)

@config = Hash.new
@config[:kitchen_root] = kitchen_root
@config[:test_base_path] = File.expand_path(test_base_path, kitchen_root)
@config[:suite_name] = suite_name
@config[:sudo] = opts.fetch(:sudo, true)
@config[:ruby_bindir] = opts.fetch(:ruby_bindir, DEFAULT_RUBY_BINDIR)
@config[:root_path] = opts.fetch(:root_path, DEFAULT_ROOT_PATH)
@config[:version] = opts.fetch(:version, "busser")
@config[:busser_bin] = opts.fetch(:busser_bin, File.join(@config[:root_path], "bin/busser"))
end
include Configurable

# Returns the name of this busser, suitable for display in a CLI.
#
# @return [String] name of this busser
def name
config[:suite_name]
default_config :busser_bin do |busser|
File.join(busser[:root_path], %W[bin busser])
end

# Returns an array of configuration keys.
#
# @return [Array] array of configuration keys
def config_keys
config.keys
end
default_config :root_path, "/tmp/busser"

default_config :ruby_bindir, "/opt/chef/embedded/bin"

default_config :sudo, true

default_config(:suite_name) { |busser| busser.instance.suite.name }

default_config :version, "busser"

expand_path_for :test_base_path

# Provides hash-like access to configuration keys.
# Creates a new Busser object using the provided configuration data
# which will be merged with any default configuration.
#
# @param attr [Object] configuration key
# @return [Object] value at configuration key
def [](attr)
config[attr]
# @param config [Hash] provided driver configuration
def initialize(config = {})
init_config(config)
end

# Returns a Hash of configuration and other useful diagnostic information.
# Returns the name of this busser, suitable for display in a CLI.
#
# @return [Hash] a diagnostic hash
def diagnose
result = Hash.new
config_keys.sort.each { |k| result[k] = config[k] }
result
# @return [String] name of this busser
def name
config[:suite_name]
end

# Returns a command string which installs Busser, and installs all
Expand Down Expand Up @@ -162,31 +137,6 @@ def run_cmd

private

DEFAULT_RUBY_BINDIR = "/opt/chef/embedded/bin".freeze
DEFAULT_ROOT_PATH = "/tmp/busser".freeze

# @return [Hash] a configuration hash
# @api private
attr_reader :config

# Ensures that the object is internally consistent and otherwise raising
# an exception.
#
# @param suite_name [String] the suite name
# @raise [ClientError] if a suite name is missing
# @raise [UserError] if the suite name is invalid
# @api private
def validate_options(suite_name)
if suite_name.nil?
raise ClientError, "Busser#new requires a suite_name"
end

if suite_name == "helper"
raise UserError,
"Suite name invalid: 'helper' is a reserved directory name."
end
end

# Returns a uniquely sorted Array of Busser plugin gems that need to
# be installed for the related suite.
#
Expand Down
2 changes: 1 addition & 1 deletion lib/kitchen/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ def kitchen_config
# @api private
def new_busser(suite, platform)
bdata = data.busser_data_for(suite.name, platform.name)
Busser.new(suite.name, bdata)
Busser.new(bdata)
end

# Builds a newly configured Driver object, for a given Suite and Platform.
Expand Down
9 changes: 9 additions & 0 deletions lib/kitchen/instance.rb
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ def initialize(options = {})
setup_driver
setup_provisioner
setup_transport
setup_busser
end

# Returns a displayable representation of the instance.
Expand Down Expand Up @@ -272,6 +273,14 @@ def validate_options(options)
end
end

# Perform any final configuration or preparation needed for the busser
# object carry out its duties.
#
# @api private
def setup_busser
busser.finalize_config!(self)
end

# Perform any final configuration or preparation needed for the driver
# object carry out its duties.
#
Expand Down
64 changes: 23 additions & 41 deletions spec/kitchen/busser_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,55 +18,47 @@

require_relative "../spec_helper"

require "kitchen/busser"
# @TODO: this can be remove once Kitchen::DEFAULT_TEST_DIR is removed
require "kitchen"
require "kitchen/busser"

describe Kitchen::Busser do

let(:suite_name) { "germany" }
let(:config) { Hash.new }
let(:logged_output) { StringIO.new }
let(:logger) { Logger.new(logged_output) }
let(:config) { Hash.new }
let(:platform) { stub(:os_type => nil, :shell_type => nil) }
let(:suite) { stub(:name => "germany") }

let(:instance) do
stub(
:name => "coolbeans",
:logger => logger,
:platform => platform,
:suite => suite,
:to_str => "instance"
)
end

let(:busser) do
Kitchen::Busser.new(suite_name, config)
Kitchen::Busser.new(config).finalize_config!(instance)
end

describe ".new" do

it "raises a ClientError if a suite name is not provided" do
proc {
Kitchen::Busser.new(nil, config)
}.must_raise Kitchen::ClientError
end

it "raises a UserError if the suite name is 'helper'" do
proc {
Kitchen::Busser.new("helper", config)
}.must_raise Kitchen::UserError
end
# TODO: deal
# it "raises a UserError if the suite name is 'helper'" do
# proc {
# Kitchen::Busser.new("helper", config)
# }.must_raise Kitchen::UserError
# end
end

it "#name returns the name of the suite" do
busser.name.must_equal "germany"
end

it "#config_keys returns an array of config key names" do
busser.config_keys.sort.must_equal [
:busser_bin, :kitchen_root, :root_path, :ruby_bindir, :sudo,
:suite_name, :test_base_path, :version
]
end

describe "configuration" do

it ":kitchen_root defaults to current directory" do
busser[:kitchen_root].must_equal Dir.pwd
end

it ":test_base_path defaults to an expanded path" do
busser[:test_base_path].must_equal File.join(Dir.pwd, "test/integration")
end

it ":suite_name defaults to the passed in suite name" do
busser[:suite_name].must_equal "germany"
end
Expand Down Expand Up @@ -94,16 +86,6 @@
end
end

describe "#diagnose" do

it "returns a hash with sorted keys" do
busser.diagnose.keys.must_equal [
:busser_bin, :kitchen_root, :root_path, :ruby_bindir, :sudo,
:suite_name, :test_base_path, :version
]
end
end

describe "#setup_cmd" do

before do
Expand Down
2 changes: 1 addition & 1 deletion spec/kitchen/config_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ def read
it "constructs a Busser object" do
munger.expects(:busser_data_for).with("tiny", "unax").returns("datum")
Kitchen::Busser.unstub(:new)
Kitchen::Busser.expects(:new).with("tiny", "datum")
Kitchen::Busser.expects(:new).with("datum")

config.instances
end
Expand Down
9 changes: 7 additions & 2 deletions spec/kitchen/instance_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def converge(_)
let(:instance) { Kitchen::Instance.new(opts) }
let(:provisioner) { Kitchen::Provisioner::Dummy.new({}) }
let(:state_file) { DummyStateFile.new }
let(:busser) { Kitchen::Busser.new(suite.name, {}) }
let(:busser) { Kitchen::Busser.new({}) }
let(:transport) { Kitchen::Transport::Dummy.new({}) }

let(:opts) do
Expand Down Expand Up @@ -267,6 +267,11 @@ def platform(name = "platform")
opts.delete(:busser)
proc { Kitchen::Instance.new(opts) }.must_raise Kitchen::ClientError
end

it "sets Busser#instance to itself" do
# it's mind-bottling
instance.busser.instance.must_equal instance
end
end

describe "#state_file" do
Expand Down Expand Up @@ -360,7 +365,7 @@ def platform(name = "platform")
it "sets :busser key to :unknown if obj can't respond to #diagnose" do
opts[:busser] = Class.new(busser.class) {
undef_method :diagnose
}.new(suite.name, {})
}.new({})

instance.diagnose[:busser].must_equal :unknown
end
Expand Down

0 comments on commit bbc177a

Please sign in to comment.