knife-solo 0.0.15 → 0.1.0.pre1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|