chef-provisioning 1.3.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -3,13 +3,14 @@ Chef Provisioning
3
3
  [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/chef/chef-provisioning?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
4
4
  [![Stories in Ready](https://badge.waffle.io/chef/chef-provisioning.png?label=ready&title=Ready)](https://waffle.io/chef/chef-provisioning)
5
5
  [![Status](https://travis-ci.org/chef/chef-provisioning.svg?branch=master)](https://travis-ci.org/chef/chef-provisioning)
6
+ [![Gem Version](https://badge.fury.io/rb/chef-provisioning.svg)](http://badge.fury.io/rb/chef-provisioning)
6
7
 
7
8
  Driver build status:
8
9
 
9
- AWS | Azure | Docker | Fog | Hanlon | LXC | ssh | Vagrant
10
- ---- | ---- | ---- | ---- | ---- | ---- | ---- | ----
11
- [![Status](https://travis-ci.org/chef/chef-provisioning-aws.svg?branch=master)](https://travis-ci.org/chef/chef-provisioning-aws)| [![Status](https://travis-ci.org/chef/chef-provisioning-azure.svg?branch=master)](https://travis-ci.org/chef/chef-provisioning-azure) | [![Status](https://travis-ci.org/chef/chef-provisioning-docker.svg?branch=master)](https://travis-ci.org/chef/chef-provisioning-docker) | [![Status](https://travis-ci.org/chef/chef-provisioning-fog.svg?branch=master)](https://travis-ci.org/chef/chef-provisioning-fog) | [![Status](https://travis-ci.org/chef/chef-provisioning-hanlon.svg?branch=master)](https://travis-ci.org/chef/chef-provisioning-hanlon) | [![Status](https://travis-ci.org/chef/chef-provisioning-lxc.svg?branch=master)](https://travis-ci.org/chef/chef-provisioning-lxc) | [![Status](https://travis-ci.org/chef/chef-provisioning-ssh.svg?branch=master)](https://travis-ci.org/chef/chef-provisioning-ssh) | [![Status](https://travis-ci.org/chef/chef-provisioning-vagrant.svg?branch=master)](https://travis-ci.org/chef/chef-provisioning-vagrant)
12
-
10
+ AWS | Azure | Docker | Fog | ssh | Vagrant
11
+ ---- | ---- | ---- | ---- | ---- | ----
12
+ [![Status](https://travis-ci.org/chef/chef-provisioning-aws.svg?branch=master)](https://travis-ci.org/chef/chef-provisioning-aws)| [![Status](https://travis-ci.org/chef/chef-provisioning-azure.svg?branch=master)](https://travis-ci.org/chef/chef-provisioning-azure) | [![Status](https://travis-ci.org/chef/chef-provisioning-docker.svg?branch=master)](https://travis-ci.org/chef/chef-provisioning-docker) | [![Status](https://travis-ci.org/chef/chef-provisioning-fog.svg?branch=master)](https://travis-ci.org/chef/chef-provisioning-fog) | [![Status](https://travis-ci.org/chef/chef-provisioning-ssh.svg?branch=master)](https://travis-ci.org/chef/chef-provisioning-ssh) | [![Status](https://travis-ci.org/chef/chef-provisioning-vagrant.svg?branch=master)](https://travis-ci.org/chef/chef-provisioning-vagrant)
13
+ [![Gem Version](https://badge.fury.io/rb/chef-provisioning-aws.svg)](http://badge.fury.io/rb/chef-provisioning-aws) | [![Gem Version](https://badge.fury.io/rb/chef-provisioning-azure.svg)](http://badge.fury.io/rb/chef-provisioning-azure) | [![Gem Version](https://badge.fury.io/rb/chef-provisioning-docker.svg)](http://badge.fury.io/rb/chef-provisioning-docker) | [![Gem Version](https://badge.fury.io/rb/chef-provisioning-fog.svg)](http://badge.fury.io/rb/chef-provisioning-fog) | [![Gem Version](https://badge.fury.io/rb/chef-provisioning-ssh.svg)](http://badge.fury.io/rb/chef-provisioning-ssh) | [![Gem Version](https://badge.fury.io/rb/chef-provisioning-vagrant.svg)](http://badge.fury.io/rb/chef-provisioning-vagrant)
13
14
  This library solves the problem of repeatably creating machines and infrastructures in Chef. It has a plugin model that lets you write bootstrappers for your favorite infrastructures, including VirtualBox, EC2, LXC, bare metal, and many more!
14
15
 
15
16
  Documentation
@@ -147,13 +148,65 @@ Drivers each have their own repository. Current drivers:
147
148
 
148
149
  **Containers:**
149
150
  - [Docker](https://github.com/chef/chef-provisioning-docker)
150
- - [LXC](https://github.com/chef/chef-provisioning-lxc)
151
151
 
152
152
  **Bare Metal:**
153
- - [Hanlon](https://github.com/chef/chef-provisioning-hanlon)
154
153
  - [OpenCrowbar](https://github.com/newgoliath/chef-provisioning-crowbar) OpenCrowbar controls your real metal. It discovers, inventories, configs RAID & BIOS and networks, and installs your OS. [OpenCrowbar website](http://www.opencrowbar.org) [OpenCrowbar github](https://github.com/opencrowbar/core)
155
154
  - [SSH (no PXE)](https://github.com/double-z/chef-metal-ssh) (not yet up to date with 0.11)
156
155
 
156
+ **Seeking Maintainers:**
157
+ These repositories are not actively maintained and are seeking maintainers.
158
+ - [LXC](https://github.com/chef/chef-provisioning-lxc)
159
+ - [Hanlon](https://github.com/chef/chef-provisioning-hanlon)
160
+
161
+ ### Machine options
162
+
163
+ You can pass machine options that will be used by `machine`, `machine_batch` and `machine_image` to
164
+ configure the machine:
165
+
166
+ ```ruby
167
+ with_machine_options({
168
+ convergence_options: {
169
+ chef_version: "12.4.1",
170
+ prerelease: "false",
171
+ chef_client_timeout: 120*60, # Default: 2 hours
172
+ chef_config: "log_level :debug\\n", # String containing additional text to inject into client.rb
173
+ chef_server: "http://my.chef.server/", # TODO could conflict with https://github.com/chef/chef-provisioning#pointing-boxes-at-chef-servers
174
+ bootstrap_proxy: "http://localhost:1234",
175
+ ssl_verify_mode: :verify_peer,
176
+ client_rb_path: "/etc/chef/client.rb", # <- DEFAULT, overwrite if necessary
177
+ client_pem_path: "/etc/chef/client.pem", # <- DEFAULT, overwrite if necessary
178
+ allow_overwrite_keys: false, # If there is an existing client.pem this needs to be true to overwrite it
179
+ private_key_options: {}, # TODO ????? Something to do with creating node object
180
+ source_key: "", # ?????
181
+ source_key_pass_phrase: "", # ?????
182
+ source_key_path: "", # ?????
183
+ public_key_path: "", # ?????
184
+ public_key_format: "", # ?????
185
+ admin: "", # ?????
186
+ validator: "", # ?????
187
+ ohai_hints: { :ec2 => { :key => :value } }, # Map from hint file name to file contents, this would create /etc/chef/ohai/hints/ec2.json,
188
+ ignore_failure: [1, 5..10, SomeSpecificError], # If true don't let a convergence failure on provisioned machine stop the provisioning workstation converge. Can also provide a single exit code to ignore (no array) or `true` to ignore all RuntimeErrors
189
+ # The following are only available for Linux machines
190
+ install_sh_url: "https://www.chef.io/chef/install.sh", # <- DEFAULT, overwrite if necessary
191
+ install_sh_path: "/tmp/chef-install.sh", # <- DEFAULT, overwrite if necessary
192
+ install_sh_arguments: "-P chef-dk", # Additional commands to pass to install.sh
193
+ # The following are only available for Windows machines
194
+ install_msi_url: "foo://bar.com"
195
+ },
196
+ ssh_username: "ubuntu", # Username to use for ssh and WinRM
197
+ ssh_options: { # a list of options to Net::SSH.start
198
+ :auth_methods => [ 'publickey' ], # DEFAULT
199
+ :keys_only => true, # DEFAULT
200
+ :host_key_alias => "#{instance.id}.AWS" # DEFAULT
201
+ }
202
+ })
203
+ ```
204
+
205
+ This options hash can be supplied to either `with_machine_options` or directly into the `machine_options`
206
+ attribute.
207
+
208
+ Individual drivers will often add their own driver specific config. For example, AWS expects a `:bootstrap_options` hash at the same level as `:convergence_options`.
209
+
157
210
  ### Anatomy of a Recipe
158
211
 
159
212
  chef-zero comes with a provisioner for Vagrant, an abstraction that covers VirtualBox, VMWare and other Virtual Machine drivers. In docs/examples, you can run this to try it:
@@ -198,41 +251,6 @@ end
198
251
 
199
252
  Other directives, like `recipe 'apache'`, help you set run lists and other information about the machine.
200
253
 
201
- ### Fog (EC2, Openstack and friends)
202
-
203
- chef-provisioning also comes with a [Fog](http://fog.io/) provisioner that handles provisioning to Openstack, Rackspace, Amazon's EC2 and other cloud drivers. Before you begin, you will need to put your AWS credentials in ~/.aws/config in the format [mentioned in Option 1 here](http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html#d0e726). There are other ways to specify your credentials, but this is the standard one for the Amazon CLI.
204
-
205
- Once your credentials are in, basic usage looks like this:
206
-
207
- ```
208
- export CHEF_DRIVER=fog:AWS
209
- chef-client -z simple.rb
210
- ```
211
-
212
- Other valid URLs include `fog:AWS:myprofilename` and `fog:AWS:profilename:us-west-2`.
213
-
214
- Most Chef Provisioning drivers try hard to provide reasonable defaults so you can get started easily. Once you have specified your credentials, AMIs and other things are chosen for you.
215
-
216
- You will usually want to create or input a custom key pair for bootstrap. To customize, specify keys and AMI and other options, you can make recipes like this:
217
-
218
- ```ruby
219
- require 'chef/provisioning/fog_driver'
220
-
221
- fog_key_pair 'my_bootstrap_key'
222
-
223
- with_machine_options :bootstrap_options => {
224
- :key_name => 'my_bootstrap_key',
225
- :image_id => 'ami-59a4a230',
226
- :flavor_id => 't1.micro'
227
- }
228
- ```
229
-
230
- `fog_key_pair` creates a new key pair (if the files do not already exist) and uploads it to AWS (it will toss an error if the key pair already exists and does not match). By default, `fog_key_pair` will look for matching key files in .chef/keys, ~/.chef/keys and ~/.ssh. If it does not find one, it will place the key in `.chef/keys`. You can override this path in fog_key_pair, but if you do, you will want to modify `private_key_paths` in your configuration to match.
231
-
232
- `with_machine_options` specifies machine_options that will be applied to any `machine` resources chef-client encounters.
233
-
234
- You will notice that we are still using `simple.rb` here. Machine definitions are generally driver-independent. This is an important feature that allows you to spin up your clusters in different places to create staging, test or miniature dev environments.
235
-
236
254
  ### Pointing Boxes at Chef Servers
237
255
 
238
256
  By default, Chef Provisioning will put your boxes on the same Chef server you started chef-client with (in the case of -z, that's a local chef-zero server). Sometimes you want to put your boxes on different servers. There are a couple of ways to do that:
data/Rakefile CHANGED
@@ -1,6 +1,40 @@
1
1
  require 'bundler'
2
2
  require 'bundler/gem_tasks'
3
+ require 'rspec/core/rake_task'
3
4
 
4
- task :spec do
5
- require File.expand_path('spec/run')
5
+ desc "run specs"
6
+ RSpec::Core::RakeTask.new(:spec) do |task|
7
+ task.pattern = 'spec/**/*_spec.rb'
6
8
  end
9
+
10
+ desc "run core gem specs and generated driver specs"
11
+ task :all => ["driver:spec", :spec]
12
+
13
+ FAKE_DIR = "chef-provisioning-fake"
14
+
15
+ namespace :driver do
16
+ desc "generate a '#{FAKE_DIR}' driver"
17
+ task :generate do
18
+ sh "./bin/generate_driver fake"
19
+ end
20
+
21
+ desc "run specs for #{FAKE_DIR}"
22
+ task :spec do
23
+ sh "cd #{FAKE_DIR} && bundle exec rspec"
24
+ end
25
+
26
+ desc "generate a #{FAKE_DIR} driver and run its specs"
27
+ task :verify => [:generate, :spec]
28
+
29
+ task :clean do
30
+ sh "rm -rf #{FAKE_DIR}"
31
+ end
32
+
33
+ desc "generate a fresh #{FAKE_DIR} driver, run its specs, and delete it"
34
+ task :cycle do
35
+ Rake::Task['driver:clean'].invoke
36
+ Rake::Task['driver:clean'].reenable
37
+ Rake::Task['driver:verify'].invoke
38
+ Rake::Task['driver:clean'].invoke
39
+ end
40
+ end
@@ -6,6 +6,7 @@ require 'chef/provisioning/chef_provider_action_handler'
6
6
  class Chef
7
7
  class Provider
8
8
  class LoadBalancer < Chef::Provider::LWRPBase
9
+ provides :load_balancer
9
10
 
10
11
  def action_handler
11
12
  @action_handler ||= Chef::Provisioning::ChefProviderActionHandler.new(self)
@@ -16,7 +17,7 @@ class Chef
16
17
  end
17
18
 
18
19
  def new_driver
19
- @new_driver ||= run_context.chef_metal.driver_for(new_resource.driver)
20
+ @new_driver ||= run_context.chef_provisioning.driver_for(new_resource.driver)
20
21
  end
21
22
 
22
23
  def chef_managed_entry_store
@@ -51,7 +52,20 @@ class Chef
51
52
  end
52
53
 
53
54
  def lb_options
54
- new_resource.load_balancer_options
55
+ @lb_options ||= begin
56
+ configs = []
57
+ configs << new_resource.load_balancer_options if new_resource.load_balancer_options
58
+
59
+ # See documentation in machine.rb provider
60
+ (self.class.additional_lb_option_keys || []).each do |k|
61
+ configs << { k => new_resource.public_send(k)} if new_resource.public_send(k)
62
+ end
63
+ Cheffish::MergedConfig.new(*configs)
64
+ end
65
+ end
66
+
67
+ def self.additional_lb_option_keys
68
+ @@additional_lb_option_keys ||= []
55
69
  end
56
70
 
57
71
  end
@@ -6,6 +6,7 @@ require 'chef/provisioning/chef_provider_action_handler'
6
6
  class Chef
7
7
  class Provider
8
8
  class Machine < Chef::Provider::LWRPBase
9
+ provides :machine
9
10
 
10
11
  def action_handler
11
12
  @action_handler ||= Chef::Provisioning::ChefProviderActionHandler.new(self)
@@ -146,12 +147,29 @@ class Machine < Chef::Provider::LWRPBase
146
147
  end
147
148
  }
148
149
 
150
+ # The current use case for this is adding a new attribute `aws_tags` to
151
+ # the machine resource from the chef-provisioning-aws driver. Because we
152
+ # want that attribute to work for the recipe DSL, it needs to be added at the
153
+ # Chef::Resource::Machine class level and not at an instance level. Thus we
154
+ # also need to pull the additional_machine_option_keys (:aws_tags) from the
155
+ # Chef::Resource::Machine class level. If you use two drivers (like AWS and
156
+ # Azure) then all machine instances will still have the `aws_tags` attribute
157
+ # DSL and will pass `:aws_tags` in on the machine_options. They can simply
158
+ # be ignored by the Azure driver.
159
+ (self.class.additional_machine_option_keys || []).each do |k|
160
+ configs << { k => new_resource.send(k)} if new_resource.send(k)
161
+ end
162
+
149
163
  configs << { from_image: new_resource.from_image } if new_resource.from_image
150
164
  configs << new_resource.machine_options if new_resource.machine_options
151
165
  configs << driver.config[:machine_options] if driver.config[:machine_options]
152
166
  Cheffish::MergedConfig.new(*configs)
153
167
  end
154
168
 
169
+ def self.additional_machine_option_keys
170
+ @@additional_machine_option_keys ||= []
171
+ end
172
+
155
173
  def load_current_resource
156
174
  node_driver = Chef::Provider::ChefNode.new(new_resource, run_context)
157
175
  node_driver.load_current_resource
@@ -8,6 +8,7 @@ require 'chef/provisioning/machine_spec'
8
8
  class Chef
9
9
  class Provider
10
10
  class MachineBatch < Chef::Provider::LWRPBase
11
+ provides :machine_batch
11
12
 
12
13
  def action_handler
13
14
  @action_handler ||= Provisioning::ChefProviderActionHandler.new(self)
@@ -5,6 +5,7 @@ require 'chef/provisioning/machine'
5
5
  class Chef
6
6
  class Provider
7
7
  class MachineFile < Chef::Provider::LWRPBase
8
+ provides :machine_file
8
9
 
9
10
  def action_handler
10
11
  @action_handler ||= Chef::Provisioning::ChefProviderActionHandler.new(self)
@@ -6,6 +6,7 @@ require 'chef/provisioning/chef_provider_action_handler'
6
6
  class Chef
7
7
  class Provider
8
8
  class MachineImage < Chef::Provider::LWRPBase
9
+ provides :machine_image
9
10
 
10
11
  def action_handler
11
12
  @action_handler ||= Chef::Provisioning::ChefProviderActionHandler.new(self)
@@ -28,6 +29,7 @@ class MachineImage < Chef::Provider::LWRPBase
28
29
  image_spec = chef_managed_entry_store.get_or_new(:machine_image, new_resource.name)
29
30
  if image_spec.reference
30
31
  # TODO check for real existence and maybe update
32
+ new_driver.ready_image(action_handler, image_spec, new_image_options)
31
33
  else
32
34
  #
33
35
  # Create a new image
@@ -77,11 +79,23 @@ class MachineImage < Chef::Provider::LWRPBase
77
79
  end
78
80
 
79
81
  def new_image_options
80
- @new_image_options ||= (new_resource.image_options || {}).to_hash.dup
82
+ @new_image_options ||= begin
83
+ configs = []
84
+ configs << new_resource.image_options if new_resource.image_options
85
+ # See documentation in machine.rb provider
86
+ (self.class.additional_image_option_keys || []).each do |k|
87
+ configs << { k => new_resource.send(k)} if new_resource.send(k)
88
+ end
89
+ Cheffish::MergedConfig.new(*configs)
90
+ end
81
91
  end
82
92
 
83
93
  def new_machine_options
84
- @new_machine_options ||= (new_resource.machine_options || {}).to_hash.dup
94
+ @new_machine_options ||= new_resource.machine_options
95
+ end
96
+
97
+ def self.additional_image_option_keys
98
+ @@additional_image_option_keys ||= []
85
99
  end
86
100
 
87
101
  end
@@ -0,0 +1,54 @@
1
+ class Chef
2
+ module Provisioning
3
+ class ConvergenceStrategy
4
+
5
+ # The purpose of this class is to decore the `converge` method with logic to catch any
6
+ # convergence failure exceptions, log them and then squelch them. The reason we
7
+ # need this is to prevent 1 provisioned node's converge failing an entire provisioning
8
+ # recipe.
9
+ module IgnoreConvergenceFailure
10
+
11
+ attr_accessor :ignore_failures_array, :ignore_exit_values
12
+
13
+ # This module is only meant to be extended into instances, not classes or modules.
14
+ # Different machines may have different settings so we don't want to extend
15
+ # every `install_sh` strategy with this logic.
16
+ def self.extended(instance)
17
+ opts = instance.convergence_options[:ignore_failure]
18
+ instance.ignore_failures_array = []
19
+ instance.ignore_exit_values = []
20
+ if opts == true
21
+ instance.ignore_failures_array << RuntimeError
22
+ else
23
+ # We assume it is integers or errors
24
+ opts = [opts].flatten
25
+ opts.each do |o|
26
+ case
27
+ when o.is_a?(Fixnum)
28
+ instance.ignore_exit_values << o
29
+ when o.is_a?(Range)
30
+ instance.ignore_exit_values += o.to_a
31
+ when o <= Exception
32
+ instance.ignore_failures_array << o
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ def converge(action_handler, machine)
39
+ super
40
+ rescue SystemExit => e
41
+ if ignore_exit_values.include? e.status
42
+ action_handler.performed_action("Caught SystemExit error #{e.status} from converging node but ignoring it")
43
+ else
44
+ raise
45
+ end
46
+ rescue *ignore_failures_array
47
+ action_handler.performed_action("Caught error '#{$!.inspect.gsub(/\n/,'\\n')}' from converging node but ignoring it")
48
+ end
49
+
50
+ end
51
+
52
+ end
53
+ end
54
+ end
@@ -20,6 +20,7 @@ module Provisioning
20
20
  # - :chef_client_timeout
21
21
  # - :client_rb_path, :client_pem_path
22
22
  # - :chef_version, :prerelease, :package_cache_path
23
+ # - :package_metadata
23
24
  def initialize(convergence_options, config)
24
25
  convergence_options = Cheffish::MergedConfig.new(convergence_options, {
25
26
  :client_rb_path => '/etc/chef/client.rb',
@@ -34,6 +35,7 @@ module Provisioning
34
35
  @chef_client_timeout = convergence_options.has_key?(:chef_client_timeout) ? convergence_options[:chef_client_timeout] : 120*60 # Default: 2 hours
35
36
  FileUtils.mkdir_p(@package_cache_path)
36
37
  @package_cache_lock = Mutex.new
38
+ @package_metadata ||= convergence_options[:package_metadata]
37
39
  end
38
40
 
39
41
  attr_reader :client_rb_path
@@ -69,7 +71,7 @@ module Provisioning
69
71
  package_file = download_package_for_platform(action_handler, machine, platform, platform_version, machine_architecture)
70
72
  remote_package_file = "#{@tmp_dir}/#{File.basename(package_file)}"
71
73
  machine.upload_file(action_handler, package_file, remote_package_file)
72
- install_package(action_handler, machine, remote_package_file)
74
+ install_package(action_handler, machine, platform, remote_package_file)
73
75
  end
74
76
 
75
77
  def converge(action_handler, machine)
@@ -101,15 +103,20 @@ module Provisioning
101
103
  #
102
104
  # Grab metadata
103
105
  #
104
- metadata = download_metadata_for_platform(machine, platform, platform_version, machine_architecture)
106
+ metadata = @package_metadata
107
+ if !metadata
108
+ Chef::Log.info("No metadata supplied, downloading it...")
109
+ metadata = download_metadata_for_platform(machine, platform, platform_version, machine_architecture)
110
+ end
105
111
 
106
112
  # Download actual package desired by metadata
107
- package_file = "#{@package_cache_path}/#{URI(metadata['url']).path.split('/')[-1]}"
113
+ package_file = "#{@package_cache_path}/#{URI(metadata[:url]).path.split('/')[-1]}"
108
114
 
115
+ Chef::Log.debug("Package metadata: #{metadata}")
109
116
  Chef::Provisioning.inline_resource(action_handler) do
110
117
  remote_file package_file do
111
- source metadata['url']
112
- checksum metadata['sha256']
118
+ source metadata[:url]
119
+ checksum metadata[:sha256]
113
120
  end
114
121
  end
115
122
 
@@ -144,16 +151,20 @@ module Provisioning
144
151
  metadata = {}
145
152
  metadata_str.each_line do |line|
146
153
  key, value = line.split("\t", 2)
147
- metadata[key] = value.chomp
154
+ metadata[key.to_sym] = value.chomp
148
155
  end
149
156
  metadata
150
157
  end
151
158
 
152
- def install_package(action_handler, machine, remote_package_file)
159
+ def install_package(action_handler, machine, platform, remote_package_file)
153
160
  extension = File.extname(remote_package_file)
154
161
  result = case extension
155
162
  when '.rpm'
156
- machine.execute(action_handler, "rpm -Uvh --oldpackage --replacepkgs \"#{remote_package_file}\"")
163
+ if platform == "wrlinux"
164
+ machine.execute(action_handler, "yum install -yv \"#{remote_package_file}\"")
165
+ else
166
+ machine.execute(action_handler, "rpm -Uvh --oldpackage --replacepkgs \"#{remote_package_file}\"")
167
+ end
157
168
  when '.deb'
158
169
  machine.execute(action_handler, "dpkg -i \"#{remote_package_file}\"")
159
170
  when '.solaris'
@@ -20,10 +20,11 @@ module Provisioning
20
20
 
21
21
  def setup_convergence(action_handler, machine)
22
22
  if !convergence_options.has_key?(:client_rb_path) || !convergence_options.has_key?(:client_pem_path)
23
- system_drive = machine.execute_always('$env:SystemDrive').stdout.strip
23
+ system_drive = machine.system_drive
24
24
  @convergence_options = Cheffish::MergedConfig.new(convergence_options, {
25
25
  :client_rb_path => "#{system_drive}\\chef\\client.rb",
26
- :client_pem_path => "#{system_drive}\\chef\\client.pem"
26
+ :client_pem_path => "#{system_drive}\\chef\\client.pem",
27
+ :install_script_path => "#{system_drive}\\chef\\\install.ps1"
27
28
  })
28
29
  end
29
30
 
@@ -36,7 +37,16 @@ module Provisioning
36
37
  super
37
38
 
38
39
  install_command = Mixlib::Install.new(chef_version, true, opts).install_command
39
- machine.execute(action_handler, install_command)
40
+ machine.write_file(action_handler, convergence_options[:install_script_path], install_command)
41
+
42
+ action_handler.open_stream(machine.node['name']) do |stdout|
43
+ action_handler.open_stream(machine.node['name']) do |stderr|
44
+ machine.execute(action_handler, "powershell.exe -ExecutionPolicy Unrestricted -NoProfile \"& \"\"#{convergence_options[:install_script_path]}\"\"\"",
45
+ :raw => true,
46
+ :stream_stdout => stdout,
47
+ :stream_stderr => stderr)
48
+ end
49
+ end
40
50
  end
41
51
 
42
52
  def converge(action_handler, machine)
@@ -47,6 +57,7 @@ module Provisioning
47
57
  command_line = "chef-client"
48
58
  command_line << " -l #{config[:log_level].to_s}" if config[:log_level]
49
59
  machine.execute(action_handler, command_line,
60
+ :raw => true,
50
61
  :stream_stdout => stdout,
51
62
  :stream_stderr => stderr,
52
63
  :timeout => @chef_client_timeout)