chef-provisioning 2.0.0 → 2.0.1

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