chef-provisioning 2.0.0 → 2.0.1

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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +899 -885
  3. data/Gemfile +17 -17
  4. data/LICENSE +201 -201
  5. data/README.md +312 -312
  6. data/Rakefile +55 -55
  7. data/chef-provisioning.gemspec +38 -38
  8. data/lib/chef/provider/load_balancer.rb +75 -75
  9. data/lib/chef/provider/machine.rb +219 -219
  10. data/lib/chef/provider/machine_batch.rb +224 -224
  11. data/lib/chef/provider/machine_execute.rb +36 -35
  12. data/lib/chef/provider/machine_file.rb +55 -55
  13. data/lib/chef/provider/machine_image.rb +105 -105
  14. data/lib/chef/provisioning.rb +110 -110
  15. data/lib/chef/provisioning/action_handler.rb +68 -68
  16. data/lib/chef/provisioning/add_prefix_action_handler.rb +35 -35
  17. data/lib/chef/provisioning/chef_managed_entry_store.rb +128 -128
  18. data/lib/chef/provisioning/chef_provider_action_handler.rb +74 -74
  19. data/lib/chef/provisioning/chef_run_data.rb +132 -132
  20. data/lib/chef/provisioning/convergence_strategy.rb +28 -28
  21. data/lib/chef/provisioning/convergence_strategy/ignore_convergence_failure.rb +54 -54
  22. data/lib/chef/provisioning/convergence_strategy/install_cached.rb +188 -188
  23. data/lib/chef/provisioning/convergence_strategy/install_msi.rb +71 -71
  24. data/lib/chef/provisioning/convergence_strategy/install_sh.rb +71 -71
  25. data/lib/chef/provisioning/convergence_strategy/no_converge.rb +35 -35
  26. data/lib/chef/provisioning/convergence_strategy/precreate_chef_objects.rb +255 -255
  27. data/lib/chef/provisioning/driver.rb +323 -323
  28. data/lib/chef/provisioning/load_balancer_spec.rb +14 -14
  29. data/lib/chef/provisioning/machine.rb +112 -112
  30. data/lib/chef/provisioning/machine/basic_machine.rb +84 -84
  31. data/lib/chef/provisioning/machine/unix_machine.rb +288 -288
  32. data/lib/chef/provisioning/machine/windows_machine.rb +108 -108
  33. data/lib/chef/provisioning/machine_image_spec.rb +34 -34
  34. data/lib/chef/provisioning/machine_spec.rb +58 -58
  35. data/lib/chef/provisioning/managed_entry.rb +121 -121
  36. data/lib/chef/provisioning/managed_entry_store.rb +136 -136
  37. data/lib/chef/provisioning/recipe_dsl.rb +99 -99
  38. data/lib/chef/provisioning/rspec.rb +27 -27
  39. data/lib/chef/provisioning/transport.rb +100 -100
  40. data/lib/chef/provisioning/transport/ssh.rb +403 -403
  41. data/lib/chef/provisioning/transport/winrm.rb +144 -156
  42. data/lib/chef/provisioning/version.rb +5 -5
  43. data/lib/chef/resource/chef_data_bag_resource.rb +146 -146
  44. data/lib/chef/resource/load_balancer.rb +57 -57
  45. data/lib/chef/resource/machine.rb +128 -128
  46. data/lib/chef/resource/machine_batch.rb +78 -78
  47. data/lib/chef/resource/machine_execute.rb +30 -29
  48. data/lib/chef/resource/machine_file.rb +34 -34
  49. data/lib/chef/resource/machine_image.rb +35 -35
  50. data/lib/chef_metal.rb +1 -1
  51. data/spec/chef/provisioning/convergence_strategy/ignore_convergence_failure_spec.rb +86 -86
  52. data/spec/spec_helper.rb +27 -27
  53. metadata +5 -5
