knife-windows 0.5.3 → 0.5.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|