forked from matschaffer/knife-solo
/
cook.rb
120 lines (100 loc) · 3.41 KB
/
cook.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
require 'pathname'
require 'chef/knife'
require 'chef/config'
require 'knife-solo/ssh_command'
require 'knife-solo/kitchen_command'
class Chef
class Knife
# Approach ported from spatula (https://github.com/trotter/spatula)
# Copyright 2009, Trotter Cashion
class Cook < Knife
include KnifeSolo::SshCommand
include KnifeSolo::KitchenCommand
banner "knife cook [user@]hostname [json] (options)"
option :skip_chef_check,
:long => '--skip-chef-check',
:boolean => true,
:description => "Skip the version check on the Chef gem"
option :windows_compat,
:long => '--windows-compat',
:description => 'Windows compatibility mode (enable, disable, auto)',
:default => 'auto'
def run
super
check_syntax
Chef::Config.from_file('solo.rb')
check_chef_version unless config[:skip_chef_check]
rsync_kitchen
add_patches
cook
end
# todo - move this to SshCommand?
def is_windows_node?
run_command("ver").stdout =~ /Windows/i
end
def windows_compat?
# TODO - use a cleaner construct (proper option with choices?)
@windows_compat ||= case config[:windows_compat]
when 'enable'; true
when 'disable'; false
when 'auto'; is_windows_node?
else raise "Unsupported windows compatiblity mode"
end
end
def check_syntax
ui.msg('Checking cookbook syntax...')
Dir["**/*.rb"].each do |recipe|
ok = system "ruby -c #{recipe} >/dev/null 2>&1"
raise "Syntax error in #{recipe}" if not ok
end
Dir["**/*.json"].each do |json|
begin
require 'json'
# parse without instantiating Chef classes
JSON.parse File.read(json), :create_additions => false
rescue => error
raise "Syntax error in #{json}: #{error.message}"
end
end
end
def node_config
@name_args[1] || super
end
def chef_path
Chef::Config.file_cache_path
end
# cygwin rsync path must be adjusted to work
def adjust_rsync_path(path)
return path unless windows_compat?
path.gsub(/^(\w):/) { "/cygdrive/#{$1}" }
end
def patch_path
Array(Chef::Config.cookbook_path).first + "/chef_solo_patches/libraries"
end
def rsync_kitchen
system %Q{rsync -rlP --rsh="ssh #{ssh_args}" --delete --exclude '.*' ./ :#{adjust_rsync_path(chef_path)}}
end
def add_patches
run_portable_mkdir_p(patch_path)
Dir[Pathname.new(__FILE__).dirname.join("patches", "*.rb")].each do |patch|
system %Q{rsync -rlP --rsh="ssh #{ssh_args}" #{patch} :#{adjust_rsync_path(patch_path)}}
end
end
def check_chef_version
constraint = "~>0.10.4"
result = run_command <<-BASH
ruby -rubygems -e "gem 'chef', '#{constraint}'"
BASH
raise "The chef gem on #{host} is out of date. Please run `#{$0} prepare #{ssh_args}` to upgrade Chef to #{constraint}." unless result.success?
end
def cook
logging_arg = "-l debug" if config[:verbosity] > 0
stream_command <<-BASH
chef-solo -c #{chef_path}/solo.rb \
-j #{chef_path}/#{node_config} \
#{logging_arg}
BASH
end
end
end
end