data/Rakefile CHANGED
@@ -1,55 +1,55 @@
1
- require 'bundler'
2
- require 'bundler/gem_tasks'
3
- require 'rspec/core/rake_task'
4
-
5
- desc "run specs"
6
- RSpec::Core::RakeTask.new(:spec) do |task|
7
- task.pattern = 'spec/**/*_spec.rb'
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
41
-
42
- require "chef/provisioning/version"
43
-
44
- begin
45
- require 'github_changelog_generator/task'
46
-
47
- GitHubChangelogGenerator::RakeTask.new :changelog do |config|
48
- config.future_release = Chef::Provisioning::VERSION
49
- config.enhancement_labels = "enhancement,Enhancement,New Feature".split(',')
50
- config.bug_labels = "bug,Bug,Improvement,Upstream Bug".split(',')
51
- config.exclude_labels = "duplicate,question,invalid,wontfix,no_changelog,Exclude From Changelog".split(',')
52
- end
53
- rescue LoadError
54
- # It's OK if the github_changelog_generator isn't there, that happens when we're testing older chef versions
55
- end
1
+ require 'bundler'
2
+ require 'bundler/gem_tasks'
3
+ require 'rspec/core/rake_task'
4
+
5
+ desc "run specs"
6
+ RSpec::Core::RakeTask.new(:spec) do |task|
7
+ task.pattern = 'spec/**/*_spec.rb'
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
41
+
42
+ require "chef/provisioning/version"
43
+
44
+ begin
45
+ require 'github_changelog_generator/task'
46
+
47
+ GitHubChangelogGenerator::RakeTask.new :changelog do |config|
48
+ config.future_release = Chef::Provisioning::VERSION
49
+ config.enhancement_labels = "enhancement,Enhancement,New Feature".split(',')
50
+ config.bug_labels = "bug,Bug,Improvement,Upstream Bug".split(',')
51
+ config.exclude_labels = "duplicate,question,invalid,wontfix,no_changelog,Exclude From Changelog".split(',')
52
+ end
53
+ rescue LoadError
54
+ # It's OK if the github_changelog_generator isn't there, that happens when we're testing older chef versions
55
+ end
@@ -1,38 +1,38 @@
1
- $:.unshift(File.dirname(__FILE__) + '/lib')
2
- require 'chef/provisioning/version'
3
-
4
- Gem::Specification.new do |s|
5
- s.name = 'chef-provisioning'
6
- s.version = Chef::Provisioning::VERSION
7
- s.platform = Gem::Platform::RUBY
8
- s.extra_rdoc_files = ['README.md', 'CHANGELOG.md', 'LICENSE' ]
9
- s.summary = 'A library for creating machines and infrastructures idempotently in Chef.'
10
- s.description = s.summary
11
- s.author = 'John Keiser'
12
- s.email = 'jkeiser@chef.io'
13
- s.homepage = 'http://github.com/chef/chef-provisioning/README.md'
14
-
15
- s.required_ruby_version = ">= 2.2.2"
16
-
17
- s.add_dependency 'net-ssh', '>= 2.9', '< 4.0'
18
- s.add_dependency 'net-scp', '~> 1.0'
19
- s.add_dependency 'net-ssh-gateway', '~> 1.2.0'
20
- s.add_dependency 'inifile', '>= 2.0.2'
21
- s.add_dependency 'cheffish', '~> 4.0'
22
- s.add_dependency 'winrm', '~> 1.3'
23
- s.add_dependency "mixlib-install", "~> 1.0"
24
-
25
- s.add_development_dependency 'chef', '~> 12.1', "!= 12.4.0" # 12.4.0 is incompatible.
26
- s.add_development_dependency 'rspec'
27
- s.add_development_dependency 'rake'
28
- s.add_development_dependency 'pry'
29
- s.add_development_dependency 'simplecov'
30
- s.add_development_dependency 'github_changelog_generator'
31
-
32
- s.bindir = "bin"
33
- s.executables = %w( )
34
-
35
- s.require_path = 'lib'
36
- s.files = %w(Gemfile Rakefile LICENSE README.md CHANGELOG.md) + Dir.glob("*.gemspec") +
37
- Dir.glob("{distro,lib,tasks,spec}/**/*", File::FNM_DOTMATCH).reject {|f| File.directory?(f) }
38
- end
1
+ $:.unshift(File.dirname(__FILE__) + '/lib')
2
+ require 'chef/provisioning/version'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'chef-provisioning'
6
+ s.version = Chef::Provisioning::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.extra_rdoc_files = ['README.md', 'CHANGELOG.md', 'LICENSE' ]
9
+ s.summary = 'A library for creating machines and infrastructures idempotently in Chef.'
10
+ s.description = s.summary
11
+ s.author = 'John Keiser'
12
+ s.email = 'jkeiser@chef.io'
13
+ s.homepage = 'http://github.com/chef/chef-provisioning/README.md'
14
+
15
+ s.required_ruby_version = ">= 2.2.2"
16
+
17
+ s.add_dependency 'net-ssh', '>= 2.9', '< 4.0'
18
+ s.add_dependency 'net-scp', '~> 1.0'
19
+ s.add_dependency 'net-ssh-gateway', '~> 1.2.0'
20
+ s.add_dependency 'inifile', '>= 2.0.2'
21
+ s.add_dependency 'cheffish', '~> 4.0'
22
+ s.add_dependency 'winrm-fs', '~> 1.0'
23
+ s.add_dependency "mixlib-install", "~> 1.0"
24
+
25
+ s.add_development_dependency 'chef', '~> 12.1', "!= 12.4.0" # 12.4.0 is incompatible.
26
+ s.add_development_dependency 'rspec'
27
+ s.add_development_dependency 'rake'
28
+ s.add_development_dependency 'pry'
29
+ s.add_development_dependency 'simplecov'
30
+ s.add_development_dependency 'github_changelog_generator'
31
+
32
+ s.bindir = "bin"
33
+ s.executables = %w( )
34
+
35
+ s.require_path = 'lib'
36
+ s.files = %w(Gemfile Rakefile LICENSE README.md CHANGELOG.md) + Dir.glob("*.gemspec") +
37
+ Dir.glob("{distro,lib,tasks,spec}/**/*", File::FNM_DOTMATCH).reject {|f| File.directory?(f) }
38
+ end
@@ -1,75 +1,75 @@
1
- require 'chef/provider/lwrp_base'
2
- require 'openssl'
3
- require 'chef/provisioning/chef_provider_action_handler'
4
-
5
- class Chef
6
- class Provider
7
- class LoadBalancer < Chef::Provider::LWRPBase
8
- provides :load_balancer
9
-
10
- def action_handler
11
- @action_handler ||= Chef::Provisioning::ChefProviderActionHandler.new(self)
12
- end
13
-
14
- def whyrun_supported?
15
- true
16
- end
17
-
18
- def new_driver
19
- @new_driver ||= run_context.chef_provisioning.driver_for(new_resource.driver)
20
- end
21
-
22
- def chef_managed_entry_store
23
- @chef_managed_entry_store ||= Provisioning.chef_managed_entry_store(new_resource.chef_server)
24
- end
25
-
26
- action :create do
27
- lb_spec = chef_managed_entry_store.get_or_new(:load_balancer, new_resource.name)
28
-
29
- Chef::Log.debug "Creating load balancer: #{new_resource.name}; loaded #{lb_spec.inspect}"
30
- if new_resource.machines
31
- machine_specs = new_resource.machines.map { |machine| get_machine_spec!(machine) }
32
- end
33
-
34
- new_driver.allocate_load_balancer(action_handler, lb_spec, lb_options, machine_specs)
35
- lb_spec.save(action_handler)
36
- new_driver.ready_load_balancer(action_handler, lb_spec, lb_options, machine_specs)
37
- end
38
-
39
- action :destroy do
40
- lb_spec = chef_managed_entry_store.get(:load_balancer, new_resource.name)
41
- if lb_spec
42
- new_driver.destroy_load_balancer(action_handler, lb_spec, lb_options)
43
- end
44
- end
45
-
46
- private
47
-
48
- def get_machine_spec!(machine_name)
49
- Chef::Log.debug "Getting machine spec for #{machine_name}"
50
- Provisioning.chef_managed_entry_store(new_resource.chef_server).get!(:machine, machine_name)
51
- end
52
-
53
- def lb_options
54
- @lb_options ||= begin
55
- configs = []
56
- configs << new_resource.load_balancer_options if new_resource.load_balancer_options
57
-
58
- # See documentation in machine.rb provider
59
- (self.class.additional_lb_option_keys || []).each do |k|
60
- configs << { k => new_resource.public_send(k)} if new_resource.public_send(k)
61
- end
62
- Cheffish::MergedConfig.new(*configs)
63
- end
64
- end
65
-
66
- def self.additional_lb_option_keys
67
- @@additional_lb_option_keys ||= []
68
- end
69
-
70
- end
71
- end
72
- end
73
-
74
- require 'chef/provisioning/chef_managed_entry_store'
75
- Chef::Provisioning::ChefManagedEntryStore.type_names_for_backcompat[:load_balancer] = "loadbalancers"
1
+ require 'chef/provider/lwrp_base'
2
+ require 'openssl'
3
+ require 'chef/provisioning/chef_provider_action_handler'
4
+
5
+ class Chef
6
+ class Provider
7
+ class LoadBalancer < Chef::Provider::LWRPBase
8
+ provides :load_balancer
9
+
10
+ def action_handler
11
+ @action_handler ||= Chef::Provisioning::ChefProviderActionHandler.new(self)
12
+ end
13
+
14
+ def whyrun_supported?
15
+ true
16
+ end
17
+
18
+ def new_driver
19
+ @new_driver ||= run_context.chef_provisioning.driver_for(new_resource.driver)
20
+ end
21
+
22
+ def chef_managed_entry_store
23
+ @chef_managed_entry_store ||= Provisioning.chef_managed_entry_store(new_resource.chef_server)
24
+ end
25
+
26
+ action :create do
27
+ lb_spec = chef_managed_entry_store.get_or_new(:load_balancer, new_resource.name)
28
+
29
+ Chef::Log.debug "Creating load balancer: #{new_resource.name}; loaded #{lb_spec.inspect}"
30
+ if new_resource.machines
31
+ machine_specs = new_resource.machines.map { |machine| get_machine_spec!(machine) }
32
+ end
33
+
34
+ new_driver.allocate_load_balancer(action_handler, lb_spec, lb_options, machine_specs)
35
+ lb_spec.save(action_handler)
36
+ new_driver.ready_load_balancer(action_handler, lb_spec, lb_options, machine_specs)
37
+ end
38
+
39
+ action :destroy do
40
+ lb_spec = chef_managed_entry_store.get(:load_balancer, new_resource.name)
41
+ if lb_spec
42
+ new_driver.destroy_load_balancer(action_handler, lb_spec, lb_options)
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ def get_machine_spec!(machine_name)
49
+ Chef::Log.debug "Getting machine spec for #{machine_name}"
50
+ Provisioning.chef_managed_entry_store(new_resource.chef_server).get!(:machine, machine_name)
51
+ end
52
+
53
+ def lb_options
54
+ @lb_options ||= begin
55
+ configs = []
56
+ configs << new_resource.load_balancer_options if new_resource.load_balancer_options
57
+
58
+ # See documentation in machine.rb provider
59
+ (self.class.additional_lb_option_keys || []).each do |k|
60
+ configs << { k => new_resource.public_send(k)} if new_resource.public_send(k)
61
+ end
62
+ Cheffish::MergedConfig.new(*configs)
63
+ end
64
+ end
65
+
66
+ def self.additional_lb_option_keys
67
+ @@additional_lb_option_keys ||= []
68
+ end
69
+
70
+ end
71
+ end
72
+ end
73
+
74
+ require 'chef/provisioning/chef_managed_entry_store'
75
+ Chef::Provisioning::ChefManagedEntryStore.type_names_for_backcompat[:load_balancer] = "loadbalancers"
@@ -1,219 +1,219 @@
1
- require 'chef/provider/lwrp_base'
2
- require 'chef/resource/chef_node'
3
- require 'openssl'
4
- require 'chef/provisioning/chef_provider_action_handler'
5
-
6
- class Chef
7
- class Provider
8
- class Machine < Chef::Provider::LWRPBase
9
- provides :machine
10
-
11
- def action_handler
12
- @action_handler ||= Chef::Provisioning::ChefProviderActionHandler.new(self)
13
- end
14
- def action_handler=(value)
15
- @action_handler = value
16
- end
17
-
18
- use_inline_resources
19
-
20
- def whyrun_supported?
21
- true
22
- end
23
-
24
- action :allocate do
25
- if !new_driver
26
- raise "Driver not specified for machine #{machine_spec.name}"
27
- end
28
- if current_driver && current_driver.driver_url != new_driver.driver_url
29
- raise "Cannot move '#{machine_spec.name}' from #{current_driver.driver_url} to #{new_driver.driver_url}: machine moving is not supported. Destroy and recreate."
30
- end
31
- new_driver.allocate_machine(action_handler, machine_spec, new_machine_options)
32
- machine_spec.from_image ||= new_resource.from_image if new_resource.from_image
33
- machine_spec.driver_url ||= new_driver.driver_url
34
- machine_spec.save(action_handler)
35
- end
36
-
37
- action :ready do
38
- action_allocate
39
- machine = current_driver.ready_machine(action_handler, machine_spec, current_machine_options)
40
- machine_spec.save(action_handler)
41
- machine
42
- end
43
-
44
- action :setup do
45
- machine = action_ready
46
- begin
47
- machine.setup_convergence(action_handler)
48
- machine_spec.save(action_handler)
49
- upload_files(machine)
50
- ensure
51
- machine.disconnect
52
- end
53
- end
54
-
55
- action :converge do
56
- machine = action_ready
57
- begin
58
- machine.setup_convergence(action_handler)
59
- machine_spec.save(action_handler)
60
- upload_files(machine)
61
- # If we were asked to converge, or anything changed, or if a converge has never succeeded, converge.
62
- if new_resource.converge
63
- Chef::Log.info("Converging #{machine_spec.name} because 'converge true' is set ...")
64
- machine.converge(action_handler)
65
- elsif new_resource.converge.nil? && resource_updated?
66
- Chef::Log.info("Converging #{machine_spec.name} because the resource was updated ...")
67
- machine.converge(action_handler)
68
- elsif !machine_spec.node['automatic'] || machine_spec.node['automatic'].size == 0
69
- Chef::Log.info("Converging #{machine_spec.name} because it has never been converged (automatic attributes are empty) ...")
70
- machine.converge(action_handler)
71
- elsif new_resource.converge == false
72
- Chef::Log.debug("Not converging #{machine_spec.name} because 'converge false' is set.")
73
- end
74
- ensure
75
- machine.disconnect
76
- end
77
- end
78
-
79
- action :converge_only do
80
- if new_resource.converge == false
81
- Chef::Log.debug("Not converging #{machine_spec.name} because 'converge false' is set.")
82
- else
83
- machine = run_context.chef_provisioning.connect_to_machine(machine_spec, current_machine_options)
84
- begin
85
- machine.converge(action_handler)
86
- ensure
87
- machine.disconnect
88
- end
89
- end
90
- end
91
-
92
- action :stop do
93
- if current_driver
94
- current_driver.stop_machine(action_handler, machine_spec, current_machine_options)
95
- end
96
- end
97
-
98
- action :destroy do
99
- if current_driver
100
- current_driver.destroy_machine(action_handler, machine_spec, current_machine_options)
101
- end
102
- machine_spec.delete(action_handler)
103
- end
104
-
105
- attr_reader :machine_spec
106
-
107
- def new_driver
108
- run_context.chef_provisioning.driver_for(new_resource.driver)
109
- end
110
-
111
- def current_driver
112
- if machine_spec.driver_url
113
- run_context.chef_provisioning.driver_for(machine_spec.driver_url)
114
- end
115
- end
116
-
117
- def from_image_spec
118
- @from_image_spec ||= begin
119
- if new_resource.from_image
120
- chef_managed_entry_store.get!(:machine_image, new_resource.from_image)
121
- else
122
- nil
123
- end
124
- end
125
- end
126
-
127
- def new_machine_options
128
- machine_options(new_driver)
129
- end
130
-
131
- def current_machine_options
132
- machine_options(current_driver)
133
- end
134
-
135
- def machine_options(driver)
136
- configs = []
137
-
138
- configs << {
139
- :convergence_options =>
140
- [ :chef_server,
141
- :allow_overwrite_keys,
142
- :source_key, :source_key_path, :source_key_pass_phrase,
143
- :private_key_options,
144
- :ohai_hints,
145
- :public_key_path, :public_key_format,
146
- :admin, :validator,
147
- :chef_config
148
- ].inject({}) do |result, key|
149
- result[key] = new_resource.send(key)
150
- result
151
- end
152
- }
153
-
154
- # The current use case for this is adding a new attribute `aws_tags` to
155
- # the machine resource from the chef-provisioning-aws driver. Because we
156
- # want that attribute to work for the recipe DSL, it needs to be added at the
157
- # Chef::Resource::Machine class level and not at an instance level. Thus we
158
- # also need to pull the additional_machine_option_keys (:aws_tags) from the
159
- # Chef::Resource::Machine class level. If you use two drivers (like AWS and
160
- # Azure) then all machine instances will still have the `aws_tags` attribute
161
- # DSL and will pass `:aws_tags` in on the machine_options. They can simply
162
- # be ignored by the Azure driver.
163
- (self.class.additional_machine_option_keys || []).each do |k|
164
- configs << { k => new_resource.send(k)} if new_resource.send(k)
165
- end
166
-
167
- configs << { from_image: new_resource.from_image } if new_resource.from_image
168
- configs << new_resource.machine_options if new_resource.machine_options
169
- configs << driver.config[:machine_options] if driver.config[:machine_options]
170
- Cheffish::MergedConfig.new(*configs)
171
- end
172
-
173
- def self.additional_machine_option_keys
174
- @@additional_machine_option_keys ||= []
175
- end
176
-
177
- def load_current_resource
178
- if defined?(Chef::Provider::ChefNode)
179
- # Cheffish 1.x
180
- node_provider = Chef::Provider::ChefNode.new(new_resource, run_context)
181
- else
182
- # Cheffish 2.x
183
- node_provider = Chef::Resource::ChefNode.action_class.new(new_resource, run_context)
184
- end
185
- node_provider.load_current_resource
186
- json = node_provider.new_json
187
- json['normal']['chef_provisioning'] = node_provider.current_json['normal']['chef_provisioning']
188
- @machine_spec = chef_managed_entry_store.new_entry(:machine, new_resource.name, json)
189
- end
190
-
191
- def chef_managed_entry_store
192
- @chef_managed_entry_store ||= Provisioning.chef_managed_entry_store(new_resource.chef_server)
193
- end
194
-
195
- def self.upload_files(action_handler, machine, files)
196
- if files
197
- files.each_pair do |remote_file, local|
198
- if local.is_a?(Hash)
199
- if local[:local_path]
200
- machine.upload_file(action_handler, local[:local_path], remote_file)
201
- else
202
- machine.write_file(action_handler, remote_file, local[:content])
203
- end
204
- else
205
- machine.upload_file(action_handler, local, remote_file)
206
- end
207
- end
208
- end
209
- end
210
-
211
- private
212
-
213
- def upload_files(machine)
214
- Machine.upload_files(action_handler, machine, new_resource.files)
215
- end
216
-
217
- end
218
- end
219
- end
1
+ require 'chef/provider/lwrp_base'
2
+ require 'chef/resource/chef_node'
3
+ require 'openssl'
4
+ require 'chef/provisioning/chef_provider_action_handler'
5
+
6
+ class Chef
7
+ class Provider
8
+ class Machine < Chef::Provider::LWRPBase
9
+ provides :machine
10
+
11
+ def action_handler
12
+ @action_handler ||= Chef::Provisioning::ChefProviderActionHandler.new(self)
13
+ end
14
+ def action_handler=(value)
15
+ @action_handler = value
16
+ end
17
+
18
+ use_inline_resources
19
+
20
+ def whyrun_supported?
21
+ true
22
+ end
23
+
24
+ action :allocate do
25
+ if !new_driver
26
+ raise "Driver not specified for machine #{machine_spec.name}"
27
+ end
28
+ if current_driver && current_driver.driver_url != new_driver.driver_url
29
+ raise "Cannot move '#{machine_spec.name}' from #{current_driver.driver_url} to #{new_driver.driver_url}: machine moving is not supported. Destroy and recreate."
30
+ end
31
+ new_driver.allocate_machine(action_handler, machine_spec, new_machine_options)
32
+ machine_spec.from_image ||= new_resource.from_image if new_resource.from_image
33
+ machine_spec.driver_url ||= new_driver.driver_url
34
+ machine_spec.save(action_handler)
35
+ end
36
+
37
+ action :ready do
38
+ action_allocate
39
+ machine = current_driver.ready_machine(action_handler, machine_spec, current_machine_options)
40
+ machine_spec.save(action_handler)
41
+ machine
42
+ end
43
+
44
+ action :setup do
45
+ machine = action_ready
46
+ begin
47
+ machine.setup_convergence(action_handler)
48
+ machine_spec.save(action_handler)
49
+ upload_files(machine)
50
+ ensure
51
+ machine.disconnect
52
+ end
53
+ end
54
+
55
+ action :converge do
56
+ machine = action_ready
57
+ begin
58
+ machine.setup_convergence(action_handler)
59
+ machine_spec.save(action_handler)
60
+ upload_files(machine)
61
+ # If we were asked to converge, or anything changed, or if a converge has never succeeded, converge.
62
+ if new_resource.converge
63
+ Chef::Log.info("Converging #{machine_spec.name} because 'converge true' is set ...")
64
+ machine.converge(action_handler)
65
+ elsif new_resource.converge.nil? && resource_updated?
66
+ Chef::Log.info("Converging #{machine_spec.name} because the resource was updated ...")
67
+ machine.converge(action_handler)
68
+ elsif !machine_spec.node['automatic'] || machine_spec.node['automatic'].size == 0
69
+ Chef::Log.info("Converging #{machine_spec.name} because it has never been converged (automatic attributes are empty) ...")
70
+ machine.converge(action_handler)
71
+ elsif new_resource.converge == false
72
+ Chef::Log.debug("Not converging #{machine_spec.name} because 'converge false' is set.")
73
+ end
74
+ ensure
75
+ machine.disconnect
76
+ end
77
+ end
78
+
79
+ action :converge_only do
80
+ if new_resource.converge == false
81
+ Chef::Log.debug("Not converging #{machine_spec.name} because 'converge false' is set.")
82
+ else
83
+ machine = run_context.chef_provisioning.connect_to_machine(machine_spec, current_machine_options)
84
+ begin
85
+ machine.converge(action_handler)
86
+ ensure
87
+ machine.disconnect
88
+ end
89
+ end
90
+ end
91
+
92
+ action :stop do
93
+ if current_driver
94
+ current_driver.stop_machine(action_handler, machine_spec, current_machine_options)
95
+ end
96
+ end
97
+
98
+ action :destroy do
99
+ if current_driver
100
+ current_driver.destroy_machine(action_handler, machine_spec, current_machine_options)
101
+ end
102
+ machine_spec.delete(action_handler)
103
+ end
104
+
105
+ attr_reader :machine_spec
106
+
107
+ def new_driver
108
+ run_context.chef_provisioning.driver_for(new_resource.driver)
109
+ end
110
+
111
+ def current_driver
112
+ if machine_spec.driver_url
113
+ run_context.chef_provisioning.driver_for(machine_spec.driver_url)
114
+ end
115
+ end
116
+
117
+ def from_image_spec
118
+ @from_image_spec ||= begin
119
+ if new_resource.from_image
120
+ chef_managed_entry_store.get!(:machine_image, new_resource.from_image)
121
+ else
122
+ nil
123
+ end
124
+ end
125
+ end
126
+
127
+ def new_machine_options
128
+ machine_options(new_driver)
129
+ end
130
+
131
+ def current_machine_options
132
+ machine_options(current_driver)
133
+ end
134
+
135
+ def machine_options(driver)
136
+ configs = []
137
+
138
+ configs << {
139
+ :convergence_options =>
140
+ [ :chef_server,
141
+ :allow_overwrite_keys,
142
+ :source_key, :source_key_path, :source_key_pass_phrase,
143
+ :private_key_options,
144
+ :ohai_hints,
145
+ :public_key_path, :public_key_format,
146
+ :admin, :validator,
147
+ :chef_config
148
+ ].inject({}) do |result, key|
149
+ result[key] = new_resource.send(key)
150
+ result
151
+ end
152
+ }
153
+
154
+ # The current use case for this is adding a new attribute `aws_tags` to
155
+ # the machine resource from the chef-provisioning-aws driver. Because we
156
+ # want that attribute to work for the recipe DSL, it needs to be added at the
157
+ # Chef::Resource::Machine class level and not at an instance level. Thus we
158
+ # also need to pull the additional_machine_option_keys (:aws_tags) from the
159
+ # Chef::Resource::Machine class level. If you use two drivers (like AWS and
160
+ # Azure) then all machine instances will still have the `aws_tags` attribute
161
+ # DSL and will pass `:aws_tags` in on the machine_options. They can simply
162
+ # be ignored by the Azure driver.
163
+ (self.class.additional_machine_option_keys || []).each do |k|
164
+ configs << { k => new_resource.send(k)} if new_resource.send(k)
165
+ end
166
+
167
+ configs << { from_image: new_resource.from_image } if new_resource.from_image
168
+ configs << new_resource.machine_options if new_resource.machine_options
169
+ configs << driver.config[:machine_options] if driver.config[:machine_options]
170
+ Cheffish::MergedConfig.new(*configs)
171
+ end
172
+
173
+ def self.additional_machine_option_keys
174
+ @@additional_machine_option_keys ||= []
175
+ end
176
+
177
+ def load_current_resource
178
+ if defined?(Chef::Provider::ChefNode)
179
+ # Cheffish 1.x
180
+ node_provider = Chef::Provider::ChefNode.new(new_resource, run_context)
181
+ else
182
+ # Cheffish 2.x
183
+ node_provider = Chef::Resource::ChefNode.action_class.new(new_resource, run_context)
184
+ end
185
+ node_provider.load_current_resource
186
+ json = node_provider.new_json
187
+ json['normal']['chef_provisioning'] = node_provider.current_json['normal']['chef_provisioning']
188
+ @machine_spec = chef_managed_entry_store.new_entry(:machine, new_resource.name, json)
189
+ end
190
+
191
+ def chef_managed_entry_store
192
+ @chef_managed_entry_store ||= Provisioning.chef_managed_entry_store(new_resource.chef_server)
193
+ end
194
+
195
+ def self.upload_files(action_handler, machine, files)
196
+ if files
197
+ files.each_pair do |remote_file, local|
198
+ if local.is_a?(Hash)
199
+ if local[:local_path]
200
+ machine.upload_file(action_handler, local[:local_path], remote_file)
201
+ else
202
+ machine.write_file(action_handler, remote_file, local[:content])
203
+ end
204
+ else
205
+ machine.upload_file(action_handler, local, remote_file)
206
+ end
207
+ end
208
+ end
209
+ end
210
+
211
+ private
212
+
213
+ def upload_files(machine)
214
+ Machine.upload_files(action_handler, machine, new_resource.files)
215
+ end
216
+
217
+ end
218
+ end
219
+ end