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.
Files changed (62) hide show
  1. data/CHANGELOG.md +216 -0
  2. data/LICENSE +7 -0
  3. data/README.rdoc +127 -0
  4. data/Rakefile +31 -0
  5. data/lib/chef/knife/cook.rb +4 -131
  6. data/lib/chef/knife/kitchen.rb +4 -49
  7. data/lib/chef/knife/prepare.rb +4 -50
  8. data/lib/chef/knife/solo_bootstrap.rb +51 -0
  9. data/lib/chef/knife/solo_clean.rb +25 -0
  10. data/lib/chef/knife/solo_cook.rb +137 -0
  11. data/lib/chef/knife/solo_init.rb +59 -0
  12. data/lib/chef/knife/solo_prepare.rb +56 -0
  13. data/lib/chef/knife/wash_up.rb +4 -15
  14. data/lib/knife-solo/bootstraps.rb +1 -1
  15. data/lib/knife-solo/bootstraps/linux.rb +6 -4
  16. data/lib/knife-solo/bootstraps/sun_os.rb +9 -0
  17. data/lib/knife-solo/deprecated_command.rb +19 -0
  18. data/lib/knife-solo/info.rb +1 -1
  19. data/lib/knife-solo/kitchen_command.rb +5 -10
  20. data/lib/knife-solo/node_config_command.rb +17 -3
  21. data/lib/knife-solo/ssh_command.rb +3 -3
  22. data/test/bootstraps_test.rb +90 -0
  23. data/test/deprecated_command_test.rb +46 -0
  24. data/test/integration/cases/apache2_bootstrap.rb +15 -0
  25. data/test/integration/cases/apache2_cook.rb +28 -0
  26. data/test/integration/cases/empty_cook.rb +8 -0
  27. data/test/integration/cases/encrypted_data_bag.rb +27 -0
  28. data/test/integration/centos5_6_test.rb +19 -0
  29. data/test/integration/gentoo2011_test.rb +18 -0
  30. data/test/integration/omnios_r151004_test.rb +14 -0
  31. data/test/integration/scientific_linux_63_test.rb +15 -0
  32. data/test/integration/sles_11_test.rb +14 -0
  33. data/test/integration/ubuntu10_04_test.rb +15 -0
  34. data/test/integration/ubuntu12_04_bootstrap_test.rb +17 -0
  35. data/test/integration/ubuntu12_04_test.rb +15 -0
  36. data/test/integration_helper.rb +16 -0
  37. data/test/kitchen_command_test.rb +31 -0
  38. data/test/minitest/parallel.rb +41 -0
  39. data/test/node_config_command_test.rb +101 -0
  40. data/test/solo_bootstrap_test.rb +32 -0
  41. data/test/solo_clean_test.rb +12 -0
  42. data/test/solo_cook_test.rb +67 -0
  43. data/test/solo_init_test.rb +40 -0
  44. data/test/solo_prepare_test.rb +50 -0
  45. data/test/ssh_command_test.rb +100 -0
  46. data/test/support/config.yml.example +4 -0
  47. data/test/support/data_bag_key +1 -0
  48. data/test/support/ec2_runner.rb +122 -0
  49. data/test/support/integration_test.rb +94 -0
  50. data/test/support/issue_files/gentoo2011 +3 -0
  51. data/test/support/issue_files/sles11-sp1 +4 -0
  52. data/test/support/issue_files/ubuntu +2 -0
  53. data/test/support/kitchen_helper.rb +22 -0
  54. data/test/support/loggable.rb +18 -0
  55. data/test/support/secret_cookbook/metadata.rb +5 -0
  56. data/test/support/secret_cookbook/recipes/default.rb +8 -0
  57. data/test/support/ssh_config +3 -0
  58. data/test/support/test_case.rb +24 -0
  59. data/test/support/validation_helper.rb +39 -0
  60. data/test/test_helper.rb +7 -0
  61. metadata +99 -11
  62. data/lib/knife-solo/knife_solo_error.rb +0 -3
@@ -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 < Knife
6
- include FileUtils
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
@@ -1,56 +1,10 @@
1
- require 'chef/knife'
2
- require 'knife-solo/ssh_command'
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
- # Approach ported from littlechef (https://github.com/tobami/littlechef)
9
- # Copyright 2010, 2011, Miquel Torres <tobami@googlemail.com>
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