knife-windows 0.5.3 → 0.5.4
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 +9 -0
- data/README.rdoc +4 -0
- data/knife-windows.gemspec +1 -1
- data/lib/chef/knife/bootstrap/windows-shell.erb +6 -0
- data/lib/chef/knife/bootstrap_windows_base.rb +175 -0
- data/lib/chef/knife/bootstrap_windows_ssh.rb +2 -39
- data/lib/chef/knife/bootstrap_windows_winrm.rb +4 -95
- data/lib/chef/knife/core/windows_bootstrap_context.rb +10 -2
- data/lib/chef/knife/winrm.rb +25 -66
- data/lib/chef/knife/winrm_base.rb +98 -0
- data/lib/knife-windows/version.rb +1 -1
- metadata +6 -4
- data/lib/chef/knife/mixin/windows/bootstrap.rb +0 -94
data/CHANGELOG
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
Release Notes - Knife Windows Plugin - Version 0.5.4
|
2
|
+
|
3
|
+
** Bug
|
4
|
+
* [KNIFE_WINDOWS-7] - Exception: NoMethodError: undefined method `env_namespace' for Savon:Module
|
5
|
+
* [KNIFE_WINDOWS-8] - winrm based bootstrap fails with 'Bad HTTP response returned from server (500)'
|
6
|
+
|
7
|
+
|
8
|
+
** New Feature
|
9
|
+
* [KNIFE_WINDOWS-6] - default bootstrap template should support encrypted_data_bag_secret
|
data/README.rdoc
CHANGED
@@ -90,6 +90,10 @@ The Chef and Ohai gem installations (that occur during bootstrap) take more memo
|
|
90
90
|
|
91
91
|
C:\Users\Administrator> winrm set winrm/config/winrs @{MaxMemoryPerShellMB="300"}
|
92
92
|
|
93
|
+
Bootstrap commands can take longer than the WinRM default 60 seconds to complete, bump to 30 minutes:
|
94
|
+
|
95
|
+
C:\Users\Administrator> winrm set winrm/config @{MaxTimeoutms="1800000"}
|
96
|
+
|
93
97
|
WinRM supports both the HTTP and HTTPS transports and the following authentication schemes: Kerberos, Digest, Certificate and Basic. The details of these authentication transports are outside of the scope of this README but details can be found on the {WinRM configuration guide}[http://msdn.microsoft.com/en-us/library/aa384372(v=vs.85).aspx]. Currently, this plugin support Kerberos and Basic authentication schemes.
|
94
98
|
|
95
99
|
For development and testing purposes, unencrypted traffic with Basic authentication can make things easier:
|
data/knife-windows.gemspec
CHANGED
@@ -15,7 +15,7 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.description = s.summary
|
16
16
|
|
17
17
|
s.required_ruby_version = ">= 1.9.1"
|
18
|
-
s.add_dependency "em-winrm", "= 0.
|
18
|
+
s.add_dependency "em-winrm", "= 0.5.2"
|
19
19
|
|
20
20
|
s.files = `git ls-files`.split("\n")
|
21
21
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
@@ -44,6 +44,12 @@ cmd.exe /C C:\ruby\bin\gem install chef --no-rdoc --no-ri --verbose <%= bootstra
|
|
44
44
|
<%= validation_key %>
|
45
45
|
)
|
46
46
|
|
47
|
+
<% if @config[:encrypted_data_bag_secret] -%>
|
48
|
+
> C:\chef\encrypted_data_bag_secret (
|
49
|
+
<%= encrypted_data_bag_secret %>
|
50
|
+
)
|
51
|
+
<% end -%>
|
52
|
+
|
47
53
|
> C:\chef\client.rb (
|
48
54
|
echo.require 'win32ole'
|
49
55
|
echo.WIN32OLE.codepage = WIN32OLE::CP_UTF8
|
@@ -0,0 +1,175 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Seth Chisamore (<schisamo@opscode.com>)
|
3
|
+
# Copyright:: Copyright (c) 2011 Opscode, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'chef/knife'
|
20
|
+
require 'chef/encrypted_data_bag_item'
|
21
|
+
|
22
|
+
class Chef
|
23
|
+
class Knife
|
24
|
+
module BootstrapWindowsBase
|
25
|
+
|
26
|
+
# :nodoc:
|
27
|
+
# Would prefer to do this in a rational way, but can't be done b/c of
|
28
|
+
# Mixlib::CLI's design :(
|
29
|
+
def self.included(includer)
|
30
|
+
includer.class_eval do
|
31
|
+
|
32
|
+
deps do
|
33
|
+
require 'readline'
|
34
|
+
require 'chef/json_compat'
|
35
|
+
end
|
36
|
+
|
37
|
+
option :chef_node_name,
|
38
|
+
:short => "-N NAME",
|
39
|
+
:long => "--node-name NAME",
|
40
|
+
:description => "The Chef node name for your new node"
|
41
|
+
|
42
|
+
option :prerelease,
|
43
|
+
:long => "--prerelease",
|
44
|
+
:description => "Install the pre-release chef gems"
|
45
|
+
|
46
|
+
option :bootstrap_version,
|
47
|
+
:long => "--bootstrap-version VERSION",
|
48
|
+
:description => "The version of Chef to install",
|
49
|
+
:proc => Proc.new { |v| Chef::Config[:knife][:bootstrap_version] = v }
|
50
|
+
|
51
|
+
option :bootstrap_proxy,
|
52
|
+
:long => "--bootstrap-proxy PROXY_URL",
|
53
|
+
:description => "The proxy server for the node being bootstrapped",
|
54
|
+
:proc => Proc.new { |p| Chef::Config[:knife][:bootstrap_proxy] = p }
|
55
|
+
|
56
|
+
option :distro,
|
57
|
+
:short => "-d DISTRO",
|
58
|
+
:long => "--distro DISTRO",
|
59
|
+
:description => "Bootstrap a distro using a template",
|
60
|
+
:default => "windows-shell"
|
61
|
+
|
62
|
+
option :template_file,
|
63
|
+
:long => "--template-file TEMPLATE",
|
64
|
+
:description => "Full path to location of template to use",
|
65
|
+
:default => false
|
66
|
+
|
67
|
+
option :run_list,
|
68
|
+
:short => "-r RUN_LIST",
|
69
|
+
:long => "--run-list RUN_LIST",
|
70
|
+
:description => "Comma separated list of roles/recipes to apply",
|
71
|
+
:proc => lambda { |o| o.split(",") },
|
72
|
+
:default => []
|
73
|
+
|
74
|
+
option :encrypted_data_bag_secret,
|
75
|
+
:short => "-s SECRET",
|
76
|
+
:long => "--secret ",
|
77
|
+
:description => "The secret key to use to decrypt data bag item values. Will be rendered on the node at c:/chef/encrypted_data_bag_secret and set in the rendered client config.",
|
78
|
+
:default => false
|
79
|
+
|
80
|
+
option :encrypted_data_bag_secret_file,
|
81
|
+
:long => "--secret-file SECRET_FILE",
|
82
|
+
:description => "A file containing the secret key to use to encrypt data bag item values. Will be rendered on the node at c:/chef/encrypted_data_bag_secret and set in the rendered client config."
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# TODO: This should go away when CHEF-2193 is fixed
|
88
|
+
def load_template(template=nil)
|
89
|
+
# Are we bootstrapping using an already shipped template?
|
90
|
+
if config[:template_file]
|
91
|
+
bootstrap_files = config[:template_file]
|
92
|
+
else
|
93
|
+
bootstrap_files = []
|
94
|
+
bootstrap_files << File.join(File.dirname(__FILE__), 'bootstrap', "#{config[:distro]}.erb")
|
95
|
+
bootstrap_files << File.join(Dir.pwd, ".chef", "bootstrap", "#{config[:distro]}.erb")
|
96
|
+
bootstrap_files << File.join(ENV['HOME'], '.chef', 'bootstrap', "#{config[:distro]}.erb")
|
97
|
+
bootstrap_files << Gem.find_files(File.join("chef","knife","bootstrap","#{config[:distro]}.erb"))
|
98
|
+
bootstrap_files.flatten!
|
99
|
+
end
|
100
|
+
|
101
|
+
template = Array(bootstrap_files).find do |bootstrap_template|
|
102
|
+
Chef::Log.debug("Looking for bootstrap template in #{File.dirname(bootstrap_template)}")
|
103
|
+
::File.exists?(bootstrap_template)
|
104
|
+
end
|
105
|
+
|
106
|
+
unless template
|
107
|
+
ui.info("Can not find bootstrap definition for #{config[:distro]}")
|
108
|
+
raise Errno::ENOENT
|
109
|
+
end
|
110
|
+
|
111
|
+
Chef::Log.debug("Found bootstrap template in #{File.dirname(template)}")
|
112
|
+
|
113
|
+
IO.read(template).chomp
|
114
|
+
end
|
115
|
+
|
116
|
+
def render_template(template=nil)
|
117
|
+
if config[:encrypted_data_bag_secret_file]
|
118
|
+
config[:encrypted_data_bag_secret] = Chef::EncryptedDataBagItem.load_secret(config[:encrypted_data_bag_secret_file])
|
119
|
+
end
|
120
|
+
context = Knife::Core::WindowsBootstrapContext.new(config, config[:run_list], Chef::Config)
|
121
|
+
Erubis::Eruby.new(template).evaluate(context)
|
122
|
+
end
|
123
|
+
|
124
|
+
def bootstrap(proto=nil)
|
125
|
+
|
126
|
+
validate_name_args!
|
127
|
+
|
128
|
+
@node_name = Array(@name_args).first
|
129
|
+
# back compat--templates may use this setting:
|
130
|
+
config[:server_name] = @node_name
|
131
|
+
|
132
|
+
STDOUT.sync = STDERR.sync = true
|
133
|
+
|
134
|
+
ui.info("Bootstrapping Chef on #{ui.color(@node_name, :bold)}")
|
135
|
+
# create a bootstrap.bat file on the node
|
136
|
+
# we have to run the remote commands in 2047 char chunks
|
137
|
+
create_bootstrap_bat_command do |command_chunk, chunk_num|
|
138
|
+
run_command("cmd.exe /C echo \"Rendering bootstrap.bat chunk #{chunk_num}\" && #{command_chunk}").run
|
139
|
+
end
|
140
|
+
|
141
|
+
# execute the bootstrap.bat file
|
142
|
+
run_command(bootstrap_command).run
|
143
|
+
end
|
144
|
+
|
145
|
+
def bootstrap_command
|
146
|
+
@bootstrap_command ||= "cmd.exe /C #{bootstrap_bat_file}"
|
147
|
+
end
|
148
|
+
|
149
|
+
def create_bootstrap_bat_command(&block)
|
150
|
+
bootstrap_bat = []
|
151
|
+
chunk_num = 0
|
152
|
+
render_template(load_template(config[:bootstrap_template])).each_line do |line|
|
153
|
+
# escape WIN BATCH special chars
|
154
|
+
line.gsub!(/[(<|>)^]/).each{|m| "^#{m}"}
|
155
|
+
# windows commands are limited to 2047 characters
|
156
|
+
if((bootstrap_bat + [line]).join(" && ").size > 2047 )
|
157
|
+
yield bootstrap_bat.join(" && "), chunk_num += 1
|
158
|
+
bootstrap_bat = []
|
159
|
+
end
|
160
|
+
bootstrap_bat << ">> #{bootstrap_bat_file} (echo.#{line.chomp.strip})"
|
161
|
+
end
|
162
|
+
yield bootstrap_bat.join(" && "), chunk_num += 1
|
163
|
+
end
|
164
|
+
|
165
|
+
def bootstrap_bat_file
|
166
|
+
"%TEMP%\\bootstrap.bat"
|
167
|
+
end
|
168
|
+
|
169
|
+
def locate_config_value(key)
|
170
|
+
key = key.to_sym
|
171
|
+
Chef::Config[:knife][key] || config[key]
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
@@ -16,13 +16,13 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
|
19
|
-
require
|
19
|
+
require 'chef/knife/bootstrap_windows_base'
|
20
20
|
|
21
21
|
class Chef
|
22
22
|
class Knife
|
23
23
|
class BootstrapWindowsSsh < Bootstrap
|
24
24
|
|
25
|
-
include Chef::
|
25
|
+
include Chef::Knife::BootstrapWindowsBase
|
26
26
|
|
27
27
|
deps do
|
28
28
|
require 'chef/knife/core/windows_bootstrap_context'
|
@@ -59,43 +59,6 @@ class Chef
|
|
59
59
|
:long => "--identity-file IDENTITY_FILE",
|
60
60
|
:description => "The SSH identity file used for authentication"
|
61
61
|
|
62
|
-
option :chef_node_name,
|
63
|
-
:short => "-N NAME",
|
64
|
-
:long => "--node-name NAME",
|
65
|
-
:description => "The Chef node name for your new node"
|
66
|
-
|
67
|
-
option :prerelease,
|
68
|
-
:long => "--prerelease",
|
69
|
-
:description => "Install the pre-release chef gems"
|
70
|
-
|
71
|
-
option :bootstrap_version,
|
72
|
-
:long => "--bootstrap-version VERSION",
|
73
|
-
:description => "The version of Chef to install",
|
74
|
-
:proc => Proc.new { |v| Chef::Config[:knife][:bootstrap_version] = v }
|
75
|
-
|
76
|
-
option :bootstrap_proxy,
|
77
|
-
:long => "--bootstrap-proxy PROXY_URL",
|
78
|
-
:description => "The proxy server for the node being bootstrapped",
|
79
|
-
:proc => Proc.new { |p| Chef::Config[:knife][:bootstrap_proxy] = p }
|
80
|
-
|
81
|
-
option :distro,
|
82
|
-
:short => "-d DISTRO",
|
83
|
-
:long => "--distro DISTRO",
|
84
|
-
:description => "Bootstrap a distro using a template",
|
85
|
-
:default => "windows-shell"
|
86
|
-
|
87
|
-
option :template_file,
|
88
|
-
:long => "--template-file TEMPLATE",
|
89
|
-
:description => "Full path to location of template to use",
|
90
|
-
:default => false
|
91
|
-
|
92
|
-
option :run_list,
|
93
|
-
:short => "-r RUN_LIST",
|
94
|
-
:long => "--run-list RUN_LIST",
|
95
|
-
:description => "Comma separated list of roles/recipes to apply",
|
96
|
-
:proc => lambda { |o| o.split(",") },
|
97
|
-
:default => []
|
98
|
-
|
99
62
|
option :no_host_key_verify,
|
100
63
|
:long => "--no-host-key-verify",
|
101
64
|
:description => "Disable host key verification",
|
@@ -16,13 +16,15 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
|
19
|
-
require
|
19
|
+
require 'chef/knife/bootstrap_windows_base'
|
20
|
+
require 'chef/knife/winrm_base'
|
20
21
|
|
21
22
|
class Chef
|
22
23
|
class Knife
|
23
24
|
class BootstrapWindowsWinrm < Bootstrap
|
24
25
|
|
25
|
-
include Chef::
|
26
|
+
include Chef::Knife::BootstrapWindowsBase
|
27
|
+
include Chef::Knife::WinrmBase
|
26
28
|
|
27
29
|
deps do
|
28
30
|
require 'chef/knife/core/windows_bootstrap_context'
|
@@ -33,99 +35,6 @@ class Chef
|
|
33
35
|
|
34
36
|
banner "knife bootstrap windows winrm FQDN (options)"
|
35
37
|
|
36
|
-
option :winrm_user,
|
37
|
-
:short => "-x USERNAME",
|
38
|
-
:long => "--winrm-user USERNAME",
|
39
|
-
:description => "The WinRM username",
|
40
|
-
:default => "Administrator",
|
41
|
-
:proc => Proc.new { |key| Chef::Config[:knife][:winrm_user] = key }
|
42
|
-
|
43
|
-
option :winrm_password,
|
44
|
-
:short => "-P PASSWORD",
|
45
|
-
:long => "--winrm-password PASSWORD",
|
46
|
-
:description => "The WinRM password",
|
47
|
-
:proc => Proc.new { |key| Chef::Config[:knife][:winrm_password] = key }
|
48
|
-
|
49
|
-
option :winrm_port,
|
50
|
-
:short => "-p PORT",
|
51
|
-
:long => "--winrm-port PORT",
|
52
|
-
:description => "The WinRM port, by default this is 5985",
|
53
|
-
:default => "5985",
|
54
|
-
:proc => Proc.new { |key| Chef::Config[:knife][:winrm_port] = key }
|
55
|
-
|
56
|
-
option :identity_file,
|
57
|
-
:short => "-i IDENTITY_FILE",
|
58
|
-
:long => "--identity-file IDENTITY_FILE",
|
59
|
-
:description => "The SSH identity file used for authentication"
|
60
|
-
|
61
|
-
option :winrm_transport,
|
62
|
-
:short => "-t TRANSPORT",
|
63
|
-
:long => "--winrm-transport TRANSPORT",
|
64
|
-
:description => "The WinRM transport type. valid choices are [ssl, plaintext]",
|
65
|
-
:default => 'plaintext',
|
66
|
-
:proc => Proc.new { |transport| Chef::Config[:knife][:winrm_transport] = transport }
|
67
|
-
|
68
|
-
option :keytab_file,
|
69
|
-
:short => "-i KEYTAB_FILE",
|
70
|
-
:long => "--keytab-file KEYTAB_FILE",
|
71
|
-
:description => "The Kerberos keytab file used for authentication",
|
72
|
-
:proc => Proc.new { |keytab| Chef::Config[:knife][:keytab_file] = keytab }
|
73
|
-
|
74
|
-
option :kerberos_realm,
|
75
|
-
:short => "-R KERBEROS_REALM",
|
76
|
-
:long => "--kerberos-realm KERBEROS_REALM",
|
77
|
-
:description => "The Kerberos realm used for authentication",
|
78
|
-
:proc => Proc.new { |realm| Chef::Config[:knife][:kerberos_realm] = realm }
|
79
|
-
|
80
|
-
option :kerberos_service,
|
81
|
-
:short => "-S KERBEROS_SERVICE",
|
82
|
-
:long => "--kerberos-service KERBEROS_SERVICE",
|
83
|
-
:description => "The Kerberos service used for authentication",
|
84
|
-
:proc => Proc.new { |service| Chef::Config[:knife][:kerberos_service] = service }
|
85
|
-
|
86
|
-
option :ca_trust_file,
|
87
|
-
:short => "-f CA_TRUST_FILE",
|
88
|
-
:long => "--ca-trust-file CA_TRUST_FILE",
|
89
|
-
:description => "The Certificate Authority (CA) trust file used for SSL transport",
|
90
|
-
:proc => Proc.new { |trust| Chef::Config[:knife][:ca_trust_file] = trust }
|
91
|
-
|
92
|
-
option :chef_node_name,
|
93
|
-
:short => "-N NAME",
|
94
|
-
:long => "--node-name NAME",
|
95
|
-
:description => "The Chef node name for your new node"
|
96
|
-
|
97
|
-
option :prerelease,
|
98
|
-
:long => "--prerelease",
|
99
|
-
:description => "Install the pre-release chef gems"
|
100
|
-
|
101
|
-
option :bootstrap_version,
|
102
|
-
:long => "--bootstrap-version VERSION",
|
103
|
-
:description => "The version of Chef to install",
|
104
|
-
:proc => Proc.new { |v| Chef::Config[:knife][:bootstrap_version] = v }
|
105
|
-
|
106
|
-
option :bootstrap_proxy,
|
107
|
-
:long => "--bootstrap-proxy PROXY_URL",
|
108
|
-
:description => "The proxy server for the node being bootstrapped",
|
109
|
-
:proc => Proc.new { |p| Chef::Config[:knife][:bootstrap_proxy] = p }
|
110
|
-
|
111
|
-
option :distro,
|
112
|
-
:short => "-d DISTRO",
|
113
|
-
:long => "--distro DISTRO",
|
114
|
-
:description => "Bootstrap a distro using a template",
|
115
|
-
:default => "windows-shell"
|
116
|
-
|
117
|
-
option :template_file,
|
118
|
-
:long => "--template-file TEMPLATE",
|
119
|
-
:description => "Full path to location of template to use",
|
120
|
-
:default => false
|
121
|
-
|
122
|
-
option :run_list,
|
123
|
-
:short => "-r RUN_LIST",
|
124
|
-
:long => "--run-list RUN_LIST",
|
125
|
-
:description => "Comma separated list of roles/recipes to apply",
|
126
|
-
:proc => lambda { |o| o.split(",") },
|
127
|
-
:default => []
|
128
|
-
|
129
38
|
def run
|
130
39
|
bootstrap
|
131
40
|
end
|
@@ -40,6 +40,10 @@ class Chef
|
|
40
40
|
escape_and_echo(super)
|
41
41
|
end
|
42
42
|
|
43
|
+
def encrypted_data_bag_secret
|
44
|
+
escape_and_echo(@config[:encrypted_data_bag_secret])
|
45
|
+
end
|
46
|
+
|
43
47
|
def config_content
|
44
48
|
client_rb = <<-CONFIG
|
45
49
|
log_level :info
|
@@ -60,13 +64,17 @@ CONFIG
|
|
60
64
|
else
|
61
65
|
client_rb << "# Using default node name (fqdn)\n"
|
62
66
|
end
|
63
|
-
|
67
|
+
|
64
68
|
if knife_config[:bootstrap_proxy]
|
65
69
|
client_rb << "\n"
|
66
70
|
client_rb << %Q{http_proxy "#{knife_config[:bootstrap_proxy]}"\n}
|
67
71
|
client_rb << %Q{https_proxy "#{knife_config[:bootstrap_proxy]}"\n}
|
68
72
|
end
|
69
|
-
|
73
|
+
|
74
|
+
if @config[:encrypted_data_bag_secret]
|
75
|
+
client_rb << %Q{encrypted_data_bag_secret "c:/chef/encrypted_data_bag_secret"\n}
|
76
|
+
end
|
77
|
+
|
70
78
|
escape_and_echo(client_rb)
|
71
79
|
end
|
72
80
|
|
data/lib/chef/knife/winrm.rb
CHANGED
@@ -17,14 +17,18 @@
|
|
17
17
|
#
|
18
18
|
|
19
19
|
require 'chef/knife'
|
20
|
+
require 'chef/knife/winrm_base'
|
20
21
|
|
21
22
|
class Chef
|
22
23
|
class Knife
|
23
24
|
class Winrm < Knife
|
24
25
|
|
26
|
+
include Chef::Knife::WinrmBase
|
27
|
+
|
25
28
|
deps do
|
26
29
|
require 'readline'
|
27
30
|
require 'chef/search/query'
|
31
|
+
require 'em-winrm'
|
28
32
|
end
|
29
33
|
|
30
34
|
attr_writer :password
|
@@ -44,65 +48,7 @@ class Chef
|
|
44
48
|
:description => "QUERY is a space separated list of servers",
|
45
49
|
:default => false
|
46
50
|
|
47
|
-
option :winrm_user,
|
48
|
-
:short => "-x USERNAME",
|
49
|
-
:long => "--winrm-user USERNAME",
|
50
|
-
:description => "The WinRM username",
|
51
|
-
:default => "Administrator",
|
52
|
-
:proc => Proc.new { |key| Chef::Config[:knife][:winrm_user] = key }
|
53
|
-
|
54
|
-
option :winrm_password,
|
55
|
-
:short => "-P PASSWORD",
|
56
|
-
:long => "--winrm-password PASSWORD",
|
57
|
-
:description => "The WinRM password",
|
58
|
-
:proc => Proc.new { |key| Chef::Config[:knife][:winrm_password] = key }
|
59
|
-
|
60
|
-
option :winrm_port,
|
61
|
-
:short => "-p PORT",
|
62
|
-
:long => "--winrm-port PORT",
|
63
|
-
:description => "The WinRM port",
|
64
|
-
:default => "5985",
|
65
|
-
:proc => Proc.new { |key| Chef::Config[:knife][:winrm_port] = key }
|
66
|
-
|
67
|
-
option :winrm_transport,
|
68
|
-
:short => "-t TRANSPORT",
|
69
|
-
:long => "--winrm-transport TRANSPORT",
|
70
|
-
:description => "The WinRM transport type: ssl, or plaintext",
|
71
|
-
:default => 'plaintext',
|
72
|
-
:proc => Proc.new { |transport| Chef::Config[:knife][:winrm_transport] = transport }
|
73
|
-
|
74
|
-
option :kerberos_keytab_file,
|
75
|
-
:short => "-i KEYTAB_FILE",
|
76
|
-
:long => "--keytab-file KEYTAB_FILE",
|
77
|
-
:description => "The Kerberos keytab file used for authentication",
|
78
|
-
:proc => Proc.new { |keytab| Chef::Config[:knife][:kerberos_keytab_file] = keytab }
|
79
|
-
|
80
|
-
option :kerberos_realm,
|
81
|
-
:short => "-R KERBEROS_REALM",
|
82
|
-
:long => "--kerberos-realm KERBEROS_REALM",
|
83
|
-
:description => "The Kerberos realm used for authentication",
|
84
|
-
:proc => Proc.new { |realm| Chef::Config[:knife][:kerberos_realm] = realm }
|
85
|
-
|
86
|
-
option :kerberos_service,
|
87
|
-
:short => "-S KERBEROS_SERVICE",
|
88
|
-
:long => "--kerberos-service KERBEROS_SERVICE",
|
89
|
-
:description => "The Kerberos service used for authentication",
|
90
|
-
:proc => Proc.new { |service| Chef::Config[:knife][:kerberos_service] = service }
|
91
|
-
|
92
|
-
option :keytab_file,
|
93
|
-
:short => "-i KEYTAB_FILE",
|
94
|
-
:long => "--keytab-file KEYTAB_FILE",
|
95
|
-
:description => "The Kerberos keytab file used for authentication",
|
96
|
-
:proc => Proc.new { |keytab| Chef::Config[:knife][:keytab_file] = keytab }
|
97
|
-
|
98
|
-
option :ca_trust_file,
|
99
|
-
:short => "-f CA_TRUST_FILE",
|
100
|
-
:long => "--ca-trust-file CA_TRUST_FILE",
|
101
|
-
:description => "The Certificate Authority (CA) trust file used for SSL transport",
|
102
|
-
:proc => Proc.new { |trust| Chef::Config[:knife][:ca_trust_file] = trust }
|
103
|
-
|
104
51
|
def session
|
105
|
-
require 'em-winrm'
|
106
52
|
session_opts = {}
|
107
53
|
session_opts[:logger] = Chef::Log.logger if Chef::Log.level == :debug
|
108
54
|
@session ||= begin
|
@@ -151,6 +97,7 @@ class Chef
|
|
151
97
|
session_opts[:realm] = Chef::Config[:knife][:kerberos_realm] if Chef::Config[:knife][:kerberos_realm]
|
152
98
|
session_opts[:service] = Chef::Config[:knife][:kerberos_service] if Chef::Config[:knife][:kerberos_service]
|
153
99
|
session_opts[:ca_trust_path] = Chef::Config[:knife][:ca_trust_file] if Chef::Config[:knife][:ca_trust_file]
|
100
|
+
session_opts[:operation_timeout] = 1800 # 30 min OperationTimeout for long bootstraps fix for KNIFE_WINDOWS-8
|
154
101
|
|
155
102
|
if config.keys.any? {|k| k.to_s =~ /kerberos/ }
|
156
103
|
session_opts[:transport] = :kerberos
|
@@ -243,16 +190,28 @@ class Chef
|
|
243
190
|
end
|
244
191
|
|
245
192
|
def run
|
246
|
-
|
193
|
+
STDOUT.sync = STDERR.sync = true
|
247
194
|
|
248
|
-
|
195
|
+
begin
|
196
|
+
@longest = 0
|
249
197
|
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
198
|
+
configure_session
|
199
|
+
|
200
|
+
case @name_args[1]
|
201
|
+
when "interactive"
|
202
|
+
interactive
|
203
|
+
else
|
204
|
+
winrm_command(@name_args[1..-1].join(" "))
|
205
|
+
session.close
|
206
|
+
end
|
207
|
+
rescue WinRM::WinRMHTTPTransportError => e
|
208
|
+
case e.message
|
209
|
+
when /401/
|
210
|
+
ui.error "Failed to authenticate to #{@name_args[0].split(" ")} as #{config[:winrm_user]}"
|
211
|
+
ui.info "Response: #{e.message}"
|
212
|
+
else
|
213
|
+
raise e
|
214
|
+
end
|
256
215
|
end
|
257
216
|
end
|
258
217
|
|
@@ -0,0 +1,98 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Seth Chisamore (<schisamo@opscode.com>)
|
3
|
+
# Copyright:: Copyright (c) 2011 Opscode, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'chef/knife'
|
20
|
+
require 'chef/encrypted_data_bag_item'
|
21
|
+
|
22
|
+
class Chef
|
23
|
+
class Knife
|
24
|
+
module WinrmBase
|
25
|
+
|
26
|
+
# :nodoc:
|
27
|
+
# Would prefer to do this in a rational way, but can't be done b/c of
|
28
|
+
# Mixlib::CLI's design :(
|
29
|
+
def self.included(includer)
|
30
|
+
includer.class_eval do
|
31
|
+
|
32
|
+
deps do
|
33
|
+
require 'readline'
|
34
|
+
require 'chef/json_compat'
|
35
|
+
end
|
36
|
+
|
37
|
+
option :winrm_user,
|
38
|
+
:short => "-x USERNAME",
|
39
|
+
:long => "--winrm-user USERNAME",
|
40
|
+
:description => "The WinRM username",
|
41
|
+
:default => "Administrator",
|
42
|
+
:proc => Proc.new { |key| Chef::Config[:knife][:winrm_user] = key }
|
43
|
+
|
44
|
+
option :winrm_password,
|
45
|
+
:short => "-P PASSWORD",
|
46
|
+
:long => "--winrm-password PASSWORD",
|
47
|
+
:description => "The WinRM password",
|
48
|
+
:proc => Proc.new { |key| Chef::Config[:knife][:winrm_password] = key }
|
49
|
+
|
50
|
+
option :winrm_port,
|
51
|
+
:short => "-p PORT",
|
52
|
+
:long => "--winrm-port PORT",
|
53
|
+
:description => "The WinRM port, by default this is 5985",
|
54
|
+
:default => "5985",
|
55
|
+
:proc => Proc.new { |key| Chef::Config[:knife][:winrm_port] = key }
|
56
|
+
|
57
|
+
option :identity_file,
|
58
|
+
:short => "-i IDENTITY_FILE",
|
59
|
+
:long => "--identity-file IDENTITY_FILE",
|
60
|
+
:description => "The SSH identity file used for authentication"
|
61
|
+
|
62
|
+
option :winrm_transport,
|
63
|
+
:short => "-t TRANSPORT",
|
64
|
+
:long => "--winrm-transport TRANSPORT",
|
65
|
+
:description => "The WinRM transport type. valid choices are [ssl, plaintext]",
|
66
|
+
:default => 'plaintext',
|
67
|
+
:proc => Proc.new { |transport| Chef::Config[:knife][:winrm_transport] = transport }
|
68
|
+
|
69
|
+
option :kerberos_keytab_file,
|
70
|
+
:short => "-i KEYTAB_FILE",
|
71
|
+
:long => "--keytab-file KEYTAB_FILE",
|
72
|
+
:description => "The Kerberos keytab file used for authentication",
|
73
|
+
:proc => Proc.new { |keytab| Chef::Config[:knife][:kerberos_keytab_file] = keytab }
|
74
|
+
|
75
|
+
option :kerberos_realm,
|
76
|
+
:short => "-R KERBEROS_REALM",
|
77
|
+
:long => "--kerberos-realm KERBEROS_REALM",
|
78
|
+
:description => "The Kerberos realm used for authentication",
|
79
|
+
:proc => Proc.new { |realm| Chef::Config[:knife][:kerberos_realm] = realm }
|
80
|
+
|
81
|
+
option :kerberos_service,
|
82
|
+
:short => "-S KERBEROS_SERVICE",
|
83
|
+
:long => "--kerberos-service KERBEROS_SERVICE",
|
84
|
+
:description => "The Kerberos service used for authentication",
|
85
|
+
:proc => Proc.new { |service| Chef::Config[:knife][:kerberos_service] = service }
|
86
|
+
|
87
|
+
option :ca_trust_file,
|
88
|
+
:short => "-f CA_TRUST_FILE",
|
89
|
+
:long => "--ca-trust-file CA_TRUST_FILE",
|
90
|
+
:description => "The Certificate Authority (CA) trust file used for SSL transport",
|
91
|
+
:proc => Proc.new { |trust| Chef::Config[:knife][:ca_trust_file] = trust }
|
92
|
+
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: knife-windows
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.5.
|
5
|
+
version: 0.5.4
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Seth Chisamore
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-
|
13
|
+
date: 2011-08-12 00:00:00 -04:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -21,7 +21,7 @@ dependencies:
|
|
21
21
|
requirements:
|
22
22
|
- - "="
|
23
23
|
- !ruby/object:Gem::Version
|
24
|
-
version: 0.
|
24
|
+
version: 0.5.2
|
25
25
|
type: :runtime
|
26
26
|
version_requirements: *id001
|
27
27
|
description: Plugin that adds functionality to Chef's Knife CLI for configuring/interacting with nodes running Microsoft Windows
|
@@ -36,17 +36,19 @@ extra_rdoc_files:
|
|
36
36
|
- LICENSE
|
37
37
|
files:
|
38
38
|
- .gitignore
|
39
|
+
- CHANGELOG
|
39
40
|
- Gemfile
|
40
41
|
- LICENSE
|
41
42
|
- README.rdoc
|
42
43
|
- Rakefile
|
43
44
|
- knife-windows.gemspec
|
44
45
|
- lib/chef/knife/bootstrap/windows-shell.erb
|
46
|
+
- lib/chef/knife/bootstrap_windows_base.rb
|
45
47
|
- lib/chef/knife/bootstrap_windows_ssh.rb
|
46
48
|
- lib/chef/knife/bootstrap_windows_winrm.rb
|
47
49
|
- lib/chef/knife/core/windows_bootstrap_context.rb
|
48
|
-
- lib/chef/knife/mixin/windows/bootstrap.rb
|
49
50
|
- lib/chef/knife/winrm.rb
|
51
|
+
- lib/chef/knife/winrm_base.rb
|
50
52
|
- lib/knife-windows/version.rb
|
51
53
|
has_rdoc: true
|
52
54
|
homepage: https://github.com/opscode/knife-windows
|
@@ -1,94 +0,0 @@
|
|
1
|
-
require 'chef/knife'
|
2
|
-
require 'erubis'
|
3
|
-
|
4
|
-
class Chef
|
5
|
-
module Mixin
|
6
|
-
module Bootstrap
|
7
|
-
|
8
|
-
# TODO: This should go away when CHEF-2193 is fixed
|
9
|
-
def load_template(template=nil)
|
10
|
-
# Are we bootstrapping using an already shipped template?
|
11
|
-
if config[:template_file]
|
12
|
-
bootstrap_files = config[:template_file]
|
13
|
-
else
|
14
|
-
bootstrap_files = []
|
15
|
-
bootstrap_files << File.join(File.dirname(__FILE__), 'bootstrap', "#{config[:distro]}.erb")
|
16
|
-
bootstrap_files << File.join(Dir.pwd, ".chef", "bootstrap", "#{config[:distro]}.erb")
|
17
|
-
bootstrap_files << File.join(ENV['HOME'], '.chef', 'bootstrap', "#{config[:distro]}.erb")
|
18
|
-
bootstrap_files << Gem.find_files(File.join("chef","knife","bootstrap","#{config[:distro]}.erb"))
|
19
|
-
bootstrap_files.flatten!
|
20
|
-
end
|
21
|
-
|
22
|
-
template = Array(bootstrap_files).find do |bootstrap_template|
|
23
|
-
Chef::Log.debug("Looking for bootstrap template in #{File.dirname(bootstrap_template)}")
|
24
|
-
::File.exists?(bootstrap_template)
|
25
|
-
end
|
26
|
-
|
27
|
-
unless template
|
28
|
-
ui.info("Can not find bootstrap definition for #{config[:distro]}")
|
29
|
-
raise Errno::ENOENT
|
30
|
-
end
|
31
|
-
|
32
|
-
Chef::Log.debug("Found bootstrap template in #{File.dirname(template)}")
|
33
|
-
|
34
|
-
IO.read(template).chomp
|
35
|
-
end
|
36
|
-
|
37
|
-
def render_template(template=nil)
|
38
|
-
context = Knife::Core::WindowsBootstrapContext.new(config, config[:run_list], Chef::Config)
|
39
|
-
Erubis::Eruby.new(template).evaluate(context)
|
40
|
-
end
|
41
|
-
|
42
|
-
def bootstrap(proto=nil)
|
43
|
-
|
44
|
-
validate_name_args!
|
45
|
-
|
46
|
-
@node_name = Array(@name_args).first
|
47
|
-
# back compat--templates may use this setting:
|
48
|
-
config[:server_name] = @node_name
|
49
|
-
|
50
|
-
$stdout.sync = true
|
51
|
-
|
52
|
-
ui.info("Bootstrapping Chef on #{ui.color(@node_name, :bold)}")
|
53
|
-
# create a bootstrap.bat file on the node
|
54
|
-
# we have to run the remote commands in 2047 char chunks
|
55
|
-
create_bootstrap_bat_command do |command_chunk, chunk_num|
|
56
|
-
run_command("cmd.exe /C echo \"Rendering bootstrap.bat chunk #{chunk_num}\" && #{command_chunk}").run
|
57
|
-
end
|
58
|
-
|
59
|
-
# execute the bootstrap.bat file
|
60
|
-
run_command(bootstrap_command).run
|
61
|
-
end
|
62
|
-
|
63
|
-
def bootstrap_command
|
64
|
-
@bootstrap_command ||= "cmd.exe /C #{bootstrap_bat_file}"
|
65
|
-
end
|
66
|
-
|
67
|
-
def create_bootstrap_bat_command(&block)
|
68
|
-
bootstrap_bat = []
|
69
|
-
chunk_num = 0
|
70
|
-
render_template(load_template(config[:bootstrap_template])).each_line do |line|
|
71
|
-
# escape WIN BATCH special chars
|
72
|
-
line.gsub!(/[(<|>)^]/).each{|m| "^#{m}"}
|
73
|
-
# windows commands are limited to 2047 characters
|
74
|
-
if((bootstrap_bat + [line]).join(" && ").size > 2047 )
|
75
|
-
yield bootstrap_bat.join(" && "), chunk_num += 1
|
76
|
-
bootstrap_bat = []
|
77
|
-
end
|
78
|
-
bootstrap_bat << ">> #{bootstrap_bat_file} (echo.#{line.chomp.strip})"
|
79
|
-
end
|
80
|
-
yield bootstrap_bat.join(" && "), chunk_num += 1
|
81
|
-
end
|
82
|
-
|
83
|
-
def bootstrap_bat_file
|
84
|
-
"%TEMP%\\bootstrap.bat"
|
85
|
-
end
|
86
|
-
|
87
|
-
def locate_config_value(key)
|
88
|
-
key = key.to_sym
|
89
|
-
Chef::Config[:knife][key] || config[key]
|
90
|
-
end
|
91
|
-
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|