test-kitchen 1.3.1 → 1.4.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.cane +2 -0
- data/.gitignore +4 -0
- data/CHANGELOG.md +45 -0
- data/Rakefile +15 -0
- data/features/kitchen_action_commands.feature +12 -9
- data/features/kitchen_defaults.feature +38 -0
- data/features/kitchen_init_command.feature +0 -1
- data/features/kitchen_list_command.feature +2 -2
- data/features/kitchen_login_command.feature +7 -1
- data/features/kitchen_test_command.feature +4 -4
- data/lib/kitchen.rb +40 -11
- data/lib/kitchen/cli.rb +38 -22
- data/lib/kitchen/command/list.rb +5 -2
- data/lib/kitchen/config.rb +45 -18
- data/lib/kitchen/configurable.rb +137 -1
- data/lib/kitchen/data_munger.rb +248 -17
- data/lib/kitchen/driver.rb +1 -1
- data/lib/kitchen/driver/base.rb +1 -83
- data/lib/kitchen/driver/dummy.rb +0 -5
- data/lib/kitchen/driver/ssh_base.rb +177 -22
- data/lib/kitchen/instance.rb +140 -20
- data/lib/kitchen/logger.rb +43 -8
- data/lib/kitchen/login_command.rb +14 -5
- data/lib/kitchen/platform.rb +19 -0
- data/lib/kitchen/provisioner.rb +5 -3
- data/lib/kitchen/provisioner/base.rb +46 -48
- data/lib/kitchen/provisioner/chef/common_sandbox.rb +322 -0
- data/lib/kitchen/provisioner/chef_base.rb +179 -286
- data/lib/kitchen/provisioner/chef_solo.rb +11 -5
- data/lib/kitchen/provisioner/chef_zero.rb +108 -94
- data/lib/kitchen/provisioner/dummy.rb +47 -0
- data/lib/kitchen/provisioner/shell.rb +45 -12
- data/lib/kitchen/rake_tasks.rb +1 -1
- data/lib/kitchen/ssh.rb +1 -1
- data/lib/kitchen/thor_tasks.rb +1 -1
- data/lib/kitchen/transport.rb +54 -0
- data/lib/kitchen/transport/base.rb +146 -0
- data/lib/kitchen/transport/dummy.rb +75 -0
- data/lib/kitchen/transport/ssh.rb +325 -0
- data/lib/kitchen/transport/winrm.rb +508 -0
- data/lib/kitchen/transport/winrm/command_executor.rb +188 -0
- data/lib/kitchen/transport/winrm/file_transporter.rb +454 -0
- data/lib/kitchen/transport/winrm/logging.rb +50 -0
- data/lib/kitchen/transport/winrm/template.rb +74 -0
- data/lib/kitchen/transport/winrm/tmp_zip.rb +187 -0
- data/lib/kitchen/verifier.rb +55 -0
- data/lib/kitchen/verifier/base.rb +191 -0
- data/lib/kitchen/verifier/busser.rb +266 -0
- data/lib/kitchen/verifier/dummy.rb +75 -0
- data/lib/kitchen/version.rb +1 -1
- data/spec/kitchen/cli_spec.rb +56 -0
- data/spec/kitchen/config_spec.rb +61 -20
- data/spec/kitchen/configurable_spec.rb +327 -1
- data/spec/kitchen/data_munger_spec.rb +777 -14
- data/spec/kitchen/driver/base_spec.rb +7 -38
- data/spec/kitchen/driver/dummy_spec.rb +0 -29
- data/spec/kitchen/driver/ssh_base_spec.rb +580 -236
- data/spec/kitchen/driver_spec.rb +1 -0
- data/spec/kitchen/instance_spec.rb +383 -83
- data/spec/kitchen/login_command_spec.rb +29 -10
- data/spec/kitchen/platform_spec.rb +58 -2
- data/spec/kitchen/provisioner/base_spec.rb +170 -18
- data/spec/kitchen/provisioner/chef_base_spec.rb +454 -104
- data/spec/kitchen/provisioner/chef_solo_spec.rb +307 -104
- data/spec/kitchen/provisioner/chef_zero_spec.rb +561 -230
- data/spec/kitchen/provisioner/dummy_spec.rb +91 -0
- data/spec/kitchen/provisioner/shell_spec.rb +158 -56
- data/spec/kitchen/provisioner_spec.rb +37 -0
- data/spec/kitchen/ssh_spec.rb +19 -19
- data/spec/kitchen/transport/base_spec.rb +89 -0
- data/spec/kitchen/transport/ssh_spec.rb +1147 -0
- data/spec/kitchen/transport/winrm/command_executor_spec.rb +400 -0
- data/spec/kitchen/transport/winrm/file_transporter_spec.rb +876 -0
- data/spec/kitchen/transport/winrm/logging_spec.rb +92 -0
- data/spec/kitchen/transport/winrm/template_spec.rb +51 -0
- data/spec/kitchen/transport/winrm/tmp_zip_spec.rb +132 -0
- data/spec/kitchen/transport/winrm_spec.rb +1069 -0
- data/spec/kitchen/transport_spec.rb +112 -0
- data/spec/kitchen/verifier/base_spec.rb +310 -0
- data/spec/kitchen/verifier/busser_spec.rb +540 -0
- data/spec/kitchen/verifier/dummy_spec.rb +91 -0
- data/spec/kitchen/verifier_spec.rb +120 -0
- data/spec/kitchen_spec.rb +7 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/support/powershell_max_size_spec.rb +40 -0
- data/support/busser_install_command.ps1 +14 -0
- data/support/busser_install_command.sh +15 -0
- data/support/check_files.ps1.erb +48 -0
- data/support/chef_base_init_command.ps1 +18 -0
- data/support/chef_base_init_command.sh +2 -0
- data/support/chef_base_install_command.ps1 +76 -0
- data/support/chef_base_install_command.sh +137 -0
- data/support/chef_zero_prepare_command_legacy.ps1 +9 -0
- data/support/chef_zero_prepare_command_legacy.sh +10 -0
- data/support/decode_files.ps1.erb +61 -0
- data/test-kitchen.gemspec +2 -0
- metadata +97 -8
- data/lib/kitchen/busser.rb +0 -316
- data/spec/kitchen/busser_spec.rb +0 -490
- data/support/chef_helpers.sh +0 -16
@@ -0,0 +1,91 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
4
|
+
#
|
5
|
+
# Copyright (C) 2015, Fletcher Nichol
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
|
19
|
+
require_relative "../../spec_helper"
|
20
|
+
|
21
|
+
require "logger"
|
22
|
+
require "stringio"
|
23
|
+
|
24
|
+
require "kitchen/verifier/dummy"
|
25
|
+
|
26
|
+
describe Kitchen::Verifier::Dummy do
|
27
|
+
|
28
|
+
let(:logged_output) { StringIO.new }
|
29
|
+
let(:logger) { Logger.new(logged_output) }
|
30
|
+
let(:platform) { stub(:os_type => nil, :shell_type => nil) }
|
31
|
+
let(:suite) { stub(:name => "fries") }
|
32
|
+
let(:state) { Hash.new }
|
33
|
+
|
34
|
+
let(:config) do
|
35
|
+
{ :test_base_path => "/basist", :kitchen_root => "/rooty" }
|
36
|
+
end
|
37
|
+
|
38
|
+
let(:instance) do
|
39
|
+
stub(
|
40
|
+
:name => "coolbeans",
|
41
|
+
:to_str => "instance",
|
42
|
+
:logger => logger,
|
43
|
+
:suite => suite,
|
44
|
+
:platform => platform
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
48
|
+
let(:verifier) do
|
49
|
+
Kitchen::Verifier::Dummy.new(config).finalize_config!(instance)
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "configuration" do
|
53
|
+
|
54
|
+
it "sets :sleep to 0 by default" do
|
55
|
+
verifier[:sleep].must_equal 0
|
56
|
+
end
|
57
|
+
|
58
|
+
it "sets :random_failure to false by default" do
|
59
|
+
verifier[:random_failure].must_equal false
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "#call" do
|
64
|
+
|
65
|
+
it "calls sleep if :sleep value is greater than 0" do
|
66
|
+
config[:sleep] = 12.5
|
67
|
+
verifier.expects(:sleep).with(12.5).returns(true)
|
68
|
+
|
69
|
+
verifier.call(state)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "raises ActionFailed if :fail is set" do
|
73
|
+
config[:fail] = true
|
74
|
+
|
75
|
+
proc { verifier.call(state) }.must_raise Kitchen::ActionFailed
|
76
|
+
end
|
77
|
+
|
78
|
+
it "randomly raises ActionFailed if :random_failure is set" do
|
79
|
+
config[:random_failure] = true
|
80
|
+
verifier.stubs(:randomly_fail?).returns(true)
|
81
|
+
|
82
|
+
proc { verifier.call(state) }.must_raise Kitchen::ActionFailed
|
83
|
+
end
|
84
|
+
|
85
|
+
it "logs a converge event to INFO" do
|
86
|
+
verifier.call(state)
|
87
|
+
|
88
|
+
logged_output.string.must_match(/^.+ INFO .+ \[Dummy\] Verify on .+$/)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
4
|
+
#
|
5
|
+
# Copyright (C) 2015, Fletcher Nichol
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
|
19
|
+
require_relative "../spec_helper"
|
20
|
+
|
21
|
+
require "kitchen/verifier"
|
22
|
+
|
23
|
+
require "kitchen/configurable"
|
24
|
+
module Kitchen
|
25
|
+
module Verifier
|
26
|
+
class Base
|
27
|
+
include Configurable
|
28
|
+
def initialize(config = {})
|
29
|
+
init_config(config)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
module Kitchen
|
36
|
+
|
37
|
+
module Verifier
|
38
|
+
|
39
|
+
class Coolbeans < Kitchen::Verifier::Base
|
40
|
+
end
|
41
|
+
|
42
|
+
class ItDepends < Kitchen::Verifier::Base
|
43
|
+
|
44
|
+
attr_reader :verify_call_count
|
45
|
+
|
46
|
+
def initialize(config = {})
|
47
|
+
@verify_call_count = 0
|
48
|
+
super
|
49
|
+
end
|
50
|
+
|
51
|
+
def verify_dependencies
|
52
|
+
@verify_call_count += 1
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
class UnstableDepends < Kitchen::Verifier::Base
|
57
|
+
|
58
|
+
def verify_dependencies
|
59
|
+
raise UserError, "Oh noes, you don't have software!"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe Kitchen::Verifier do
|
66
|
+
|
67
|
+
describe ".for_plugin" do
|
68
|
+
|
69
|
+
before do
|
70
|
+
Kitchen::Verifier.stubs(:require).returns(true)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "returns a verifier object of the correct class" do
|
74
|
+
verifier = Kitchen::Verifier.for_plugin("coolbeans", {})
|
75
|
+
|
76
|
+
verifier.must_be_kind_of Kitchen::Verifier::Coolbeans
|
77
|
+
end
|
78
|
+
|
79
|
+
it "returns a verifier initialized with its config" do
|
80
|
+
verifier = Kitchen::Verifier.for_plugin("coolbeans", :foo => "bar")
|
81
|
+
|
82
|
+
verifier[:foo].must_equal "bar"
|
83
|
+
end
|
84
|
+
|
85
|
+
it "calls #verify_dependencies on the transport object" do
|
86
|
+
verifier = Kitchen::Verifier.for_plugin("it_depends", {})
|
87
|
+
|
88
|
+
verifier.verify_call_count.must_equal 1
|
89
|
+
end
|
90
|
+
|
91
|
+
it "calls #verify_dependencies once per verifier require" do
|
92
|
+
Kitchen::Verifier.stubs(:require).returns(true, false)
|
93
|
+
verifier1 = Kitchen::Verifier.for_plugin("it_depends", {})
|
94
|
+
verifier1.verify_call_count.must_equal 1
|
95
|
+
verifier2 = Kitchen::Verifier.for_plugin("it_depends", {})
|
96
|
+
|
97
|
+
verifier2.verify_call_count.must_equal 0
|
98
|
+
end
|
99
|
+
|
100
|
+
it "raises ClientError if the verifier could not be required" do
|
101
|
+
Kitchen::Verifier.stubs(:require).raises(LoadError)
|
102
|
+
|
103
|
+
proc { Kitchen::Verifier.for_plugin("coolbeans", {}) }.
|
104
|
+
must_raise Kitchen::ClientError
|
105
|
+
end
|
106
|
+
|
107
|
+
it "raises ClientError if the verifier's class constant was not found" do
|
108
|
+
# pretend require worked
|
109
|
+
Kitchen::Verifier.stubs(:require).returns(true)
|
110
|
+
|
111
|
+
proc { Kitchen::Verifier.for_plugin("nope", {}) }.
|
112
|
+
must_raise Kitchen::ClientError
|
113
|
+
end
|
114
|
+
|
115
|
+
it "raises UserError if #verify_dependencies failes" do
|
116
|
+
proc { Kitchen::Verifier.for_plugin("unstable_depends", {}) }.
|
117
|
+
must_raise Kitchen::UserError
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
data/spec/kitchen_spec.rb
CHANGED
@@ -97,6 +97,13 @@ describe "Kitchen" do
|
|
97
97
|
must_match %r{ -- Kitchen: uhoh$}
|
98
98
|
end
|
99
99
|
|
100
|
+
it ".default_file_logger accepts a level and log_overwrite" do
|
101
|
+
l = Kitchen.default_file_logger(:error, false)
|
102
|
+
|
103
|
+
l.level.must_equal 3
|
104
|
+
l.log_overwrite.must_equal false
|
105
|
+
end
|
106
|
+
|
100
107
|
it "sets Kitchen.logger to a Kitchen::Logger" do
|
101
108
|
Kitchen.default_logger.must_be_instance_of Kitchen::Logger
|
102
109
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -0,0 +1,40 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
4
|
+
#
|
5
|
+
# Copyright (C) 2014, Fletcher Nichol
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
|
19
|
+
require_relative "../spec_helper"
|
20
|
+
|
21
|
+
# There is some double Base64 encoding going on when a PowerShell script is
|
22
|
+
# given to a CMD to invoke. We're in a battle with Windows' CMD max length and
|
23
|
+
# that what these specs are trying to ensure. This does lead to some less than
|
24
|
+
# ideal "code golfing" to reduce the code payload, but at the end of the day
|
25
|
+
# it's easier to see the entire context of the code vs. uploading partial code
|
26
|
+
# fragements and calling them on the remote side (not to mention more expensive
|
27
|
+
# in terms of PowerShell invocations).
|
28
|
+
|
29
|
+
describe "PowerShell script max size" do
|
30
|
+
|
31
|
+
MAX_POWERSHELL_SIZE = 3010
|
32
|
+
|
33
|
+
Dir.glob(File.join(File.dirname(__FILE__), "../../support/*.ps1*")).each do|script|
|
34
|
+
base = File.basename(script)
|
35
|
+
|
36
|
+
it "support/#{base} size must be less than #{MAX_POWERSHELL_SIZE} bytes" do
|
37
|
+
(IO.read(script).size < MAX_POWERSHELL_SIZE).must_equal true
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
if ((& "$ruby" "$gem" list busser -i) -ne "true") {
|
2
|
+
Write-Host "-----> Installing Busser ($version)`n"
|
3
|
+
& "$ruby" "$gem" install $gem_install_args.Split() 2>&1
|
4
|
+
} else {
|
5
|
+
Write-Host "-----> Busser installation detected ($version)`n"
|
6
|
+
}
|
7
|
+
|
8
|
+
if (-Not (Test-Path "$busser")) {
|
9
|
+
$gem_bindir = & "$ruby" -rrubygems -e "puts Gem.bindir.dup.gsub('/', '\\')"
|
10
|
+
& "$ruby" "$gem_bindir\busser" setup --type bat 2>&1
|
11
|
+
}
|
12
|
+
|
13
|
+
Write-Host " Installing Busser plugins: $plugins`n"
|
14
|
+
& "$busser" plugin install $plugins.Split() 2>&1
|
@@ -0,0 +1,15 @@
|
|
1
|
+
$gem list busser -i 2>&1 >/dev/null
|
2
|
+
if test $? -ne 0; then
|
3
|
+
echo "-----> Installing Busser ($version)"
|
4
|
+
$gem install $gem_install_args
|
5
|
+
else
|
6
|
+
echo "-----> Busser installation detected ($version)"
|
7
|
+
fi
|
8
|
+
|
9
|
+
if test ! -f "$BUSSER_ROOT/bin/busser"; then
|
10
|
+
gem_bindir=`$ruby -rrubygems -e "puts Gem.bindir"`
|
11
|
+
$gem_bindir/busser setup
|
12
|
+
fi
|
13
|
+
|
14
|
+
echo " Installing Busser plugins: $plugins"
|
15
|
+
$busser plugin install $plugins
|
@@ -0,0 +1,48 @@
|
|
1
|
+
$hash_file = "<%= hash_file %>"
|
2
|
+
|
3
|
+
Function Cleanup($o) { if (($o -ne $null) -and ($o.GetType().GetMethod("Dispose") -ne $null)) { $o.Dispose() } }
|
4
|
+
|
5
|
+
Function Decode-Base64File($src, $dst) {
|
6
|
+
Try {
|
7
|
+
$in = (Get-Item $src).OpenRead()
|
8
|
+
$b64 = New-Object -TypeName System.Security.Cryptography.FromBase64Transform
|
9
|
+
$m = [System.Security.Cryptography.CryptoStreamMode]::Read
|
10
|
+
$d = New-Object -TypeName System.Security.Cryptography.CryptoStream $in,$b64,$m
|
11
|
+
Copy-Stream $d ($out = [System.IO.File]::OpenWrite($dst))
|
12
|
+
} Finally { Cleanup $in; Cleanup $out; Cleanup $d }
|
13
|
+
}
|
14
|
+
|
15
|
+
Function Copy-Stream($src, $dst) { $b = New-Object Byte[] 4096; while (($i = $src.Read($b, 0, $b.Length)) -ne 0) { $dst.Write($b, 0, $i) } }
|
16
|
+
|
17
|
+
Function Check-Files($h) {
|
18
|
+
return $h.GetEnumerator() | ForEach-Object {
|
19
|
+
$dst = Unresolve-Path $_.Key
|
20
|
+
New-Object psobject -Property @{
|
21
|
+
chk_exists = ($exists = Test-Path $dst -PathType Leaf)
|
22
|
+
src_md5 = ($sMd5 = $_.Value)
|
23
|
+
dst_md5 = ($dMd5 = if ($exists) { Get-MD5Sum $dst } else { $null })
|
24
|
+
chk_dirty = ($dirty = if ($sMd5 -ne $dMd5) { $true } else { $false })
|
25
|
+
verifies = if ($dirty -eq $false) { $true } else { $false }
|
26
|
+
}
|
27
|
+
} | Select-Object -Property chk_exists,src_md5,dst_md5,chk_dirty,verifies
|
28
|
+
}
|
29
|
+
|
30
|
+
Function Get-MD5Sum($src) {
|
31
|
+
Try {
|
32
|
+
$c = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
|
33
|
+
$bytes = $c.ComputeHash(($in = (Get-Item $src).OpenRead()))
|
34
|
+
return ([System.BitConverter]::ToString($bytes)).Replace("-", "").ToLower()
|
35
|
+
} Finally { Cleanup $c; Cleanup $in }
|
36
|
+
}
|
37
|
+
|
38
|
+
Function Invoke-Input($in) {
|
39
|
+
$in = Unresolve-Path $in
|
40
|
+
Decode-Base64File $in ($decoded = "$($in).ps1")
|
41
|
+
$expr = Get-Content $decoded | Out-String
|
42
|
+
Remove-Item $in,$decoded -Force
|
43
|
+
return Invoke-Expression "$expr"
|
44
|
+
}
|
45
|
+
|
46
|
+
Function Unresolve-Path($p) { if ($p -eq $null) { return $null } else { return $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($p) } }
|
47
|
+
|
48
|
+
Check-Files (Invoke-Input $hash_file) | ConvertTo-Csv -NoTypeInformation
|
@@ -0,0 +1,18 @@
|
|
1
|
+
Function Delete-AllDirs($dirs) {
|
2
|
+
$dirs | ForEach-Object {
|
3
|
+
if (Test-Path ($path = Unresolve-Path $_)) { Remove-Item $path -Recurse -Force }
|
4
|
+
}
|
5
|
+
}
|
6
|
+
|
7
|
+
Function Unresolve-Path($p) {
|
8
|
+
if ($p -eq $null) { return $null }
|
9
|
+
else { return $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($p) }
|
10
|
+
}
|
11
|
+
|
12
|
+
Function Make-RootPath($p) {
|
13
|
+
$p = Unresolve-Path $p
|
14
|
+
if (-Not (Test-Path $p)) { New-Item $p -ItemType directory | Out-Null }
|
15
|
+
}
|
16
|
+
|
17
|
+
Delete-AllDirs $dirs
|
18
|
+
Make-RootPath $root_path
|
@@ -0,0 +1,76 @@
|
|
1
|
+
Function Check-UpdateChef($root, $version) {
|
2
|
+
if (-Not (Test-Path $root)) { return $true }
|
3
|
+
elseif ("$version" -eq "true") { return $false }
|
4
|
+
elseif ("$version" -eq "latest") { return $true }
|
5
|
+
|
6
|
+
Try { $chef_version = (& $root\bin\chef-solo.bat -v).split(" ", 2)[1] }
|
7
|
+
Catch { $chef_version = "" }
|
8
|
+
|
9
|
+
if ($chef_version.StartsWith($version)) { return $false }
|
10
|
+
else { return $true }
|
11
|
+
}
|
12
|
+
|
13
|
+
Function Get-ChefMetadata($url) {
|
14
|
+
Try { $response = ($c = Make-WebClient).DownloadString($url) }
|
15
|
+
Finally { if ($c -ne $null) { $c.Dispose() } }
|
16
|
+
|
17
|
+
$md = ConvertFrom-StringData $response.Replace("`t", "=")
|
18
|
+
return @($md.url, $md.md5)
|
19
|
+
}
|
20
|
+
|
21
|
+
Function Get-MD5Sum($src) {
|
22
|
+
Try {
|
23
|
+
$c = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
|
24
|
+
$bytes = $c.ComputeHash(($in = (Get-Item $src).OpenRead()))
|
25
|
+
return ([System.BitConverter]::ToString($bytes)).Replace("-", "").ToLower()
|
26
|
+
} Finally { if (($c -ne $null) -and ($c.GetType().GetMethod("Dispose") -ne $null)) { $c.Dispose() }; if ($in -ne $null) { $in.Dispose() } }
|
27
|
+
}
|
28
|
+
|
29
|
+
Function Download-Chef($md_url, $dst) {
|
30
|
+
$url, $md5 = Get-ChefMetadata $md_url
|
31
|
+
|
32
|
+
Try {
|
33
|
+
Log "Downloading package from $url"
|
34
|
+
($c = Make-WebClient).DownloadFile($url, $dst)
|
35
|
+
Log "Download complete."
|
36
|
+
} Finally { if ($c -ne $null) { $c.Dispose() } }
|
37
|
+
|
38
|
+
if (($dmd5 = Get-MD5Sum $dst) -eq $md5) { Log "Successfully verified $dst" }
|
39
|
+
else { throw "MD5 for $dst $dmd5 does not match $md5" }
|
40
|
+
}
|
41
|
+
|
42
|
+
Function Install-Chef($msi) {
|
43
|
+
Log "Installing Chef Omnibus package $msi"
|
44
|
+
$p = Start-Process -FilePath "msiexec.exe" -ArgumentList "/qn /i $msi" -Passthru -Wait
|
45
|
+
|
46
|
+
if ($p.ExitCode -ne 0) { throw "msiexec was not successful. Received exit code $($p.ExitCode)" }
|
47
|
+
|
48
|
+
Remove-Item $msi -Force
|
49
|
+
Log "Installation complete"
|
50
|
+
}
|
51
|
+
|
52
|
+
Function Log($m) { Write-Host " $m`n" }
|
53
|
+
|
54
|
+
Function Make-WebClient {
|
55
|
+
$proxy = New-Object -TypeName System.Net.WebProxy
|
56
|
+
$proxy.Address = $env:http_proxy
|
57
|
+
$client = New-Object -TypeName System.Net.WebClient
|
58
|
+
$client.Proxy = $proxy
|
59
|
+
return $client
|
60
|
+
}
|
61
|
+
|
62
|
+
Function Unresolve-Path($p) {
|
63
|
+
if ($p -eq $null) { return $null }
|
64
|
+
else { return $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($p) }
|
65
|
+
}
|
66
|
+
|
67
|
+
$chef_omnibus_root = Unresolve-Path $chef_omnibus_root
|
68
|
+
$msi = Unresolve-Path $msi
|
69
|
+
|
70
|
+
if (Check-UpdateChef $chef_omnibus_root $version) {
|
71
|
+
Write-Host "-----> Installing Chef Omnibus ($pretty_version)`n"
|
72
|
+
Download-Chef "$chef_metadata_url" $msi
|
73
|
+
Install-Chef $msi
|
74
|
+
} else {
|
75
|
+
Write-Host "-----> Chef Omnibus installation detected ($pretty_version)`n"
|
76
|
+
}
|