Module: Chef::Knife::BootstrapWindowsBase

Included in:
BootstrapWindowsSsh, BootstrapWindowsWinrm
Defined in:
lib/chef/knife/bootstrap_windows_base.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(includer) ⇒ Object

:nodoc: Would prefer to do this in a rational way, but can’t be done b/c of Mixlib::CLI’s design :(



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/chef/knife/bootstrap_windows_base.rb', line 29

def self.included(includer)
  includer.class_eval do

    deps do
      require 'readline'
      require 'chef/json_compat'
    end

    option :chef_node_name,
      :short => "-N NAME",
      :long => "--node-name NAME",
      :description => "The Chef node name for your new node"

    option :prerelease,
      :long => "--prerelease",
      :description => "Install the pre-release chef gems"

    option :bootstrap_version,
      :long => "--bootstrap-version VERSION",
      :description => "The version of Chef to install",
      :proc => Proc.new { |v| Chef::Config[:knife][:bootstrap_version] = v }

    option :bootstrap_proxy,
      :long => "--bootstrap-proxy PROXY_URL",
      :description => "The proxy server for the node being bootstrapped",
      :proc => Proc.new { |p| Chef::Config[:knife][:bootstrap_proxy] = p }

    option :distro,
      :short => "-d DISTRO",
      :long => "--distro DISTRO",
      :description => "Bootstrap a distro using a template",
      :default => "windows-chef-client-msi"

    option :template_file,
      :long => "--template-file TEMPLATE",
      :description => "Full path to location of template to use",
      :default => false

    option :run_list,
      :short => "-r RUN_LIST",
      :long => "--run-list RUN_LIST",
      :description => "Comma separated list of roles/recipes to apply",
      :proc => lambda { |o| o.split(",") },
      :default => []

    option :encrypted_data_bag_secret,
      :short => "-s SECRET",
      :long  => "--secret ",
      :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.",
      :default => false

    option :encrypted_data_bag_secret_file,
      :long => "--secret-file SECRET_FILE",
      :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."

  end
end

Instance Method Details

#bootstrap(proto = nil) ⇒ Object



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/chef/knife/bootstrap_windows_base.rb', line 124

def bootstrap(proto=nil)

  validate_name_args!

  @node_name = Array(@name_args).first
  # back compat--templates may use this setting:
  config[:server_name] = @node_name

  STDOUT.sync = STDERR.sync = true

  ui.info("Bootstrapping Chef on #{ui.color(@node_name, :bold)}")
  # create a bootstrap.bat file on the node
  # we have to run the remote commands in 2047 char chunks
  create_bootstrap_bat_command do |command_chunk, chunk_num|
    begin
      run_command("cmd.exe /C echo \"Rendering '#{bootstrap_bat_file}' chunk #{chunk_num}\" && #{command_chunk}")
    rescue SystemExit => e
      raise unless e.success?
    end
  end

  # execute the bootstrap.bat file
  run_command(bootstrap_command)
end

#bootstrap_bat_fileObject



169
170
171
# File 'lib/chef/knife/bootstrap_windows_base.rb', line 169

def bootstrap_bat_file
  @bootstrap_bat_file ||= "%TEMP%\\bootstrap-#{Process.pid}-#{Time.now.to_i}.bat"
end

#bootstrap_commandObject



149
150
151
# File 'lib/chef/knife/bootstrap_windows_base.rb', line 149

def bootstrap_command
  @bootstrap_command ||= "cmd.exe /C #{bootstrap_bat_file}"
end

#create_bootstrap_bat_command {|bootstrap_bat.join(" && "), chunk_num += 1| ... } ⇒ Object

Yields:

  • (bootstrap_bat.join(" && "), chunk_num += 1)


153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/chef/knife/bootstrap_windows_base.rb', line 153

def create_bootstrap_bat_command(&block)
  bootstrap_bat = []
  chunk_num = 0
  render_template(load_template(config[:bootstrap_template])).each_line do |line|
    # escape WIN BATCH special chars
    line.gsub!(/[(<|>)^]/).each{|m| "^#{m}"}
    # windows commands are limited to 2047 characters
    if((bootstrap_bat + [line]).join(" && ").size > 2047 )
      yield bootstrap_bat.join(" && "), chunk_num += 1
      bootstrap_bat = []
    end
    bootstrap_bat << ">> #{bootstrap_bat_file} (echo.#{line.chomp.strip})"
  end
  yield bootstrap_bat.join(" && "), chunk_num += 1
end

#load_template(template = nil) ⇒ Object

TODO: This should go away when CHEF-2193 is fixed



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/chef/knife/bootstrap_windows_base.rb', line 88

def load_template(template=nil)
  # Are we bootstrapping using an already shipped template?
  if config[:template_file]
    bootstrap_files = config[:template_file]
  else
    bootstrap_files = []
    bootstrap_files << File.join(File.dirname(__FILE__), 'bootstrap', "#{config[:distro]}.erb")
    bootstrap_files << File.join(Dir.pwd, ".chef", "bootstrap", "#{config[:distro]}.erb")
    bootstrap_files << File.join(ENV['HOME'], '.chef', 'bootstrap', "#{config[:distro]}.erb")
    bootstrap_files << Gem.find_files(File.join("chef","knife","bootstrap","#{config[:distro]}.erb"))
    bootstrap_files.flatten!
  end

  template = Array(bootstrap_files).find do |bootstrap_template|
    Chef::Log.debug("Looking for bootstrap template in #{File.dirname(bootstrap_template)}")
    ::File.exists?(bootstrap_template)
  end

  unless template
    ui.info("Can not find bootstrap definition for #{config[:distro]}")
    raise Errno::ENOENT
  end

  Chef::Log.debug("Found bootstrap template in #{File.dirname(template)}")

  IO.read(template).chomp
end

#locate_config_value(key) ⇒ Object



173
174
175
176
# File 'lib/chef/knife/bootstrap_windows_base.rb', line 173

def locate_config_value(key)
  key = key.to_sym
  Chef::Config[:knife][key] || config[key]
end

#render_template(template = nil) ⇒ Object



116
117
118
119
120
121
122
# File 'lib/chef/knife/bootstrap_windows_base.rb', line 116

def render_template(template=nil)
  if config[:encrypted_data_bag_secret_file]
    config[:encrypted_data_bag_secret] = Chef::EncryptedDataBagItem.load_secret(config[:encrypted_data_bag_secret_file])
  end
  context = Knife::Core::WindowsBootstrapContext.new(config, config[:run_list], Chef::Config)
  Erubis::Eruby.new(template).evaluate(context)
end