knife-solo 0.0.14 → 0.0.15
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/chef/knife/cook.rb +34 -54
- data/lib/chef/knife/kitchen.rb +31 -6
- data/lib/chef/knife/prepare.rb +9 -14
- data/lib/chef/knife/wash_up.rb +1 -0
- data/lib/knife-solo/bootstraps.rb +11 -4
- data/lib/knife-solo/bootstraps/linux.rb +9 -4
- data/lib/knife-solo/info.rb +1 -1
- data/lib/knife-solo/kitchen_command.rb +1 -13
- data/lib/knife-solo/node_config_command.rb +40 -0
- data/lib/knife-solo/ssh_command.rb +29 -8
- metadata +3 -8
data/lib/chef/knife/cook.rb
CHANGED
@@ -1,11 +1,8 @@
|
|
1
|
-
require 'pathname'
|
2
|
-
|
3
1
|
require 'chef/knife'
|
4
|
-
require 'chef/config'
|
5
|
-
require 'chef/cookbook/chefignore'
|
6
2
|
|
7
3
|
require 'knife-solo/ssh_command'
|
8
4
|
require 'knife-solo/kitchen_command'
|
5
|
+
require 'knife-solo/node_config_command'
|
9
6
|
require 'knife-solo/tools'
|
10
7
|
|
11
8
|
class Chef
|
@@ -14,13 +11,20 @@ class Chef
|
|
14
11
|
# Copyright 2009, Trotter Cashion
|
15
12
|
class Cook < Knife
|
16
13
|
OMNIBUS_EMBEDDED_PATHS = ["/opt/chef/embedded/bin", "/opt/opscode/embedded/bin"]
|
14
|
+
OMNIBUS_EMBEDDED_GEM_PATHS = ["/opt/chef/embedded/lib/ruby/gems/1.9.1", "/opt/opscode/embedded/lib/ruby/gems/1.9.1"]
|
17
15
|
CHEF_VERSION_CONSTRAINT = ">=0.10.4"
|
18
16
|
|
19
17
|
include KnifeSolo::SshCommand
|
20
18
|
include KnifeSolo::KitchenCommand
|
19
|
+
include KnifeSolo::NodeConfigCommand
|
21
20
|
include KnifeSolo::Tools
|
22
21
|
|
23
|
-
|
22
|
+
deps do
|
23
|
+
require 'chef/cookbook/chefignore'
|
24
|
+
require 'pathname'
|
25
|
+
KnifeSolo::SshCommand.load_deps
|
26
|
+
KnifeSolo::NodeConfigCommand.load_deps
|
27
|
+
end
|
24
28
|
|
25
29
|
banner "knife cook [user@]hostname [json] (options)"
|
26
30
|
|
@@ -34,53 +38,25 @@ class Chef
|
|
34
38
|
:boolean => false,
|
35
39
|
:description => "Only sync the cookbook - do not run Chef"
|
36
40
|
|
37
|
-
option :
|
38
|
-
:
|
39
|
-
:
|
40
|
-
:
|
41
|
+
option :why_run,
|
42
|
+
:short => '-W',
|
43
|
+
:long => '--why-run',
|
44
|
+
:boolean => true,
|
45
|
+
:description => "Enable whyrun mode"
|
41
46
|
|
42
|
-
option :syntax_check_only,
|
43
|
-
:long => '--syntax-check-only',
|
44
|
-
:boolean => true,
|
45
|
-
:description => "Only run syntax checks - do not run Chef"
|
46
|
-
|
47
47
|
def run
|
48
48
|
time('Run') do
|
49
49
|
validate_params!
|
50
50
|
super
|
51
|
-
check_syntax unless config[:skip_syntax_check]
|
52
|
-
return if config[:syntax_check_only]
|
53
51
|
Chef::Config.from_file('solo.rb')
|
54
52
|
check_chef_version unless config[:skip_chef_check]
|
53
|
+
generate_node_config
|
55
54
|
rsync_kitchen
|
56
55
|
add_patches
|
57
56
|
cook unless config[:sync_only]
|
58
57
|
end
|
59
58
|
end
|
60
59
|
|
61
|
-
def check_syntax
|
62
|
-
ui.msg('Checking cookbook syntax...')
|
63
|
-
chefignore.remove_ignores_from(Dir["**/*.rb"]).each do |recipe|
|
64
|
-
ok = system "ruby -c #{recipe} >/dev/null 2>&1"
|
65
|
-
raise "Syntax error in #{recipe}" if not ok
|
66
|
-
end
|
67
|
-
|
68
|
-
chefignore.remove_ignores_from(Dir["**/*.json"]).each do |json|
|
69
|
-
begin
|
70
|
-
require 'json'
|
71
|
-
# parse without instantiating Chef classes
|
72
|
-
JSON.parse File.read(json), :create_additions => false
|
73
|
-
rescue => error
|
74
|
-
raise "Syntax error in #{json}: #{error.message}"
|
75
|
-
end
|
76
|
-
end
|
77
|
-
Chef::Log.info "cookbook and json syntax is ok"
|
78
|
-
end
|
79
|
-
|
80
|
-
def node_config
|
81
|
-
@name_args[1] || super
|
82
|
-
end
|
83
|
-
|
84
60
|
def chef_path
|
85
61
|
Chef::Config.file_cache_path
|
86
62
|
end
|
@@ -103,26 +79,30 @@ class Chef
|
|
103
79
|
(%w{revision-deploys tmp '.*'} + chefignore.ignores).uniq
|
104
80
|
end
|
105
81
|
|
82
|
+
def debug?
|
83
|
+
config[:verbosity] and config[:verbosity] > 0
|
84
|
+
end
|
85
|
+
|
106
86
|
# Time a command
|
107
87
|
def time(msg)
|
108
|
-
return yield
|
109
|
-
|
88
|
+
return yield unless debug?
|
89
|
+
ui.msg "Starting '#{msg}'"
|
110
90
|
start = Time.now
|
111
91
|
yield
|
112
|
-
|
92
|
+
ui.msg "#{msg} finished in #{Time.now - start} seconds"
|
113
93
|
end
|
114
94
|
|
115
95
|
def rsync_kitchen
|
116
96
|
time('Rsync kitchen') do
|
117
97
|
cmd = %Q{rsync -rl --rsh="ssh #{ssh_args}" --delete #{rsync_exclude.collect{ |ignore| "--exclude #{ignore} " }.join} ./ :#{adjust_rsync_path(chef_path)}}
|
118
|
-
|
98
|
+
ui.msg cmd if debug?
|
119
99
|
system! cmd
|
120
100
|
end
|
121
101
|
end
|
122
102
|
|
123
103
|
def add_patches
|
124
104
|
run_portable_mkdir_p(patch_path)
|
125
|
-
Dir[Pathname.new(__FILE__).dirname.join("patches", "*.rb")].each do |patch|
|
105
|
+
Dir[Pathname.new(__FILE__).dirname.join("patches", "*.rb").to_s].each do |patch|
|
126
106
|
time(patch) do
|
127
107
|
system! %Q{rsync -rl --rsh="ssh #{ssh_args}" #{patch} :#{adjust_rsync_path(patch_path)}}
|
128
108
|
end
|
@@ -130,28 +110,28 @@ class Chef
|
|
130
110
|
end
|
131
111
|
|
132
112
|
def check_chef_version
|
133
|
-
ui.msg
|
113
|
+
ui.msg "Checking Chef version..."
|
134
114
|
result = run_command <<-BASH
|
135
115
|
export PATH="#{OMNIBUS_EMBEDDED_PATHS.join(":")}:$PATH"
|
116
|
+
export GEM_PATH="#{OMNIBUS_EMBEDDED_GEM_PATHS.join(":")}:$GEM_PATH"
|
136
117
|
ruby -rubygems -e "gem 'chef', '#{CHEF_VERSION_CONSTRAINT}'"
|
137
118
|
BASH
|
138
119
|
raise "Couldn't find Chef #{CHEF_VERSION_CONSTRAINT} on #{host}. Please run `#{$0} prepare #{ssh_args}` to ensure Chef is installed and up to date." unless result.success?
|
139
120
|
end
|
140
|
-
|
121
|
+
|
141
122
|
def cook
|
142
|
-
|
123
|
+
cmd = "sudo chef-solo -c #{chef_path}/solo.rb -j #{chef_path}/#{node_config}"
|
124
|
+
cmd << " -l debug" if debug?
|
125
|
+
cmd << " -N #{config[:chef_node_name]}" if config[:chef_node_name]
|
126
|
+
cmd << " -W" if config[:why_run]
|
143
127
|
|
144
|
-
stream_command
|
145
|
-
sudo chef-solo -c #{chef_path}/solo.rb \
|
146
|
-
-j #{chef_path}/#{node_config} \
|
147
|
-
#{logging_arg}
|
148
|
-
BASH
|
128
|
+
stream_command cmd
|
149
129
|
end
|
150
130
|
|
151
131
|
def validate_params!
|
152
|
-
validate_first_cli_arg_is_a_hostname!
|
132
|
+
validate_first_cli_arg_is_a_hostname!
|
153
133
|
end
|
154
|
-
|
134
|
+
|
155
135
|
end
|
156
136
|
end
|
157
137
|
end
|
data/lib/chef/knife/kitchen.rb
CHANGED
@@ -5,16 +5,41 @@ class Chef
|
|
5
5
|
class Kitchen < Knife
|
6
6
|
include FileUtils
|
7
7
|
|
8
|
+
deps do
|
9
|
+
require 'knife-solo/knife_solo_error'
|
10
|
+
end
|
11
|
+
|
8
12
|
banner "knife kitchen NAME or initialize current directory with '.'"
|
9
13
|
|
10
14
|
def run
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
15
|
+
raise KnifeSolo::KnifeSoloError.new(banner) unless base = @name_args.first
|
16
|
+
|
17
|
+
create_kitchen base
|
18
|
+
create_cupboards base, %w(nodes roles data_bags site-cookbooks cookbooks)
|
19
|
+
create_solo_config base
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def create_cupboards(base, dirs)
|
25
|
+
dirs.each do |dir|
|
26
|
+
cupboard_dir = File.join(base, dir)
|
27
|
+
unless File.exist?(cupboard_dir)
|
28
|
+
mkdir cupboard_dir
|
29
|
+
touch File.join(cupboard_dir, '.gitkeep')
|
30
|
+
end
|
16
31
|
end
|
17
|
-
|
32
|
+
end
|
33
|
+
|
34
|
+
def create_kitchen(base)
|
35
|
+
mkdir base unless base == '.'
|
36
|
+
end
|
37
|
+
|
38
|
+
def create_solo_config(base)
|
39
|
+
solo_file = File.join(base, 'solo.rb')
|
40
|
+
return if File.exist? solo_file
|
41
|
+
|
42
|
+
File.open(solo_file, 'w') do |f|
|
18
43
|
f << <<-RUBY.gsub(/^ {12}/, '')
|
19
44
|
file_cache_path "/tmp/chef-solo"
|
20
45
|
data_bag_path "/tmp/chef-solo/data_bags"
|
data/lib/chef/knife/prepare.rb
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
require 'chef/knife'
|
2
2
|
require 'knife-solo/ssh_command'
|
3
3
|
require 'knife-solo/kitchen_command'
|
4
|
-
require 'knife-solo/
|
5
|
-
require 'knife-solo/knife_solo_error'
|
4
|
+
require 'knife-solo/node_config_command'
|
6
5
|
|
7
6
|
class Chef
|
8
7
|
class Knife
|
@@ -11,12 +10,15 @@ class Chef
|
|
11
10
|
class Prepare < Knife
|
12
11
|
include KnifeSolo::SshCommand
|
13
12
|
include KnifeSolo::KitchenCommand
|
13
|
+
include KnifeSolo::NodeConfigCommand
|
14
14
|
|
15
|
-
|
16
|
-
|
15
|
+
deps do
|
16
|
+
require 'knife-solo/bootstraps'
|
17
|
+
KnifeSolo::SshCommand.load_deps
|
18
|
+
KnifeSolo::NodeConfigCommand.load_deps
|
17
19
|
end
|
18
20
|
|
19
|
-
banner "knife prepare [user@]hostname (options)"
|
21
|
+
banner "knife prepare [user@]hostname [json] (options)"
|
20
22
|
|
21
23
|
option :omnibus_version,
|
22
24
|
:long => "--omnibus-version VERSION",
|
@@ -38,23 +40,16 @@ class Chef
|
|
38
40
|
end
|
39
41
|
|
40
42
|
def bootstrap
|
43
|
+
ui.msg "Bootstrapping Chef..."
|
41
44
|
KnifeSolo::Bootstraps.class_for_operating_system(operating_system()).new(self)
|
42
45
|
end
|
43
46
|
|
44
|
-
def generate_node_config
|
45
|
-
File.open(node_config, 'w') do |f|
|
46
|
-
f.print <<-JSON.gsub(/^\s+/, '')
|
47
|
-
{ "run_list": [] }
|
48
|
-
JSON
|
49
|
-
end unless node_config.exist?
|
50
|
-
end
|
51
|
-
|
52
47
|
def operating_system
|
53
48
|
@operating_system ||= run_command('uname -s').stdout.strip
|
54
49
|
end
|
55
50
|
|
56
51
|
def validate_params!
|
57
|
-
validate_first_cli_arg_is_a_hostname!
|
52
|
+
validate_first_cli_arg_is_a_hostname!
|
58
53
|
end
|
59
54
|
end
|
60
55
|
end
|
data/lib/chef/knife/wash_up.rb
CHANGED
@@ -66,7 +66,7 @@ module KnifeSolo
|
|
66
66
|
end
|
67
67
|
|
68
68
|
def omnibus_install
|
69
|
-
url = prepare.config[:omnibus_url] || "
|
69
|
+
url = prepare.config[:omnibus_url] || "https://www.opscode.com/chef/install.sh"
|
70
70
|
file = File.basename(url)
|
71
71
|
http_client_get_url(url, file)
|
72
72
|
# `release_version` within install.sh will be installed if
|
@@ -78,13 +78,20 @@ module KnifeSolo
|
|
78
78
|
stream_command(install_command)
|
79
79
|
end
|
80
80
|
|
81
|
-
def
|
81
|
+
def yum_omnibus_install
|
82
|
+
omnibus_install
|
83
|
+
# Make sure we have rsync on builds that don't include it by default
|
84
|
+
# (for example Scientific Linux minimal)
|
85
|
+
run_command("sudo yum -y install rsync")
|
86
|
+
end
|
87
|
+
|
88
|
+
def debianoid_omnibus_install
|
82
89
|
omnibus_install
|
83
90
|
# Update to avoid out-of-date package caches
|
84
91
|
run_command("sudo apt-get update")
|
85
92
|
# Make sure we have rsync on builds that don't include it by default
|
86
|
-
# (
|
87
|
-
run_command("sudo apt-get install rsync")
|
93
|
+
# (for example linode's ubuntu 10.04 images)
|
94
|
+
run_command("sudo apt-get -y install rsync")
|
88
95
|
end
|
89
96
|
|
90
97
|
def gem_install
|
@@ -5,6 +5,11 @@ module KnifeSolo::Bootstraps
|
|
5
5
|
prepare.run_command("cat /etc/issue").stdout.strip || perepare.run_command("lsb_release -d -s").stdout.strip
|
6
6
|
end
|
7
7
|
|
8
|
+
def x86?
|
9
|
+
machine = run_command('uname -m').stdout.strip
|
10
|
+
%w{i686 x86 x86_64}.include?(machine)
|
11
|
+
end
|
12
|
+
|
8
13
|
def package_list
|
9
14
|
@packages.join(' ')
|
10
15
|
end
|
@@ -68,14 +73,14 @@ module KnifeSolo::Bootstraps
|
|
68
73
|
return @distro if @distro
|
69
74
|
@distro = case issue
|
70
75
|
when %r{Debian GNU/Linux 5}
|
71
|
-
{:type => "
|
76
|
+
{:type => if x86? then "debianoid_omnibus" else "debian_gem" end, :version => "lenny"}
|
72
77
|
when %r{Debian GNU/Linux 6}
|
73
|
-
{:type => "
|
78
|
+
{:type => if x86? then "debianoid_omnibus" else "debian_gem" end, :version => "squeeze"}
|
74
79
|
when %r{Debian GNU/Linux wheezy}
|
75
80
|
{:type => "debian_gem", :version => "wheezy"}
|
76
81
|
when %r{Ubuntu}i
|
77
82
|
version = run_command("lsb_release -cs").stdout.strip
|
78
|
-
{:type => "
|
83
|
+
{:type => if x86? then "debianoid_omnibus" else "debian_gem" end, :version => version}
|
79
84
|
when %r{Linaro}
|
80
85
|
version = run_command("lsb_release -cs").stdout.strip
|
81
86
|
{:type => "debian_gem", :version => version}
|
@@ -94,7 +99,7 @@ module KnifeSolo::Bootstraps
|
|
94
99
|
when %r{Scientific Linux.*? 5}
|
95
100
|
{:type => "omnibus", :version => "RHEL5"}
|
96
101
|
when %r{Scientific Linux.*? 6}
|
97
|
-
{:type => "
|
102
|
+
{:type => "yum_omnibus", :version => "RHEL6"}
|
98
103
|
when %r{SUSE Linux Enterprise Server 11 SP1}
|
99
104
|
{:type => "zypper_gem", :version => "SLES11"}
|
100
105
|
when %r{openSUSE 11.4}
|
data/lib/knife-solo/info.rb
CHANGED
@@ -25,19 +25,7 @@ module KnifeSolo
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def warn_for_required_file(file)
|
28
|
-
|
28
|
+
ui.error "#{file} is a required file/directory"
|
29
29
|
end
|
30
|
-
|
31
|
-
def first_cli_arg_is_a_hostname?
|
32
|
-
@name_args.first =~ /\A([^@]+(?>@)[^@]+|[^@]+?(?!@))\z/
|
33
|
-
end
|
34
|
-
|
35
|
-
def validate_first_cli_arg_is_a_hostname!(error_class)
|
36
|
-
unless first_cli_arg_is_a_hostname?
|
37
|
-
ui.msg opt_parser.help
|
38
|
-
raise error_class.new "need to pass atleast a [user@]hostname as the first argument"
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
30
|
end
|
43
31
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module KnifeSolo
|
2
|
+
module NodeConfigCommand
|
3
|
+
|
4
|
+
def self.load_deps
|
5
|
+
require 'pathname'
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.included(other)
|
9
|
+
other.class_eval do
|
10
|
+
# Lazy load our dependencies if the including class did not call
|
11
|
+
# Knife#deps yet. See KnifeSolo::SshCommand for more information.
|
12
|
+
deps { KnifeSolo::NodeConfigCommand.load_deps } unless @dependency_loader
|
13
|
+
|
14
|
+
option :chef_node_name,
|
15
|
+
:short => "-N NAME",
|
16
|
+
:long => "--node-name NAME",
|
17
|
+
:description => "The Chef node name for your new node"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def node_config
|
22
|
+
# host method must be defined by the including class
|
23
|
+
Pathname.new(@name_args[1] || "nodes/#{config[:chef_node_name] || host}.json")
|
24
|
+
end
|
25
|
+
|
26
|
+
def generate_node_config
|
27
|
+
if node_config.exist?
|
28
|
+
Chef::Log.debug "Node config '#{node_config}' already exists"
|
29
|
+
else
|
30
|
+
ui.msg "Generating node config '#{node_config}'..."
|
31
|
+
File.open(node_config, 'w') do |f|
|
32
|
+
f.print <<-JSON.gsub(/^\s+/, '')
|
33
|
+
{ "run_list": [] }
|
34
|
+
JSON
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -1,12 +1,26 @@
|
|
1
|
-
require 'pathname'
|
2
|
-
|
3
1
|
module KnifeSolo
|
4
2
|
module SshCommand
|
3
|
+
|
4
|
+
def self.load_deps
|
5
|
+
require 'knife-solo/knife_solo_error'
|
6
|
+
require 'net/ssh'
|
7
|
+
end
|
8
|
+
|
5
9
|
def self.included(other)
|
6
|
-
other.
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
+
other.class_eval do
|
11
|
+
# Lazy load our dependencies if the including class did not call
|
12
|
+
# Knife#deps yet. Later calls to #deps override previous ones, so if
|
13
|
+
# the outer class calls it, it should also call our #load_deps, i.e:
|
14
|
+
#
|
15
|
+
# Include KnifeSolo::SshCommand
|
16
|
+
#
|
17
|
+
# dep do
|
18
|
+
# require 'foo'
|
19
|
+
# require 'bar'
|
20
|
+
# KnifeSolo::SshCommand.load_deps
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
deps { KnifeSolo::SshCommand.load_deps } unless @dependency_loader
|
10
24
|
|
11
25
|
option :ssh_config,
|
12
26
|
:short => "-F CONFIG_FILE",
|
@@ -35,8 +49,15 @@ module KnifeSolo
|
|
35
49
|
end
|
36
50
|
end
|
37
51
|
|
38
|
-
def
|
39
|
-
|
52
|
+
def first_cli_arg_is_a_hostname?
|
53
|
+
@name_args.first =~ /\A([^@]+(?>@)[^@]+|[^@]+?(?!@))\z/
|
54
|
+
end
|
55
|
+
|
56
|
+
def validate_first_cli_arg_is_a_hostname!
|
57
|
+
unless first_cli_arg_is_a_hostname?
|
58
|
+
ui.msg opt_parser.help
|
59
|
+
raise KnifeSoloError.new "need to pass atleast a [user@]hostname as the first argument"
|
60
|
+
end
|
40
61
|
end
|
41
62
|
|
42
63
|
def host_descriptor
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: knife-solo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.15
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-11-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -116,6 +116,7 @@ files:
|
|
116
116
|
- lib/knife-solo/info.rb
|
117
117
|
- lib/knife-solo/kitchen_command.rb
|
118
118
|
- lib/knife-solo/knife_solo_error.rb
|
119
|
+
- lib/knife-solo/node_config_command.rb
|
119
120
|
- lib/knife-solo/ssh_command.rb
|
120
121
|
- lib/knife-solo/tools.rb
|
121
122
|
- lib/knife-solo.rb
|
@@ -131,18 +132,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
131
132
|
- - ! '>='
|
132
133
|
- !ruby/object:Gem::Version
|
133
134
|
version: '0'
|
134
|
-
segments:
|
135
|
-
- 0
|
136
|
-
hash: 3414347062334937427
|
137
135
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
138
136
|
none: false
|
139
137
|
requirements:
|
140
138
|
- - ! '>='
|
141
139
|
- !ruby/object:Gem::Version
|
142
140
|
version: '0'
|
143
|
-
segments:
|
144
|
-
- 0
|
145
|
-
hash: 3414347062334937427
|
146
141
|
requirements: []
|
147
142
|
rubyforge_project: nowarning
|
148
143
|
rubygems_version: 1.8.24
|