knife-solo 0.0.15 → 0.1.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +216 -0
- data/LICENSE +7 -0
- data/README.rdoc +127 -0
- data/Rakefile +31 -0
- data/lib/chef/knife/cook.rb +4 -131
- data/lib/chef/knife/kitchen.rb +4 -49
- data/lib/chef/knife/prepare.rb +4 -50
- data/lib/chef/knife/solo_bootstrap.rb +51 -0
- data/lib/chef/knife/solo_clean.rb +25 -0
- data/lib/chef/knife/solo_cook.rb +137 -0
- data/lib/chef/knife/solo_init.rb +59 -0
- data/lib/chef/knife/solo_prepare.rb +56 -0
- data/lib/chef/knife/wash_up.rb +4 -15
- data/lib/knife-solo/bootstraps.rb +1 -1
- data/lib/knife-solo/bootstraps/linux.rb +6 -4
- data/lib/knife-solo/bootstraps/sun_os.rb +9 -0
- data/lib/knife-solo/deprecated_command.rb +19 -0
- data/lib/knife-solo/info.rb +1 -1
- data/lib/knife-solo/kitchen_command.rb +5 -10
- data/lib/knife-solo/node_config_command.rb +17 -3
- data/lib/knife-solo/ssh_command.rb +3 -3
- data/test/bootstraps_test.rb +90 -0
- data/test/deprecated_command_test.rb +46 -0
- data/test/integration/cases/apache2_bootstrap.rb +15 -0
- data/test/integration/cases/apache2_cook.rb +28 -0
- data/test/integration/cases/empty_cook.rb +8 -0
- data/test/integration/cases/encrypted_data_bag.rb +27 -0
- data/test/integration/centos5_6_test.rb +19 -0
- data/test/integration/gentoo2011_test.rb +18 -0
- data/test/integration/omnios_r151004_test.rb +14 -0
- data/test/integration/scientific_linux_63_test.rb +15 -0
- data/test/integration/sles_11_test.rb +14 -0
- data/test/integration/ubuntu10_04_test.rb +15 -0
- data/test/integration/ubuntu12_04_bootstrap_test.rb +17 -0
- data/test/integration/ubuntu12_04_test.rb +15 -0
- data/test/integration_helper.rb +16 -0
- data/test/kitchen_command_test.rb +31 -0
- data/test/minitest/parallel.rb +41 -0
- data/test/node_config_command_test.rb +101 -0
- data/test/solo_bootstrap_test.rb +32 -0
- data/test/solo_clean_test.rb +12 -0
- data/test/solo_cook_test.rb +67 -0
- data/test/solo_init_test.rb +40 -0
- data/test/solo_prepare_test.rb +50 -0
- data/test/ssh_command_test.rb +100 -0
- data/test/support/config.yml.example +4 -0
- data/test/support/data_bag_key +1 -0
- data/test/support/ec2_runner.rb +122 -0
- data/test/support/integration_test.rb +94 -0
- data/test/support/issue_files/gentoo2011 +3 -0
- data/test/support/issue_files/sles11-sp1 +4 -0
- data/test/support/issue_files/ubuntu +2 -0
- data/test/support/kitchen_helper.rb +22 -0
- data/test/support/loggable.rb +18 -0
- data/test/support/secret_cookbook/metadata.rb +5 -0
- data/test/support/secret_cookbook/recipes/default.rb +8 -0
- data/test/support/ssh_config +3 -0
- data/test/support/test_case.rb +24 -0
- data/test/support/validation_helper.rb +39 -0
- data/test/test_helper.rb +7 -0
- metadata +99 -11
- data/lib/knife-solo/knife_solo_error.rb +0 -3
data/lib/chef/knife/kitchen.rb
CHANGED
@@ -1,55 +1,10 @@
|
|
1
|
-
require 'chef/knife'
|
1
|
+
require 'chef/knife/solo_init'
|
2
|
+
require 'knife-solo/deprecated_command'
|
2
3
|
|
3
4
|
class Chef
|
4
5
|
class Knife
|
5
|
-
class Kitchen <
|
6
|
-
include
|
7
|
-
|
8
|
-
deps do
|
9
|
-
require 'knife-solo/knife_solo_error'
|
10
|
-
end
|
11
|
-
|
12
|
-
banner "knife kitchen NAME or initialize current directory with '.'"
|
13
|
-
|
14
|
-
def run
|
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
|
31
|
-
end
|
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|
|
43
|
-
f << <<-RUBY.gsub(/^ {12}/, '')
|
44
|
-
file_cache_path "/tmp/chef-solo"
|
45
|
-
data_bag_path "/tmp/chef-solo/data_bags"
|
46
|
-
encrypted_data_bag_secret "/tmp/chef-solo/data_bag_key"
|
47
|
-
cookbook_path [ "/tmp/chef-solo/site-cookbooks",
|
48
|
-
"/tmp/chef-solo/cookbooks" ]
|
49
|
-
role_path "/tmp/chef-solo/roles"
|
50
|
-
RUBY
|
51
|
-
end
|
52
|
-
end
|
6
|
+
class Kitchen < SoloInit
|
7
|
+
include KnifeSolo::DeprecatedCommand
|
53
8
|
end
|
54
9
|
end
|
55
10
|
end
|
data/lib/chef/knife/prepare.rb
CHANGED
@@ -1,56 +1,10 @@
|
|
1
|
-
require 'chef/knife'
|
2
|
-
require 'knife-solo/
|
3
|
-
require 'knife-solo/kitchen_command'
|
4
|
-
require 'knife-solo/node_config_command'
|
1
|
+
require 'chef/knife/solo_prepare'
|
2
|
+
require 'knife-solo/deprecated_command'
|
5
3
|
|
6
4
|
class Chef
|
7
5
|
class Knife
|
8
|
-
|
9
|
-
|
10
|
-
class Prepare < Knife
|
11
|
-
include KnifeSolo::SshCommand
|
12
|
-
include KnifeSolo::KitchenCommand
|
13
|
-
include KnifeSolo::NodeConfigCommand
|
14
|
-
|
15
|
-
deps do
|
16
|
-
require 'knife-solo/bootstraps'
|
17
|
-
KnifeSolo::SshCommand.load_deps
|
18
|
-
KnifeSolo::NodeConfigCommand.load_deps
|
19
|
-
end
|
20
|
-
|
21
|
-
banner "knife prepare [user@]hostname [json] (options)"
|
22
|
-
|
23
|
-
option :omnibus_version,
|
24
|
-
:long => "--omnibus-version VERSION",
|
25
|
-
:description => "The version of Omnibus to install"
|
26
|
-
|
27
|
-
option :omnibus_url,
|
28
|
-
:long => "--omnibus-url URL",
|
29
|
-
:description => "URL to download install.sh from"
|
30
|
-
|
31
|
-
option :omnibus_options,
|
32
|
-
:long => "--omnibus-options \"-r -n\"",
|
33
|
-
:description => "Pass options to the install.sh script"
|
34
|
-
|
35
|
-
def run
|
36
|
-
validate_params!
|
37
|
-
super
|
38
|
-
bootstrap.bootstrap!
|
39
|
-
generate_node_config
|
40
|
-
end
|
41
|
-
|
42
|
-
def bootstrap
|
43
|
-
ui.msg "Bootstrapping Chef..."
|
44
|
-
KnifeSolo::Bootstraps.class_for_operating_system(operating_system()).new(self)
|
45
|
-
end
|
46
|
-
|
47
|
-
def operating_system
|
48
|
-
@operating_system ||= run_command('uname -s').stdout.strip
|
49
|
-
end
|
50
|
-
|
51
|
-
def validate_params!
|
52
|
-
validate_first_cli_arg_is_a_hostname!
|
53
|
-
end
|
6
|
+
class Prepare < SoloPrepare
|
7
|
+
include KnifeSolo::DeprecatedCommand
|
54
8
|
end
|
55
9
|
end
|
56
10
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'chef/knife'
|
2
|
+
require 'chef/knife/solo_cook'
|
3
|
+
require 'chef/knife/solo_prepare'
|
4
|
+
|
5
|
+
require 'knife-solo/kitchen_command'
|
6
|
+
require 'knife-solo/ssh_command'
|
7
|
+
|
8
|
+
class Chef
|
9
|
+
class Knife
|
10
|
+
class SoloBootstrap < Knife
|
11
|
+
include KnifeSolo::KitchenCommand
|
12
|
+
include KnifeSolo::SshCommand
|
13
|
+
|
14
|
+
deps do
|
15
|
+
KnifeSolo::SshCommand.load_deps
|
16
|
+
SoloPrepare.load_deps
|
17
|
+
SoloCook.load_deps
|
18
|
+
end
|
19
|
+
|
20
|
+
banner "knife solo bootstrap [USER@]HOSTNAME [JSON] (options)"
|
21
|
+
|
22
|
+
# Use (some) options from prepare and cook commands
|
23
|
+
self.options = SoloPrepare.options
|
24
|
+
[:sync_only, :why_run].each { |opt| option opt, SoloCook.options[opt] }
|
25
|
+
|
26
|
+
def run
|
27
|
+
validate!
|
28
|
+
|
29
|
+
prepare = command_with_same_args(SoloPrepare)
|
30
|
+
prepare.run
|
31
|
+
|
32
|
+
cook = command_with_same_args(SoloCook)
|
33
|
+
cook.config[:skip_chef_check] = true
|
34
|
+
cook.run
|
35
|
+
end
|
36
|
+
|
37
|
+
def validate!
|
38
|
+
validate_first_cli_arg_is_a_hostname!
|
39
|
+
validate_kitchen!
|
40
|
+
end
|
41
|
+
|
42
|
+
def command_with_same_args(klass)
|
43
|
+
cmd = klass.new
|
44
|
+
cmd.ui = ui
|
45
|
+
cmd.name_args = @name_args
|
46
|
+
cmd.config = config
|
47
|
+
cmd
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'chef/knife'
|
2
|
+
require 'knife-solo/ssh_command'
|
3
|
+
require 'knife-solo/kitchen_command'
|
4
|
+
|
5
|
+
class Chef
|
6
|
+
class Knife
|
7
|
+
class SoloClean < Knife
|
8
|
+
include KnifeSolo::SshCommand
|
9
|
+
include KnifeSolo::KitchenCommand
|
10
|
+
|
11
|
+
banner "knife solo clean [USER@]HOSTNAME"
|
12
|
+
|
13
|
+
def run
|
14
|
+
validate!
|
15
|
+
Chef::Config.from_file('solo.rb')
|
16
|
+
run_command "rm -rf #{Chef::Config.file_cache_path}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def validate!
|
20
|
+
validate_first_cli_arg_is_a_hostname!
|
21
|
+
validate_kitchen!
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
require 'chef/knife'
|
2
|
+
|
3
|
+
require 'knife-solo/ssh_command'
|
4
|
+
require 'knife-solo/kitchen_command'
|
5
|
+
require 'knife-solo/node_config_command'
|
6
|
+
require 'knife-solo/tools'
|
7
|
+
|
8
|
+
class Chef
|
9
|
+
class Knife
|
10
|
+
# Approach ported from spatula (https://github.com/trotter/spatula)
|
11
|
+
# Copyright 2009, Trotter Cashion
|
12
|
+
class SoloCook < Knife
|
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"]
|
15
|
+
CHEF_VERSION_CONSTRAINT ||= ">=0.10.4"
|
16
|
+
|
17
|
+
include KnifeSolo::SshCommand
|
18
|
+
include KnifeSolo::KitchenCommand
|
19
|
+
include KnifeSolo::NodeConfigCommand
|
20
|
+
include KnifeSolo::Tools
|
21
|
+
|
22
|
+
deps do
|
23
|
+
require 'chef/cookbook/chefignore'
|
24
|
+
require 'pathname'
|
25
|
+
KnifeSolo::SshCommand.load_deps
|
26
|
+
KnifeSolo::NodeConfigCommand.load_deps
|
27
|
+
end
|
28
|
+
|
29
|
+
banner "knife solo cook [USER@]HOSTNAME [JSON] (options)"
|
30
|
+
|
31
|
+
option :skip_chef_check,
|
32
|
+
:long => '--skip-chef-check',
|
33
|
+
:boolean => true,
|
34
|
+
:description => "Skip the version check on the Chef gem"
|
35
|
+
|
36
|
+
option :sync_only,
|
37
|
+
:long => '--sync-only',
|
38
|
+
:boolean => false,
|
39
|
+
:description => "Only sync the cookbook - do not run Chef"
|
40
|
+
|
41
|
+
option :why_run,
|
42
|
+
:short => '-W',
|
43
|
+
:long => '--why-run',
|
44
|
+
:boolean => true,
|
45
|
+
:description => "Enable whyrun mode"
|
46
|
+
|
47
|
+
def run
|
48
|
+
time('Run') do
|
49
|
+
validate!
|
50
|
+
Chef::Config.from_file('solo.rb')
|
51
|
+
check_chef_version unless config[:skip_chef_check]
|
52
|
+
generate_node_config
|
53
|
+
rsync_kitchen
|
54
|
+
add_patches
|
55
|
+
cook unless config[:sync_only]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def validate!
|
60
|
+
validate_first_cli_arg_is_a_hostname!
|
61
|
+
validate_kitchen!
|
62
|
+
end
|
63
|
+
|
64
|
+
def chef_path
|
65
|
+
Chef::Config.file_cache_path
|
66
|
+
end
|
67
|
+
|
68
|
+
def chefignore
|
69
|
+
@chefignore ||= ::Chef::Cookbook::Chefignore.new("./")
|
70
|
+
end
|
71
|
+
|
72
|
+
# cygwin rsync path must be adjusted to work
|
73
|
+
def adjust_rsync_path(path)
|
74
|
+
return path unless windows_node?
|
75
|
+
path.gsub(/^(\w):/) { "/cygdrive/#{$1}" }
|
76
|
+
end
|
77
|
+
|
78
|
+
def patch_path
|
79
|
+
Array(Chef::Config.cookbook_path).first + "/chef_solo_patches/libraries"
|
80
|
+
end
|
81
|
+
|
82
|
+
def rsync_exclude
|
83
|
+
(%w{revision-deploys tmp '.*'} + chefignore.ignores).uniq
|
84
|
+
end
|
85
|
+
|
86
|
+
def debug?
|
87
|
+
config[:verbosity] and config[:verbosity] > 0
|
88
|
+
end
|
89
|
+
|
90
|
+
# Time a command
|
91
|
+
def time(msg)
|
92
|
+
return yield unless debug?
|
93
|
+
ui.msg "Starting '#{msg}'"
|
94
|
+
start = Time.now
|
95
|
+
yield
|
96
|
+
ui.msg "#{msg} finished in #{Time.now - start} seconds"
|
97
|
+
end
|
98
|
+
|
99
|
+
def rsync_kitchen
|
100
|
+
time('Rsync kitchen') do
|
101
|
+
cmd = %Q{rsync -rl --rsh="ssh #{ssh_args}" --delete #{rsync_exclude.collect{ |ignore| "--exclude #{ignore} " }.join} ./ :#{adjust_rsync_path(chef_path)}}
|
102
|
+
ui.msg cmd if debug?
|
103
|
+
system! cmd
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def add_patches
|
108
|
+
run_portable_mkdir_p(patch_path)
|
109
|
+
Dir[Pathname.new(__FILE__).dirname.join("patches", "*.rb").to_s].each do |patch|
|
110
|
+
time(patch) do
|
111
|
+
system! %Q{rsync -rl --rsh="ssh #{ssh_args}" #{patch} :#{adjust_rsync_path(patch_path)}}
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def check_chef_version
|
117
|
+
ui.msg "Checking Chef version..."
|
118
|
+
result = run_command <<-BASH
|
119
|
+
export PATH="#{OMNIBUS_EMBEDDED_PATHS.join(":")}:$PATH"
|
120
|
+
export GEM_PATH="#{OMNIBUS_EMBEDDED_GEM_PATHS.join(":")}:$GEM_PATH"
|
121
|
+
ruby -rubygems -e "gem 'chef', '#{CHEF_VERSION_CONSTRAINT}'"
|
122
|
+
BASH
|
123
|
+
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?
|
124
|
+
end
|
125
|
+
|
126
|
+
def cook
|
127
|
+
cmd = "sudo chef-solo -c #{chef_path}/solo.rb -j #{chef_path}/#{node_config}"
|
128
|
+
cmd << " -l debug" if debug?
|
129
|
+
cmd << " -N #{config[:chef_node_name]}" if config[:chef_node_name]
|
130
|
+
cmd << " -W" if config[:why_run]
|
131
|
+
|
132
|
+
result = stream_command cmd
|
133
|
+
raise "chef-solo failed. See output above." unless result.success?
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'chef/knife'
|
2
|
+
|
3
|
+
class Chef
|
4
|
+
class Knife
|
5
|
+
class SoloInit < Knife
|
6
|
+
include FileUtils
|
7
|
+
|
8
|
+
banner "knife solo init DIRECTORY"
|
9
|
+
|
10
|
+
def run
|
11
|
+
validate!
|
12
|
+
base = @name_args.first
|
13
|
+
create_kitchen base
|
14
|
+
create_cupboards base, %w(nodes roles data_bags site-cookbooks cookbooks)
|
15
|
+
create_solo_config base
|
16
|
+
end
|
17
|
+
|
18
|
+
def validate!
|
19
|
+
unless @name_args.first
|
20
|
+
show_usage
|
21
|
+
ui.fatal "You must specify a directory. Use '.' to initialize the current one."
|
22
|
+
exit 1
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def create_cupboards(base, dirs)
|
29
|
+
dirs.each do |dir|
|
30
|
+
cupboard_dir = File.join(base, dir)
|
31
|
+
unless File.exist?(cupboard_dir)
|
32
|
+
mkdir cupboard_dir
|
33
|
+
touch File.join(cupboard_dir, '.gitkeep')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def create_kitchen(base)
|
39
|
+
mkdir base unless base == '.'
|
40
|
+
end
|
41
|
+
|
42
|
+
def create_solo_config(base)
|
43
|
+
solo_file = File.join(base, 'solo.rb')
|
44
|
+
return if File.exist? solo_file
|
45
|
+
|
46
|
+
File.open(solo_file, 'w') do |f|
|
47
|
+
f << <<-RUBY.gsub(/^ {12}/, '')
|
48
|
+
file_cache_path "/tmp/chef-solo"
|
49
|
+
data_bag_path "/tmp/chef-solo/data_bags"
|
50
|
+
encrypted_data_bag_secret "/tmp/chef-solo/data_bag_key"
|
51
|
+
cookbook_path [ "/tmp/chef-solo/site-cookbooks",
|
52
|
+
"/tmp/chef-solo/cookbooks" ]
|
53
|
+
role_path "/tmp/chef-solo/roles"
|
54
|
+
RUBY
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'chef/knife'
|
2
|
+
require 'knife-solo/ssh_command'
|
3
|
+
require 'knife-solo/kitchen_command'
|
4
|
+
require 'knife-solo/node_config_command'
|
5
|
+
|
6
|
+
class Chef
|
7
|
+
class Knife
|
8
|
+
# Approach ported from littlechef (https://github.com/tobami/littlechef)
|
9
|
+
# Copyright 2010, 2011, Miquel Torres <tobami@googlemail.com>
|
10
|
+
class SoloPrepare < Knife
|
11
|
+
include KnifeSolo::SshCommand
|
12
|
+
include KnifeSolo::KitchenCommand
|
13
|
+
include KnifeSolo::NodeConfigCommand
|
14
|
+
|
15
|
+
deps do
|
16
|
+
require 'knife-solo/bootstraps'
|
17
|
+
KnifeSolo::SshCommand.load_deps
|
18
|
+
KnifeSolo::NodeConfigCommand.load_deps
|
19
|
+
end
|
20
|
+
|
21
|
+
banner "knife solo prepare [USER@]HOSTNAME [JSON] (options)"
|
22
|
+
|
23
|
+
option :omnibus_version,
|
24
|
+
:long => "--omnibus-version VERSION",
|
25
|
+
:description => "The version of Omnibus to install"
|
26
|
+
|
27
|
+
option :omnibus_url,
|
28
|
+
:long => "--omnibus-url URL",
|
29
|
+
:description => "URL to download install.sh from"
|
30
|
+
|
31
|
+
option :omnibus_options,
|
32
|
+
:long => "--omnibus-options \"-r -n\"",
|
33
|
+
:description => "Pass options to the install.sh script"
|
34
|
+
|
35
|
+
def run
|
36
|
+
validate!
|
37
|
+
bootstrap.bootstrap!
|
38
|
+
generate_node_config
|
39
|
+
end
|
40
|
+
|
41
|
+
def validate!
|
42
|
+
validate_first_cli_arg_is_a_hostname!
|
43
|
+
validate_kitchen!
|
44
|
+
end
|
45
|
+
|
46
|
+
def bootstrap
|
47
|
+
ui.msg "Bootstrapping Chef..."
|
48
|
+
KnifeSolo::Bootstraps.class_for_operating_system(operating_system()).new(self)
|
49
|
+
end
|
50
|
+
|
51
|
+
def operating_system
|
52
|
+
@operating_system ||= run_command('uname -s').stdout.strip
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|