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/wash_up.rb
CHANGED
@@ -1,21 +1,10 @@
|
|
1
|
-
require 'chef/knife'
|
2
|
-
require 'knife-solo/
|
3
|
-
require 'knife-solo/kitchen_command'
|
1
|
+
require 'chef/knife/solo_clean'
|
2
|
+
require 'knife-solo/deprecated_command'
|
4
3
|
|
5
4
|
class Chef
|
6
5
|
class Knife
|
7
|
-
class WashUp <
|
8
|
-
include KnifeSolo::
|
9
|
-
include KnifeSolo::KitchenCommand
|
10
|
-
|
11
|
-
banner "knife wash_up [user@]hostname"
|
12
|
-
|
13
|
-
def run
|
14
|
-
validate_first_cli_arg_is_a_hostname!
|
15
|
-
super
|
16
|
-
Chef::Config.from_file('solo.rb')
|
17
|
-
run_command "rm -rf #{Chef::Config.file_cache_path}"
|
18
|
-
end
|
6
|
+
class WashUp < SoloClean
|
7
|
+
include KnifeSolo::DeprecatedCommand
|
19
8
|
end
|
20
9
|
end
|
21
10
|
end
|
@@ -96,14 +96,16 @@ module KnifeSolo::Bootstraps
|
|
96
96
|
{:type => "omnibus", :version => "FC15"}
|
97
97
|
when %r{Fedora release.*? 16}
|
98
98
|
{:type => "omnibus", :version => "FC16"}
|
99
|
+
when %r{Fedora release.*? 17}
|
100
|
+
{:type => "omnibus", :version => "FC17"}
|
99
101
|
when %r{Scientific Linux.*? 5}
|
100
102
|
{:type => "omnibus", :version => "RHEL5"}
|
101
103
|
when %r{Scientific Linux.*? 6}
|
102
104
|
{:type => "yum_omnibus", :version => "RHEL6"}
|
103
|
-
when %r{SUSE Linux Enterprise Server
|
104
|
-
{:type => "
|
105
|
-
when %r{openSUSE
|
106
|
-
{:type => "
|
105
|
+
when %r{SUSE Linux Enterprise Server 1[12]}
|
106
|
+
{:type => "omnibus", :version => "SLES11"}
|
107
|
+
when %r{openSUSE 1[12]}
|
108
|
+
{:type => "omnibus", :version => "openSUSE"}
|
107
109
|
when %r{This is \\n\.\\O \(\\s \\m \\r\) \\t}
|
108
110
|
{:type => "emerge_gem", :version => "Gentoo"}
|
109
111
|
else
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module KnifeSolo
|
2
|
+
module DeprecatedCommand
|
3
|
+
|
4
|
+
def self.included(other)
|
5
|
+
other.class_eval do
|
6
|
+
def self.deprecated
|
7
|
+
"`knife #{common_name}` is deprecated! Please use:\n #{superclass.banner}"
|
8
|
+
end
|
9
|
+
|
10
|
+
banner deprecated
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def run
|
15
|
+
ui.warn self.class.deprecated
|
16
|
+
super
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/knife-solo/info.rb
CHANGED
@@ -1,19 +1,14 @@
|
|
1
|
-
require 'knife-solo/knife_solo_error'
|
2
|
-
|
3
1
|
module KnifeSolo
|
4
2
|
module KitchenCommand
|
5
|
-
class OutOfKitchenError < KnifeSoloError
|
6
|
-
def message
|
7
|
-
"This command must be run inside a Chef solo kitchen."
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
3
|
def self.required_files
|
12
4
|
%w(solo.rb)
|
13
5
|
end
|
14
6
|
|
15
|
-
def
|
16
|
-
|
7
|
+
def validate_kitchen!
|
8
|
+
unless required_files_present?
|
9
|
+
ui.fatal "This command must be run inside a Chef solo kitchen."
|
10
|
+
exit 1
|
11
|
+
end
|
17
12
|
end
|
18
13
|
|
19
14
|
def required_files_present?
|
@@ -15,6 +15,20 @@ module KnifeSolo
|
|
15
15
|
:short => "-N NAME",
|
16
16
|
:long => "--node-name NAME",
|
17
17
|
:description => "The Chef node name for your new node"
|
18
|
+
|
19
|
+
option :run_list,
|
20
|
+
:short => "-r RUN_LIST",
|
21
|
+
:long => "--run-list RUN_LIST",
|
22
|
+
:description => "Comma separated list of roles/recipes to put to node config (if it does not exist)",
|
23
|
+
:proc => lambda { |o| o.split(/[\s,]+/) },
|
24
|
+
:default => []
|
25
|
+
|
26
|
+
option :first_boot_attributes,
|
27
|
+
:short => "-j JSON_ATTRIBS",
|
28
|
+
:long => "--json-attributes",
|
29
|
+
:description => "A JSON string to be added to node config (if it does not exist)",
|
30
|
+
:proc => lambda { |o| JSON.parse(o) },
|
31
|
+
:default => {}
|
18
32
|
end
|
19
33
|
end
|
20
34
|
|
@@ -29,9 +43,9 @@ module KnifeSolo
|
|
29
43
|
else
|
30
44
|
ui.msg "Generating node config '#{node_config}'..."
|
31
45
|
File.open(node_config, 'w') do |f|
|
32
|
-
|
33
|
-
|
34
|
-
|
46
|
+
attributes = config[:first_boot_attributes] || {}
|
47
|
+
run_list = { :run_list => config[:run_list] || [] }
|
48
|
+
f.print attributes.merge(run_list).to_json
|
35
49
|
end
|
36
50
|
end
|
37
51
|
end
|
@@ -2,7 +2,6 @@ module KnifeSolo
|
|
2
2
|
module SshCommand
|
3
3
|
|
4
4
|
def self.load_deps
|
5
|
-
require 'knife-solo/knife_solo_error'
|
6
5
|
require 'net/ssh'
|
7
6
|
end
|
8
7
|
|
@@ -55,8 +54,9 @@ module KnifeSolo
|
|
55
54
|
|
56
55
|
def validate_first_cli_arg_is_a_hostname!
|
57
56
|
unless first_cli_arg_is_a_hostname?
|
58
|
-
|
59
|
-
|
57
|
+
show_usage
|
58
|
+
ui.fatal "You must specify [<user>@]<hostname> as the first argument"
|
59
|
+
exit 1
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
require 'knife-solo/bootstraps'
|
4
|
+
|
5
|
+
class KnifeSolo::Bootstraps::StubOS < KnifeSolo::Bootstraps::Base
|
6
|
+
end
|
7
|
+
|
8
|
+
class KnifeSolo::Bootstraps::StubOS2 < KnifeSolo::Bootstraps::Base
|
9
|
+
def gem_packages ; ['chef'] ; end
|
10
|
+
def distro ; {:type => 'gem', :version => 'Fanny Faker'} ; end
|
11
|
+
def gem_install
|
12
|
+
# dont' actually install anything
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class BootstrapsTest < TestCase
|
17
|
+
def test_bootstrap_class_exists_for
|
18
|
+
assert_equal true, KnifeSolo::Bootstraps.class_exists_for?('Stub OS')
|
19
|
+
|
20
|
+
assert_equal false, KnifeSolo::Bootstraps.class_exists_for?('Mythical OS')
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_distro_raises_if_not_implemented
|
24
|
+
bootstrap = bootstrap_instance()
|
25
|
+
|
26
|
+
assert_raises RuntimeError do
|
27
|
+
bootstrap.distro()
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_gem_packages_raises_if_not_implemented
|
32
|
+
bootstrap = bootstrap_instance()
|
33
|
+
|
34
|
+
assert_raises RuntimeError do
|
35
|
+
bootstrap.gem_packages()
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_bootstrap_calls_appropriate_install_method
|
40
|
+
bootstrap = KnifeSolo::Bootstraps::StubOS2.new(mock)
|
41
|
+
bootstrap.stubs(:distro).returns({:type => 'disco_gem'})
|
42
|
+
|
43
|
+
bootstrap.expects(:disco_gem_install)
|
44
|
+
|
45
|
+
bootstrap.bootstrap!
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_bootstrap_calls_pre_bootstrap_checks
|
49
|
+
bootstrap = KnifeSolo::Bootstraps::StubOS2.new(mock)
|
50
|
+
|
51
|
+
bootstrap.expects(:run_pre_bootstrap_checks)
|
52
|
+
|
53
|
+
bootstrap.bootstrap!
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_bootstrap_delegates_to_knife_prepare
|
57
|
+
prepare = mock('chef::knife::prepare')
|
58
|
+
bootstrap = KnifeSolo::Bootstraps::StubOS2.new(prepare)
|
59
|
+
|
60
|
+
assert prepare == bootstrap.prepare
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_darwin_checks_for_xcode_install_and_barfs_if_missing
|
64
|
+
bootstrap = KnifeSolo::Bootstraps::Darwin.new(mock)
|
65
|
+
# don't want to actually run anything
|
66
|
+
bootstrap.stubs(:gem_install)
|
67
|
+
|
68
|
+
bootstrap.expects(:has_xcode_installed?).returns(false)
|
69
|
+
|
70
|
+
assert_raises RuntimeError do
|
71
|
+
bootstrap.bootstrap!
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_omnibus_install_methdod
|
76
|
+
bootstrap = KnifeSolo::Bootstraps::StubOS2.new(mock)
|
77
|
+
bootstrap.stubs(:distro).returns({:type => "omnibus"})
|
78
|
+
|
79
|
+
bootstrap.expects(:omnibus_install)
|
80
|
+
|
81
|
+
bootstrap.bootstrap!
|
82
|
+
end
|
83
|
+
|
84
|
+
# ***
|
85
|
+
|
86
|
+
def bootstrap_instance
|
87
|
+
@prepare = mock('Knife::Chef::SoloPrepare')
|
88
|
+
KnifeSolo::Bootstraps::StubOS.new(@prepare)
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
require 'chef/knife'
|
4
|
+
require 'knife-solo/deprecated_command'
|
5
|
+
|
6
|
+
class DummyNewCommand < Chef::Knife
|
7
|
+
banner "knife dummy_new_command"
|
8
|
+
|
9
|
+
def run
|
10
|
+
# calls #new_run so we can be sure this gets called
|
11
|
+
new_run
|
12
|
+
end
|
13
|
+
|
14
|
+
def new_run
|
15
|
+
# dummy
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class DummyDeprecatedCommand < DummyNewCommand
|
20
|
+
include KnifeSolo::DeprecatedCommand
|
21
|
+
end
|
22
|
+
|
23
|
+
class DeprecatedCommandTest < TestCase
|
24
|
+
def test_help_warns_about_deprecation
|
25
|
+
$stdout.expects(:puts).with(regexp_matches(/deprecated!/))
|
26
|
+
assert_exits { command("--help") }
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_warns_about_deprecation
|
30
|
+
cmd = command
|
31
|
+
cmd.ui.expects(:err).with(regexp_matches(/deprecated!/))
|
32
|
+
cmd.run
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_runs_original_command
|
36
|
+
cmd = command
|
37
|
+
cmd.ui.stubs(:err)
|
38
|
+
cmd.expects(:new_run)
|
39
|
+
cmd.run
|
40
|
+
end
|
41
|
+
|
42
|
+
def command(*args)
|
43
|
+
DummyDeprecatedCommand.load_deps
|
44
|
+
DummyDeprecatedCommand.new(args)
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# Tries to bootstrap with apache2 cookbook and
|
2
|
+
# verifies the "It Works!" page is present.
|
3
|
+
|
4
|
+
require $base_dir.join('integration', 'cases', 'apache2_cook')
|
5
|
+
|
6
|
+
module Apache2Bootstrap
|
7
|
+
include Apache2Cook
|
8
|
+
|
9
|
+
def test_apache2
|
10
|
+
write_cheffile
|
11
|
+
system "librarian-chef install >> #{log_file}"
|
12
|
+
assert_subcommand "bootstrap --run-list=recipe[apache2]"
|
13
|
+
assert_match default_apache_message, http_response
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# Tries to cook with apache2 cookbook and
|
2
|
+
# verifies the "It Works!" page is present.
|
3
|
+
module Apache2Cook
|
4
|
+
def write_cheffile
|
5
|
+
File.open('Cheffile', 'w') do |f|
|
6
|
+
f.print <<-CHEF
|
7
|
+
site 'http://community.opscode.com/api/v1'
|
8
|
+
cookbook 'apache2'
|
9
|
+
CHEF
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def http_response
|
14
|
+
Net::HTTP.get(URI.parse("http://"+server.public_ip_address))
|
15
|
+
end
|
16
|
+
|
17
|
+
def default_apache_message
|
18
|
+
/It works!/
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_apache2
|
22
|
+
write_cheffile
|
23
|
+
system "librarian-chef install >> #{log_file}"
|
24
|
+
write_nodefile(run_list: ["recipe[apache2]"])
|
25
|
+
assert_subcommand "cook"
|
26
|
+
assert_match default_apache_message, http_response
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'chef/encrypted_data_bag_item'
|
2
|
+
|
3
|
+
module EncryptedDataBag
|
4
|
+
def setup
|
5
|
+
super
|
6
|
+
FileUtils.cp $base_dir.join('support', 'data_bag_key'), 'data_bag_key'
|
7
|
+
FileUtils.cp_r $base_dir.join('support', 'secret_cookbook'), 'cookbooks/secret_cookbook'
|
8
|
+
@password = "essential particles busy loud"
|
9
|
+
create_data_bag
|
10
|
+
end
|
11
|
+
|
12
|
+
def create_data_bag
|
13
|
+
secret = Chef::EncryptedDataBagItem.load_secret('data_bag_key')
|
14
|
+
data = {"id" => "passwords", "admin" => @password}
|
15
|
+
encrypted_data = Chef::EncryptedDataBagItem.encrypt_data_bag_item(data, secret)
|
16
|
+
write_json_file('data_bags/dev/passwords.json', encrypted_data)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Test that we can read an encrypted data bag value
|
20
|
+
# NOTE: This shells out to ssh, so may not be windows-compatible
|
21
|
+
def test_reading_encrypted_data_bag
|
22
|
+
write_nodefile(run_list: ["recipe[secret_cookbook]"])
|
23
|
+
assert_subcommand "cook"
|
24
|
+
actual = `ssh #{connection_string} cat /etc/admin_password`
|
25
|
+
assert_equal @password, actual
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'integration_helper'
|
2
|
+
|
3
|
+
class Centos5_6Test < IntegrationTest
|
4
|
+
def user
|
5
|
+
"root"
|
6
|
+
end
|
7
|
+
|
8
|
+
def image_id
|
9
|
+
"ami-3fe42456"
|
10
|
+
end
|
11
|
+
|
12
|
+
def default_apache_message
|
13
|
+
/Apache 2 Test Page/
|
14
|
+
end
|
15
|
+
|
16
|
+
include EmptyCook
|
17
|
+
include Apache2Cook
|
18
|
+
include EncryptedDataBag
|
19
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'integration_helper'
|
2
|
+
|
3
|
+
class Gentoo2011Test < IntegrationTest
|
4
|
+
def user
|
5
|
+
"root"
|
6
|
+
end
|
7
|
+
|
8
|
+
def image_id
|
9
|
+
"ami-ae49b7c7"
|
10
|
+
end
|
11
|
+
|
12
|
+
# `emerge chef` takes a very long time (~ 50 minutes) on an m1.small
|
13
|
+
# Uncoment this if you need to verify Gentoo operation
|
14
|
+
|
15
|
+
# include EmptyCook
|
16
|
+
# include Apache2Cook
|
17
|
+
# include EncryptedDataBag
|
18
|
+
end
|