lib/chef/knife/solo_cook.rb in knife-solo-0.3.0.pre2 vs lib/chef/knife/solo_cook.rb in knife-solo-0.3.0.pre3
- old
+ new
@@ -2,11 +2,10 @@
require 'knife-solo'
require 'knife-solo/ssh_command'
require 'knife-solo/node_config_command'
require 'knife-solo/tools'
-require 'knife-solo/config'
class Chef
class Knife
# Approach ported from spatula (https://github.com/trotter/spatula)
# Copyright 2009, Trotter Cashion
@@ -17,13 +16,13 @@
include KnifeSolo::NodeConfigCommand
include KnifeSolo::Tools
deps do
require 'chef/cookbook/chefignore'
- require 'librarian/action'
- require 'librarian/chef'
+ require 'erubis'
require 'pathname'
+ require 'tempfile'
KnifeSolo::SshCommand.load_deps
KnifeSolo::NodeConfigCommand.load_deps
end
banner "knife solo cook [USER@]HOSTNAME [JSON] (options)"
@@ -41,12 +40,11 @@
:long => '--sync-only',
:description => 'Only sync the cookbook - do not run Chef'
option :librarian,
:long => '--no-librarian',
- :description => 'Skip librarian-chef install',
- :default => true
+ :description => 'Skip librarian-chef install'
option :why_run,
:short => '-W',
:long => '--why-run',
:description => 'Enable whyrun mode'
@@ -54,40 +52,82 @@
option :override_runlist,
:short => '-o RunlistItem,RunlistItem...,',
:long => '--override-runlist',
:description => 'Replace current run list with specified items'
- def run
- @solo_config = KnifeSolo::Config.new
+ option :provisioning_path,
+ :long => '--provisioning-path path',
+ :description => 'Where to store kitchen data on the node'
+ def run
time('Run') do
+
if config[:skip_chef_check]
ui.warn '`--skip-chef-check` is deprecated, please use `--no-chef-check`.'
config[:chef_check] = false
end
validate!
+
+ ui.msg "Running Chef on #{host}..."
+
check_chef_version if config[:chef_check]
generate_node_config
- librarian_install if config[:librarian]
- rsync_kitchen
- add_patches
- add_solo_config unless using_custom_solorb?
+ librarian_install if config_value(:librarian, true)
+ sync_kitchen
+ generate_solorb
cook unless config[:sync_only]
end
end
- def_delegators :@solo_config,
- :chef_path,
- :using_custom_solorb?,
- :patch_path
-
def validate!
validate_ssh_options!
- @solo_config.validate!
+
+ if File.exist? 'solo.rb'
+ ui.warn "solo.rb found, but since knife-solo v0.3.0 it is not used any more"
+ ui.warn "Please read the upgrade instructions: https://github.com/matschaffer/knife-solo/wiki/Upgrading-to-0.3.0"
+ end
end
+ def provisioning_path
+ # TODO ~ will likely break on cmd.exe based windows sessions
+ config_value(:provisioning_path, '~/chef-solo')
+ end
+
+ def sync_kitchen
+ ui.msg "Uploading the kitchen..."
+ run_portable_mkdir_p(provisioning_path, '0700')
+
+ cookbook_paths.each_with_index do |path, i|
+ upload_to_provision_path(path, "/cookbooks-#{i + 1}", 'cookbook_path')
+ end
+ upload_to_provision_path(nodes_path, 'nodes')
+ upload_to_provision_path(:role_path, 'roles')
+ upload_to_provision_path(:data_bag_path, 'data_bags')
+ upload_to_provision_path(:encrypted_data_bag_secret, 'data_bag_key')
+ end
+
+ def expanded_config_paths(key)
+ Array(Chef::Config[key]).map { |path| Pathname.new(path).expand_path }
+ end
+
+ def cookbook_paths
+ @cookbook_paths ||= expanded_config_paths(:cookbook_path) + [patch_cookbooks_path]
+ end
+
+ def add_cookbook_path(path)
+ cookbook_paths.unshift(path) unless cookbook_paths.include?(path)
+ end
+
+ def patch_cookbooks_path
+ KnifeSolo.resource('patch_cookbooks')
+ end
+
+ def nodes_path
+ 'nodes'
+ end
+
def chefignore
@chefignore ||= ::Chef::Cookbook::Chefignore.new("./")
end
# cygwin rsync path must be adjusted to work
@@ -110,11 +150,11 @@
def rsync_permissions
'--chmod=ugo=rwX' if windows_client?
end
def rsync_excludes
- (%w{revision-deploys tmp '.*'} + chefignore.ignores).uniq
+ (%w{revision-deploys tmp .git .hg .svn .bzr} + chefignore.ignores).uniq
end
def debug?
config[:verbosity] and config[:verbosity] > 0
end
@@ -127,40 +167,74 @@
yield
ui.msg "#{msg} finished in #{Time.now - start} seconds"
end
def librarian_install
- return unless File.exist? 'Cheffile'
- Chef::Log.debug("Installing Librarian cookbooks")
- Librarian::Action::Resolve.new(librarian_env).run
- Librarian::Action::Install.new(librarian_env).run
+ if !File.exist? 'Cheffile'
+ Chef::Log.debug "Cheffile not found"
+ elsif !load_librarian
+ ui.warn "Librarian-Chef could not be loaded"
+ ui.warn "Please add the librarian-chef gem to your Gemfile or install it manually with `gem install librarian-chef`"
+ else
+ ui.msg "Installing Librarian cookbooks..."
+ Librarian::Action::Resolve.new(librarian_env).run
+ Librarian::Action::Install.new(librarian_env).run
+ add_cookbook_path librarian_env.install_path
+ end
end
+ def load_librarian
+ begin
+ require 'librarian/action'
+ require 'librarian/chef'
+ rescue LoadError
+ false
+ else
+ true
+ end
+ end
+
def librarian_env
@librarian_env ||= Librarian::Chef::Environment.new
end
- def rsync_kitchen
- time('Rsync kitchen') do
- rsync('./', chef_path, '--delete')
- end
+ def generate_solorb
+ ui.msg "Generating solo config..."
+ template = Erubis::Eruby.new(KnifeSolo.resource('solo.rb.erb').read)
+ write(template.result(binding), provisioning_path + '/solo.rb')
end
- def add_patches
- run_portable_mkdir_p(patch_path)
- Dir[Pathname.new(__FILE__).dirname.join("patches", "*.rb").to_s].each do |patch|
- time(patch) do
- rsync(patch, patch_path)
- end
+ def upload(src, dest)
+ rsync(src, dest)
+ end
+
+ def upload_to_provision_path(src, dest, key_name = 'path')
+ if src.is_a? Symbol
+ key_name = src.to_s
+ src = Chef::Config[src]
end
+
+ if src.nil?
+ Chef::Log.debug "'#{key_name}' not set"
+ elsif !File.exist?(src)
+ ui.warn "Local #{key_name} '#{src}' does not exist"
+ else
+ upload("#{src}#{'/' if File.directory?(src)}", File.join(provisioning_path, dest))
+ end
end
- def add_solo_config
- rsync(KnifeSolo.resource('solo.rb'), chef_path)
+ # TODO probably can get Net::SSH to do this directly
+ def write(content, dest)
+ file = Tempfile.new(File.basename(dest))
+ file.write(content)
+ file.close
+ upload(file.path, dest)
+ ensure
+ file.unlink
end
- def rsync(source_path, target_path, extra_opts = '')
+ def rsync(source_path, target_path, extra_opts = '--delete')
cmd = %Q{rsync -rl #{rsync_permissions} --rsh="ssh #{ssh_args}" #{extra_opts} #{rsync_excludes.collect{ |ignore| "--exclude #{ignore} " }.join} #{adjust_rsync_path_on_client(source_path)} :#{adjust_rsync_path_on_node(target_path)}}
ui.msg cmd if debug?
system! cmd
end
@@ -176,10 +250,11 @@
v = run_command('sudo chef-solo --version').stdout.split(':')
v[0].strip == 'Chef' ? v[1].strip : ''
end
def cook
- cmd = "sudo chef-solo -c #{chef_path}/solo.rb -j #{chef_path}/#{node_config}"
+ ui.msg "Running Chef..."
+ cmd = "sudo chef-solo -c #{provisioning_path}/solo.rb -j #{provisioning_path}/#{node_config}"
cmd << " -l debug" if debug?
cmd << " -N #{config[:chef_node_name]}" if config[:chef_node_name]
cmd << " -W" if config[:why_run]
cmd << " -o #{config[:override_runlist]}" if config[:override_runlist]