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 :(



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
86
87
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
115
116
117
118
# File 'lib/chef/knife/bootstrap_windows_base.rb', line 31

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 :bootstrap_no_proxy,
      :long => "--bootstrap-no-proxy ",
      :description => "Avoid a proxy server for the given addresses",
      :proc => Proc.new { |np| Chef::Config[:knife][:bootstrap_no_proxy] = np }

    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 :first_boot_attributes,
      :short => "-j JSON_ATTRIBS",
      :long => "--json-attributes",
      :description => "A JSON string to be added to the first run of chef-client",
      :proc => lambda { |o| JSON.parse(o) },
      :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."

    option :auth_timeout,
      :long => "--auth-timeout MINUTES",
      :description => "The maximum time in minutes to wait to for authentication over the transport to the node to succeed. The default value is 2 minutes.",
      :default => 2

    option :node_ssl_verify_mode,
      :long        => "--node-ssl-verify-mode [peer|none]",
      :description => "Whether or not to verify the SSL cert for all HTTPS requests.",
      :proc        => Proc.new { |v|
        valid_values = ["none", "peer"]
        unless valid_values.include?(v)
          raise "Invalid value '#{v}' for --node-ssl-verify-mode. Valid values are: #{valid_values.join(", ")}"
        end
      }

    option :node_verify_api_cert,
      :long        => "--[no-]node-verify-api-cert",
      :description => "Verify the SSL cert for HTTPS requests to the Chef server API.",
      :boolean     => true
  end
end

Instance Method Details

#bootstrap(proto = nil) ⇒ Object



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/chef/knife/bootstrap_windows_base.rb', line 157

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

  wait_for_remote_response( config[:auth_timeout].to_i )
  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
      render_command_result = run_command(%Q!cmd.exe /C echo "Rendering #{bootstrap_bat_file} chunk #{chunk_num}" && #{command_chunk}!)
      ui.error("Batch render command returned #{render_command_result}") if render_command_result != 0
      render_command_result
    rescue SystemExit => e
      raise unless e.success?
    end
  end

  # execute the bootstrap.bat file
  bootstrap_command_result = run_command(bootstrap_command)
  ui.error("Bootstrap command returned #{bootstrap_command_result}") if bootstrap_command_result != 0
  bootstrap_command_result
end

#load_template(template = nil) ⇒ Object

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



121
122
123
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 121

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

#render_template(template = nil) ⇒ Object



149
150
151
152
153
154
155
# File 'lib/chef/knife/bootstrap_windows_base.rb', line 149

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